Score:2

Apache 2.4.51 bypass Basic Auth for specific query string

za flag

I need Basic Auth on my website, except if a specific hash is present in the URL.

AuthUserFile /path/to/.htpasswd
AuthType Basic
AuthName "Dev"

<RequireAny>
    <RequireAll>
        Require expr %{QUERY_STRING} = 'hash=123456'
    </RequireAll>

    Require valid-user
</RequireAny>

Basic Auth works, but authentication is required even if hash=123456 is in the URL. What am I doing wrong?

Update

Here is my entire .htaccess contents.

AuthUserFile /path/to/.htpasswd
AuthType Basic
AuthName "Dev"
Require expr "%{QUERY_STRING} == 'hash=123456'"
Require valid-user

I hit www.example.com/?hash=123456 and it still requires me to authenticate.

Score:2
kz flag
Require expr %{QUERY_STRING} = 'hash=123456'

You would need to enclose the entire expression in double quotes. And it should be == (double equals) for a string comparison, not =.

You also shouldn't need any of the RequireAny and RequireAll containers since RequireAny is the implied default.

So, the following should be sufficient:

AuthUserFile /path/to/.htpasswd
AuthType Basic
AuthName "Dev"
Require expr "%{QUERY_STRING} == 'hash=123456'"
Require valid-user

Note that the above is an exact string comparison. So, if there might be other query string parameters then you will need to use a regex. For example:

Require expr "%{QUERY_STRING} =~ /(^|&)hash=123456($|&)/"

Alternatively, use an <If> expression and only apply the HTTP authentication when hash=123456 does not appear in the query string. For example:

<If "%{QUERY_STRING} !~ /(^|&)hash=123456($|&)/">
    AuthUserFile /path/to/.htpasswd
    AuthType Basic
    AuthName "Dev"
    Require valid-user
</If>
jp flag
Are the double quotes around the expression mandatory? They are missing from most of the examples on the official documentation.
MrUpsidown avatar
za flag
I have tried everything but it still doesn't work. Auth is required even if the hash is in the url.
MrUpsidown avatar
za flag
I have tried this on another web root (same web server) and it works! So there is something funny going on on the web root of the previous website I was trying this on. Got to find out what it is.
MrUpsidown avatar
za flag
I have found the issue. See my own answer. Thanks anyway for the help!
Score:1
jp flag

I would guess that the ' in 'hash=123456' is part of the expression instead of being the quotes as you expect.

For exact match, try:

Require expr "%{QUERY_STRING} == hash=123456"

If you could have other parameters than hash, you might need regular expressions:

Require expr "%{QUERY_STRING} =~ /hash=123456/"

However, that would match someparam=foo&anythinghash=12345678, too. A possible fix for that:

Require expr "%{QUERY_STRING} =~ /(^|&)hash=123456($|&)/"
MrUpsidown avatar
za flag
True for the quotes. I have tried with and without. I have tried all 3 solutions but none worked. 1) 500 Server Error 2) and 3) No error but still asks for authentication. Weird thing is that with solution 2) if I click "cancel" on the credentials popup, the site loads but without CSS/JS.
jp flag
I have updated this based on the hints on the answer from @MrWhite.
MrUpsidown avatar
za flag
Still no luck and I can't figure out what is wrong. I have tried everything, including with and without quotes (produces no error) and various versions of the regex and exact match. It still requires the auth.
Score:0
za flag

I ended up doing the check of the hash in my PHP controller and only added an .htaccess exception based on the Request_URI but even when doing that, I would still get the authentication prompt.

I then understood that my exception was OK but that the specific URI was requesting additional resources such as JS, CSS, fonts and image files that were not on the allowed URI, which is why I would still be required to authenticate.

My goal was that 2 specific URI would be fully accessible without authentication (form/installation and form/vehicules) so this is what I have done:

AuthUserFile /path/to/.htpasswd
AuthType Basic
AuthName "Dev"

SetEnvIf Request_URI ^/(form/installation|form/vehicules) noauth=1
<RequireAny>
  Require env noauth
  Require env REDIRECT_noauth
  Require valid-user
</RequireAny>
<FilesMatch "\.(?i:css|js|svg|otf|png|jpe?g|ico)$">
    Require all granted
</FilesMatch>

Now, both URI are loading without requesting authentication, and with all the needed resources.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.