11

I was wondering if it was possible to setup a conditional http basic auth requirement based on the virtual host URL in an .htaccess file.

For example what I want to do is have mysite.com and test.mysite.com run off the same code base in the same directory but password protect test.mysite.com. It would be setup this way so that I wouldn't need to branch my code since my app code can see which vhost/url it's being served from and pick the database to serve content from.

Jon Lin
  • 142,182
  • 29
  • 220
  • 220
user410925
  • 189
  • 1
  • 2
  • 8

3 Answers3

21

You can sort of kludge this by using mod_setenvif along with the mod_auth modules. Use the SetEnvIfNoCase directive to set which host is password protected. You'll need a couple of extra directives to satisfy access:

# Check for the hostname here
SetEnvIfNoCase HOST ^test\.mysite\.com\.?(:80)?$ PROTECTED_HOST

Then inside the Directory block (or just out in the open) you have your auth stuff setup, something like this:

AuthUserFile /var/www/test.mysite.com/htpasswd
AuthType Basic
AuthName "Password Protected"

Now for the require/satisfy stuff:

Order Deny,Allow
Satisfy any
Deny from all
Require valid-user
Allow from env=!PROTECTED_HOST

This will make it so any host that doesn't match ^test\.mysite\.com\.?(:80)?$ will have access without need for auth (Allow from env=!PROTECTED_HOST) but otherwise, we need a valid user (Require valid-user). The Satisfy any ensures that we just need one of the 2, either the Allow or Require.

Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • I am trying to have a conditional case activate but use to test it, but it does not work. Any ideas? .. I'm using: SetEnvIfNoCase Host "dev.example.com" DEV ...and then for the 'dev' case and for the 'regular' site... – DM8 Dec 09 '12 at 11:58
  • @DM8 That's not what [ does](http://httpd.apache.org/docs/2.2/mod/core.html#ifdefine). Those variables are set by the `-D` command line flag. They're not environment variables. – Jon Lin Dec 10 '12 at 02:58
  • hmm, then apart from waiting for my host to upgrade to Apache 2.4 (which has the block...). Is there any way to get the behavior I was hoping for? ... in my searches I found the following article, which seems to indicate there is _no_ way of doing this in Apache 2.2x : http://turboflash.wordpress.com/2010/05/27/apache-environment-variables-visibility-with-setenv-setenvif-and-rewriterule-directives/ – DM8 Dec 13 '12 at 19:27
  • @DM8 No way that I know of, as far as creating a block that gets applied given an environment variable – Jon Lin Dec 13 '12 at 23:24
12

I had problems implementing Jon's solution: Although I am quite familiar with Apache conf and regular expressions, the authentication always fired. From a quick analyzes it looked like the Allow from env=!PROTECTED_HOST line did not kick in.

But I found another solution that actually looks safer to me:

I created two virtual hosts for the two domains pointing to the same document root (which is fully allowed by the way). In one of the vhosts I added the directives for basic auth (directly into the vhost directive block).

Works like a charm. And I have a better feeling that this is really safe - no risk to overlook any details in the regex pattern that would open up the gates for intruders.

<VirtualHost *:80>
    ServerName www.mysite.com
    DocumentRoot "/path/to/common/doc/root"

    <Directory "/path/to/common/doc/root">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

<VirtualHost *:80>
    ServerName protected.mysite.com
    DocumentRoot "/path/to/common/doc/root"

    <Directory "/path/to/common/doc/root">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all

        AuthUserFile /path/to/htpasswd
        AuthName "Password please"
        AuthType Basic
        Require valid-user
    </Directory>
</VirtualHost>
Jpsy
  • 20,077
  • 7
  • 118
  • 115
  • 2
    This is the **right** way to do it. If you need 2 vhosts to be configured differently, then you configure 2 vhosts. The hacky solution with the env var and `satisfy any` should really only be applied if you're hosting doesn't give you access to vhost/server config and you're left with an .htaccess solution. – Jon Lin Jun 15 '12 at 16:29
5

Here's a solution similar to what Jon Lin proposed, but using RewriteCond to check the host name:

RewriteEngine On
RewriteCond %{HTTP_HOST} =protected.hostname.com
RewriteRule ^.*$ - [E=DENY:1]

AuthUserFile /path/to/htpasswd
AuthName "Password please"
AuthType Basic

Order Deny,Allow
Satisfy any
Deny from all
Require valid-user
Allow from env=!DENY