15

I've got several sites: example.com, example1.com, and example2.com. All of them point to my server's /public_html folder, which is my Apache root folder.

What do I need to add to my .htaccess file to use http authentication only if the user is coming from example2.com? example.com and example1.com should NOT use authentication.

I know I need something like

AuthType Basic
AuthName "Password Required"
AuthUserFile "/path/to/.htpasswd"
Require valid-user

But I only want to require a password if the user is visiting example2.com.

Edit

Using an approach suggested in an answer, I have the following in my .htaccess file:

SetEnvIfNoCase Host ^(.*)$ testauth
<IfDefine testauth>
RewriteRule ^(.*)$ index2.php?q=$1 [L,QSA]
</IfDefine>

I know that the mod_setenvif.c module is enabled (I verified with an <IfModule> block), but it would appear that "testauth" is never getting defined, because my test to verify (redirecting to index2.php) is not executing (whereas it was getting executed in my <IfModule> block). Any ideas why?

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • If all domains are pointing to the same place, why would you want to protect only one of them? If you actually serve different content, why not have a saner approach like one folder per domain? – Vinko Vrsalovic Aug 31 '09 at 21:39
  • I'm running a multisite Drupal installation out of my /public_html folder, and I want to create a blanket http auth over one of the sites, in addition to that site's normal user login. – Dave DeLong Aug 31 '09 at 21:42
  • Drupal's multisite allows me to run different websites off the same set of PHP files, but with different databases (so different content). I could do a second installation in a subfolder, but that would require me to maintain to distinct sets of files and modules. – Dave DeLong Aug 31 '09 at 21:44
  • According to the documentation http://httpd.apache.org/docs/2.2/mod/core.html#ifdefine , IfDefine is processed at startup. – Colin 't Hart Jul 25 '12 at 08:38
  • ifDefine doesn't work with internal environment variables set by setenv or setenvif, only -D flags at server startup – covener Jul 25 '12 at 13:10

5 Answers5

25

How about something along the lines of this in the htaccess file in the document root:

# set the "require_auth" var if Host ends with "example2.com"
SetEnvIfNoCase Host example2\.com$ require_auth=true

# Auth stuff
AuthUserFile /var/www/htpasswd
AuthName "Password Protected"
AuthType Basic

# Setup a deny/allow
Order Deny,Allow
# Deny from everyone
Deny from all
# except if either of these are satisfied
Satisfy any
# 1. a valid authenticated user
Require valid-user
# or 2. the "require_auth" var is NOT set
Allow from env=!require_auth

This will make it so authentication is not required unless the host ends with example2.com (e.g. www.example2.com, dev.example2.com, etc). The expression can be tweaked if needed. Any other host will cause the require_auth var not to get set so authentication is not required. If this needs to be the other way around, the last line could be changed to: Allow from env=require_auth, removing the !.

James Wong
  • 4,529
  • 4
  • 48
  • 65
Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • 4
    For me !require_auth doesn't work, but this does: Allow from all Deny from env=require_auth Require valid-user Satisfy any – Maxim Krizhanovsky Apr 24 '14 at 13:58
  • Thank you very much – ononononon Jul 13 '16 at 19:27
  • afaik users might be able to exploit this by requesting "example2.com." (notice the dot at the end). So your rule should rather be `SetEnvIfNoCase Host example2\.com\.?$ ...` otherwise the content might be still visible without protection. – Matteo B. Jul 28 '17 at 15:37
  • I rolled back the change, the approach @MaximKrizhanovsky suggested does not work under my testing scenario but the original answer did. – James Wong Aug 09 '18 at 05:39
21

Apache 2.4 offers a semantic alternative with the If directive:

<If "req('Host') == 'example2.com'">
    AuthUserFile /path/to/htpasswd
    AuthType Basic
    AuthName "Password Protected"
    Require valid-user
</If>
<Else>
    Require all granted
</Else>
rebroken
  • 603
  • 4
  • 9
5

Here is one recommendation:

Create a file called common.conf and save in an accessible location

In this file place the Apache configuration common to all sites (hosts).

The remove the current single VirtualHost entry an replace with VirtualHost entries as follows:

# These are the password protected hosts
<VirtualHost *:80>
ServerName example.com
ServerAlias example1.com

Include /path-to-common-configuration/common.conf

AuthType Basic
AuthName "Password Required"
AuthUserFile "/path/to/.htpasswd"
Require valid-user
</VirtualHost>

# These are hosts not requiring authentication
<VirtualHost *:80>
ServerName example2.com
ServerAlias example3.com

Include /path-to-common-configuration/common.conf

</VirtualHost>
William Greenly
  • 3,914
  • 20
  • 18
2

I wonder if DanH would be helped by an approach that allows access per IP address?

Something like

SetEnvIf Remote_Addr 1\.2\.3\.4 AllowMeIn
SetEnvIfNoCase Host this\.host\.is\.ok\.com AllowMeIn
SetEnvIfNoCase Host this\.host\.is\.also\.ok\.com AllowMeIn

and then in your Drupal "container"

Order Allow,Deny
Allow from env=AllowMeIn

should do the trick.

Any host that is "live" should be configured to "AllowMeIn", or else you have to come from a known IP address (ie you and other developers).

Colin 't Hart
  • 7,372
  • 3
  • 28
  • 51
1

You shouldn't be putting per-vhost configuration into .htaccess. Instead, put the config block in the VirtualHost block in the proper config file in /etc/apache/sites-enabled/*.

Martin v. Löwis
  • 124,830
  • 17
  • 198
  • 235
  • I don't have access to the vhost files, unfortunately. I'm running all this on a shared hosting server through CPanel. =( – Dave DeLong Aug 31 '09 at 22:07