Reputation: 14554
The main Apache config file comes with rules to block viewing of .htaccess files. I have some other <FilesMatch>
directives of my own. I know these all work, as is.
<FilesMatch "^\.ht">
Require all denied
</FilesMatch>
In the .htaccess
at the root of my website I require authentication:
AuthUserFile /etc/.htpasswd
AuthName "Authorised Access Only"
AuthType Basic
Require valid-user
This works absolutely fine. If I try to view the .htaccess
, for example, I get forbidden. If I try to access any other page of the site, I am prompted to authenticate.
However, I want to use a condition based on my Apache environment variable so that the authentication is only active on my staging environment:
<If "env('ENV_NAME') == 'stag'">
AuthUserFile /etc/.htpasswd
AuthName "Authorised Access Only"
AuthType Basic
Require valid-user
</If>
I also know this works in itself. However, as soon as I add the <If>
statement around the Auth block, all of my <FilesMatch>
statements stop working and it's like the authentication allows all of them to bypassed.
Once I have the <If>
statement and try to view my .htaccess
in the browser, I am asked to authenticate, and then I can view the file.
I want to be able to maintain my conditional authentication based on the environment variable, but still require all the <FilesMatch>
security directives to be honoured.
Upvotes: 1
Views: 1691
Reputation: 785256
The <If>
container changes the order of processing. <If>
containers are merged very late, after the <FilesMatch>
container, so the Require valid-user
essentially overrides the Require all denied
set in Apache config. However, without the <If>
container, the .htaccess
directives are processed early and the <FilesMatch>
container is merged later, overriding the Require valid-user
directive.
However, there is no need to use <if>
directive here for enforcing auth for stag
environment. You can use Apache 2.4 Require
and RequireAny
directives to achieve this:
AuthType Basic
AuthUserFile /etc/.htpasswd
AuthName "Authorised Access Only"
<RequireAny>
Require expr "env('ENV_NAME') != 'stag'"
Require valid-user
</RequireAny>
This will enforce auth only when an env variable ENV_NAME
is not equal to stag
due to presence of RequireAny
block that requires any of the Require
conditions to be true.
Alternatively, you may add another condition in your <If>
expression to make this block execute only for requests that are not starting with /.ht
like this:
<If "%{REQUEST_URI} !~ m#^/\.ht# && env('ENV_NAME') == 'stag'">
AuthUserFile /etc/.htpasswd
AuthName "Authorised Access Only"
AuthType Basic
Require valid-user
</If>
Upvotes: 0
Reputation: 4010
I tried to replace <If>
with Require expr "env('ENV_NAME') != 'stag'"
but the function env
seems to not recognize variables defined by SetEnv
. Only <If>
seems to do so but there are some expression evaluation specificities.
I also tried some combinations of <Require(All|Any|None)>
at different level to finaly make it with a simple AuthMerging And
.
So, my suggestion and answer is to add AuthMerging And
in your .htaccess
Because I'm really not a huge fan of anubhava's answer if you have to duplicate any higher-level logic that you even might not know in the first place in the .htaccess.
EDIT: in fact, it might be a better idea to put AuthMerging And
directly in the <FilesMatch "^\.ht">
block instead of the .htaccess itself.
Upvotes: 1