Cannot exclude a path from basic auth when using a front controller script
- by Adam Monsen
I have a small PHP/Apache2 web application wherein I'd like to do two seemingly incompatible operations:
Route all requests through a single PHP script (a "front controller", if you will)
Secure everything except API calls with HTTP basic authentication
I can satisfy either requirement just fine in isolation, it's when I try to do both at once that I am blocked. For no good reason I'm trying to accomplish these requirements solely with Apache configuration.
Here are the requirements stated as an example. A GET request for this URL:
http://basic/api/listcars?max=10
should be sent through front.php without requiring basic auth. front.php will get /api/listcars?max=10 and do whatever it needs to with that.
Here's what I think should work. In my /etc/hosts I added
127.0.0.1 basic
and I am using this Apache config:
<Location />
AuthType Basic
AuthName "Home Secure"
AuthUserFile /etc/apache2/passwords
require valid-user
</Location>
<VirtualHost *:80>
ServerName basic
DocumentRoot /var/www/basic
<Directory /var/www/basic>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ /front.php/$1 [QSA,L]
</IfModule>
</Directory>
<Location /api>
Order deny,allow
Allow from all
Satisfy any
</Location>
</VirtualHost>
But I still always get a HTTP 401: Authorization Required response. I can make it work by changing <Location /api> into
<Location ~ /api>
but this allows more than I want to past basic auth.
I also tried changing the <Directory /var/www/basic> section into <Location />, but this doesn't work either (and it results in some strange values for PATH_TRANSLATED being passed to the script).
I searched around and found many examples of selective exclusion of basic auth, but none that also incorporated a front controller.
I could certainly do something like handle basic auth in the front controller, but if I can have Apache do that instead I'll be able to keep all authentication logic out of my PHP code.
A friend suggested splitting this into two vhosts, which I know also works. This used to be two separate vhosts, actually.
I'm using Apache 2.2.22 / PHP 5.3.10 on Ubuntu 12.04.