.htaccess basic auth by virtual host? - apache

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.

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.

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>

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

Related

Allow Amazon CDN to bypass HTTP Basic Authentication

I am trying to allow Amazon CDN to access the resources on my password-protected staging site (HTTP Basic Authentication).
This is the code I have in the httpd.conf file for it:
NameVirtualHost *:80
<VirtualHost *:80>
ServerName staging.domain.com
DocumentRoot /var/www/html
<Directory "/var/www/html/">
Options Indexes MultiViews FollowSymLinks
AllowOverride all
AuthName "Development Access"
AuthType Basic
AuthUserFile /path/to/password.htpasswd
Require valid-user
SetEnvIf User-Agent "^Amazon.*" cdn
Order allow,deny
Allow from env=cdn
</Directory>
</Virtualhost>
I'm using SetEnvIf to assign a variable if the user agent is Amazon and then just allowing it, but this is not working. Can somebody please help me out with this one?
the problem is that a valid user is required to get to the content, indifferent of the user agent used.
Give this article in the Apache Manual a read, specifically take a look at the RequireAny bit. That allows you to setup the rules with the complexity you require. Your config code would look something like this.
SetEnvIf User-Agent "^Amazon.*" cdn
<RequireAny>
Require valid-user
Require cdn
</RequireAny>
This only works on Apache 2.4 upwards. On 2.2 you can look at this article in the Apache Wiki and specially to the Satisfy Any directive. Hope this helps.
If you have Apache 2 and possibly the requirement to access the resources with HTTP Auth, this has worked for me:
<Directory /var/www/yourwebdirectory>
SetEnvIf User-Agent "^Amazon.*" cdn
AuthUserFile /etc/apache2/.htpasswd.forthissite
AuthType Basic
AuthName "My Files"
Require valid-user
Order allow,deny
Allow from env=cdn
Satisfy Any
</Directory>

.htaccess not working at all

I've got a file accessible through my web website by typing http://www.mywebsite.com/myfile and the server run on debian.
I'd like to put an authentication with a .htaccess and .htpasswd when trying to access to previous url.
I'm quite new to .htaccess and I tried to configure it with the doc but it doesn't seems to work since when i try nothing change and when i check the error log I've got :
[error] [client IP] client denied by server configuration:
/home/file1/myfile/www/.htaccess
The content of my .htaccess is :
<Directory /home/file1/myfile/www/>
AuthUserFile /home/file1/myfile/.htpasswd
AuthGroupFile /dev/null
AuthName "My authentication"
AuthType Basic
Require valid-user
Otions Indexes FollowSymLinks Multiviews
AllowOverride All
Order allow,deny
allow from all
Redirect permanent /.htaccess http://www.mywebsite.com/myfile
ServerSignature Off
</Directory>
How may I solve this problem please ?
You can't use a <Directory> container in an htaccess file. Remove them so you just have:
AuthUserFile /home/file1/myfile/.htpasswd
AuthGroupFile /dev/null
AuthName "My authentication"
AuthType Basic
Require valid-user
Options Indexes FollowSymLinks Multiviews
AllowOverride All
Order deny,allow
deny from all
Redirect permanent /.htaccess http://www.mywebsite.com/myfile
ServerSignature Off
(you have Otions mispelled)
Also, by looking at your error, it looks as if you were trying to access the htaccess file directly, instead of myfile. It's possible there's extra configuration on the server to deny accessing htaccess files (or all files that start with a .).
It seems that deleting et creating again the user is enough to fix the FTP connexion problem.
I've modified my global apache configuration with the following :
DirectoryIndex index.html index.htm index.xhtml index.php index.txt
ServerName debian.domain.tld
#ServerName localhost
HostnameLookups Off
ServerAdmin myadressemail
UserDir www
UserDir disable root
<Directory />
Options -Indexes FollowSymLinks
AllowOverride All
</Directory>
ServerSignature Off
An now my .htaccess is :
AuthUserFile /home/file1/myfile/.htpasswd
AuthGroupFile /dev/null
AuthName "My authentification"
AuthType Basic
Require user user1
But I still have got no authentication asked, what did I do wrong ?

How to make Basic Auth exclude a rewritten URL

