David Barnes
David Barnes

Reputation: 2148

How to force HTTPS on a directory AND force HTTPS authentication

I am wondering what the best way to force HTTPS authentication is.

When I have this in my .htaccess file:

AuthType Basic
AuthName "Developer"
AuthUserFile /usr/local/etc/apache22/passwords/passwords
Require user david

Authentication works, but it authenticates over port 80, sending the password in the clear.

So I figured I would add a Redirect Rule to redirect all non-HTTPS requests to equivalent HTTPS requests:

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteBase /~david/
RewriteRule ^(.*)$ https://myserver.tld/~david/$1 [R,L]

This also works, but it first authenicates on port 80, then redirects, then authenicates again on port 443. I do NOT want to authenticate on port 80, because the password will be sent in clear text. I have not been able to figure out a good way to redirect immediately to HTTPS, and then authenicate.

The only way I could figure how to do this is by doing this:

AuthType Basic
AuthName "Developer"
AuthUserFile /usr/local/etc/apache22/passwords/passwords
Require user david
ErrorDocument 403 /403.php
SSLRequireSSL

And having a 403.php PHP script on the / of my server:

<?php

header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);

?>

This is the desired behavior. It requires SSL, so when you try to access the directory on port 80, it spits out a custom error document, and that document to redirects the page to HTTPS.

This seems like a kludge. Is there a better way to accomplish this?

Upvotes: 5

Views: 7482

Answers (1)

Dirk-Willem van Gulik
Dirk-Willem van Gulik

Reputation: 7706

So the issue you are having is that your or block right now applies to both the HTTPS and the HTTP case. You need untangle this (well actually - you could also use 'satisfy any' - but that is a bit messy in this case).

An easy to debug/understand approach is to go to a structure like:

<VirtualHost *:80>
   ...
   RewriteRule ^/foo/bar/?(.*)$ https://myserver.tld/foo/bar/$1 [R,L]
   # and to guard against typo's...
   <Directory /foo/bar/>
       deny from all
   </Directory>
</VirtualHost>


<VirtualHost *:443>
   ...
   <Directory /foo/bar/>
       BasicAuth .. etc.
       allow from all
   </Directory>
</VirtualHost>

and take things from there.

Dw.

Upvotes: 13

Related Questions