How to use SetEnvIf with Request_URI when it is rewritten to index.php?

12.2k views Asked by At

We have a drupal website a.com that is password protected. I want all a.com/api/... URIs not to be, though. So I've read about SetEnvIf:

AuthName "Stage"
AuthType Basic
AuthUserFile ~/.htpasswd
SetEnvIf Request_URI ".*data_sheets.*\.pdf" noauth
SetEnvIf Request_URI "/api/.+" noauth
SetEnvIfNoCase Request_Method OPTIONS noauth
Order Deny,Allow
Deny from all
Require valid-user
Allow from env=noauth
Satisfy Any

The /api/foobar URIs are still asking for a password though. Since it's a Drupal website, with the help of anubhava we figured it has to do with how the request is handled by index.php.

How to deal with that?

Edit

Adding

RewriteCond %{REQUEST_URI} ^/api/ [NC]
RewriteRule ^ - [E=noauth]

right after

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]

didnt help

3

There are 3 answers

3
Dusan Bajic On

This works for me:

AuthName "Stage"
AuthType Basic
AuthUserFile /var/www/html/.htpasswd
SetEnvIf Request_URI ".*data_sheets.*\.pdf" noauth
SetEnvIf Request_URI "/api/.+" noauth
SetEnvIfNoCase Request_Method OPTIONS noauth

RewriteEngine On
RewriteCond %{THE_REQUEST} \s/api/
RewriteRule ^ - [E=noauth:1]

Order Deny,Allow
Deny from all
Require valid-user
Allow from env=noauth
Allow from env=rewritten
Satisfy Any

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ /index.html [L]
0
Daniel On

I’m two years late but I’ve worked out a thorough explanation of what’s going on and how you can work around it. The short version:

RewriteRule is fulfilled by a subrequest. The SetEnvIf module doesn’t inherit the REQUEST_URI variable in subrequests. Your noauth variable ends up as undefined in these subrequests.

Use <Location> and <LocationMatch> blocks together with mod_core’s SetEnv instead of relying on mod_setenvif.

2
anubhava On

I am visiting this question after 3 years for some reason and attempting to post a working solution that should work in any Apache version.

You may try these rules in your site root .htaccess with Drupal rules:

DirectoryIndex index.php
RewriteEngine on

# remove /index.php from URLs
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteCond %{REQUEST_URI} ^(.*/)index\.php$ [NC]
RewriteRule ^ %1 [L,R=301,NE]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]

# allow anything that starts with /api/
SetEnvIfNoCase Request_URI ^/api/ noauth

<FilesMatch "^(?!index\.php$).*$">
   AuthType Basic
   AuthName "Stage"
   AuthUserFile ~/.htpasswd
   Require valid-user
   Order   Deny,Allow
   Deny from  all
   Allow from env=noauth
   Satisfy any
</FilesMatch>