I have a Basic Authentication setup on a development server. It is setup inside my httpd.conf file for the VirtualHost of the website. I've had to set up it to exclude certain directories, which has caused no problems and all works fine.
The issue has been with excluding a URL that has been through my mod_rewrite rules in the .htaccess file. My set up is that I have all URLs going through my index.php file and from there the relevant code is found and ran. I tried adding the URL that I wanted to exclude (/businesses/upload_logo) like I did the others but it still requires authentication. This is what I currently have:
...
<Location />
SetEnvIf Request_URI "/businesses/upload_logo" noauth=1
SetEnvIf Request_URI "/api/.*" noauth=1
AuthType Basic
AuthName "Private"
AuthUserFile ****
Require valid-user
Order deny,allow
Satisfy any
Deny from all
Allow from env=noauth
</Location>
....
I have found questions that are similar to mine here & here but the answers only give me what I'm already trying.
I have thought of possible other solutions as well, but these will be last resort things. I want to see if it's possible the way I'm currently doing it:
Set up the basic auth inside my php code instead
Too much hassle at the moment
Put the authentication in my .htaccess file instead
Didn't want to do this just yet as I only want the authentication to happen on one of 3 servers. I'm aware that I could use some more SetEnvIf HOST ... but I'm looking to see if it can be fixed this way or not first.
The mod_rewrite rule:
...
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php [L,QSA]
Try adding
Allow from env=REDIRECT_noauth
For me something like this works like a charm:
<location />
SetEnvIf Request_URI "/businesses/upload_logo" REDIRECT_noauth=1
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /etc/httpd/passwords/passwords
Order Deny,Allow
Satisfy any
Deny from all
Allow from env=REDIRECT_noauth
Require user yournickname
</location>
based on what you have given it should work, unless there is a conflicting directive somewhere else in your configuration.
i have made a similar working setup , just i have used filesystem path instead of URI
i am adding it here, hoping you may find it useful
<VirtualHost *:8989 >
<IfModule mod_auth_basic.c>
<Directory /var/www/html/vella-8989>
# the auth block
AuthType Basic
AuthName "Please login."
AuthUserFile /var/www/html/vella-8989/.htpasswd
require valid-user
Order Deny,Allow
Satisfy any
Deny from all
Require valid-user
Allow from env=noauth
</Directory>
</IfModule>
# set an environtment variable "noauth" if the request has "/callbacks/"
SetEnvIf Request_URI "/callbacks/" noauth=1
ServerName vella.com
ServerSignature off
</VirtualHost>

How to allow writing to files via Apache and WebDAV

I am having trouble understanding how I can get to edit files on a WebDAV setup. I have set up the Auth correctly, as verified by loads of online tutorials, yet there are some files like .htaccess which I can't edit.
The contents of the VirtualHost setup are
<VirtualHost *:80>
ServerAdmin xxx
ServerName xxx
DocumentRoot /data/www/vhosts/xxx
<Directory /data/www/vhosts/xxx>
Options Indexes MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
<Location />
DAV On
AuthType Basic
AuthName "WebDAV Access"
AuthUserFile /data/www/.htpasswd-webdav
Require valid-user
</Location>
</VirtualHost>
I've generated the correct username in the file too, and I can log in successfully and see all the files. Like I say, the problem is that certain files are unreadable and unwritable, the main culprits being .htaccess and .gitignore.
I have set the permissions on all files to 664 and all folders to 775 and a user:group of xxx:www-data. The reason being that this allows PHP to read/write the files ok, and our remote login user xxx to do the same without permissions issues.
Is there something specific I need to do to allow reading writing to these hidden dot files? I'm completely stumped, as most tutorials I've read are telling me that if I don't set the rights on dot files to root:root then they will be writable. I am using a Mac to connect to the WebDAV service, which runs on Ubuntu, if this makes any difference
Just for clarity, all of the xxx in this question is to hide info.
So it seems that I can allow access to specific files using the below
<Files .htaccess>
order allow,deny
deny from all
</Files>
I forgot that .htaccess files are blocked over HTTP by default.
EDIT:
The final working setup, to make all files writeable in the webdav environment, with Digest secure authentication is:
<VirtualHost *:80>
ServerAdmin xxx
ServerName www.domain.name
DocumentRoot xxx
<Directory xxx>
Options Indexes MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
<FilesMatch "\.(htaccess|php)$">
Order allow,deny
allow from all
ForceType text/plain
</FilesMatch>
<Location />
DAV On
AuthType Digest
AuthName "Webdav Access"
AuthDigestDomain / http://www.domain.name/
AuthDigestProvider file
AuthUserFile /data/www/digest.users
Require valid-user
php_value engine off
</Location>
</VirtualHost>
I hope this helps someone else. It took days to find all this info out on the web.
Also check the permissions of /data/www/ itself. It should be writable for the apache user.

Use HTTP Auth only if accessing a specific domain

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?
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 !.
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>
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>
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).
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/*.