Apache: how to properly secure a folder

Here’s the scenario: the folder named “secure” contains sensitive data and should be protected by user name and password. To redirect all HTTP requests to HTTPS and enforce basic authentication for the folder, add the following to httpd.conf (etc/apache2/sites-enabled/000-default.conf on Ubuntu):

<Directory /var/www/html/secure>
SSLOptions +StrictRequire
SSLRequireSSL
ErrorDocument 403 /https.php
AuthName 'Enter your user name and password:'
AuthType Basic
AuthUserFile /path/to/.htpasswd
Require valid-user
</Directory>

Create https.php file with this code:

<?php
$path = "https://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
if ( $_SERVER['SERVER_PORT'] != 443) {
    header("Status: 302 Moved\n");
    header("Location: ".$path."\n\n");
}
else {
    header( "Content-type: text/html\n\n");
    echo "<html><body><h1>Access denied</h1></body></html>";
}?>

Make sure https.php is in a directory not protected by authentication, and when you’re done, don’t forget to restart Apache.

Why basic authentication?

Outside of enterprise environments, basic authentication over HTTPS is the only practical option. Digest authentication has less browser support and is only slightly more secure. Basic authentication over HTTP will send the password in the clear, which is probably worse than not having a password at all: many people use the same password for multiple things.

Why not to use rewrites?

Many web sites suggest to add rewrite rules that would automatically redirect all HTTP requests to HTTPS, along the lines of

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Unfortunately, this won’t work with SSLRequireSSL. If the user tries to access http://mysite.com/secure, he will get error 403 Forbidden before the rewrite rules have a chance to kick in. It is possible to remove SSLRequireSSL, but then there is a high risk of accidentally allowing HTTP access and even running basic authentication over HTTP instead of HTTPS, which is totally not something with should do.

So, we replace Apache rewriting rules with a PHP script that essentially does the same thing, and designate it as an error document for 403 Forbidden. HTTPS users get straight through to authentication, while HTTP users are redirect to the error document due to 403 error, and the PHP code in https.php redirects them to HTTPS, nice and sweet.

Leave a Reply

Your email address will not be published. Required fields are marked *