Basic HTTP authentication in Apache shows the files when I cancel login

Viewed 133

I'm trying to put protection on two pages. However when I click cancel, those pages are displayed. I'm using WordPress, this is the setting in my .htaccess file.

SetEnvIf Request_URI "^/page/page1/$" PAGE1
# use BASIC authentication only when env variable PAGE1 is set
AuthType Basic
Authname "Users zone"
AuthUserFile "/path/to/passwd"
Require valid-user
Satisfy any
Order allow,deny
Allow from all
Deny from env=PAGE1
SetEnvIf Request_URI "^/page/page2/$" PAGE2
# use BASIC authentication only when env variable PAGE2 is set
AuthType Basic
Authname "Users zone"
AuthUserFile "/path/to/passwd"
Require valid-user
Satisfy any
Order allow,deny
Allow from all
Deny from env=PAGE2
1 Answers

The directives as written should work OK, however, there are a number of reasons that could prevent them from working as intended:

  • Conflicts with other auth directives.
  • When the request is rewritten to the WordPress front-controller, the "requested URL" is updated and the environment variables (PAGE1 and PAGE2 in your example) are renamed with a REDIRECT_ prefix, so access is granted on the second pass.
  • You are actually on a LiteSpeed server (that identifies itself as Apache 2.4). Modules are processed in a different order (notably mod_rewrite before mod_auth...) and env vars created in the initial pass are lost after the rewrite to the WP front-controller.

Additional notes:

  • You are using Apache 2.2 auth directives, which are deprecated on Apache 2.4.
  • There doesn't appear to be any requirement to have two separate rule blocks, one for each URL.

We can instead using an Apache <If> expression and check the URL against THE_REQUEST environment variable instead. THE_REQUEST is not updated when the URL is rewritten and this removes the dependency on environment variables (which can be renamed or even removed).

THE_REQUEST contains the entire first line of the request headers and contains a string of the form:

GET /page/page1/ HTTP/1.1

However, THE_REQUEST also contains the query string (if any), so we have to be careful to exclude this in the match, otherwise a user could potentially bypass the authentication simply by appending a query string.

Try the following instead to check both URLs:

<If "%{THE_REQUEST} =~ m#\s(/page/page1/|/page/page2/)(\?|\s)#">
AuthType Basic
Authname "Users zone"
AuthUserFile "/path/to/passwd"
Require valid-user
</If>
Related