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.