Properly force SSL with .htaccess, no double authentication

15,659

Solution 1

If you have server-side execution such as php or cgi, then set your ErrorDocument to a file that does not require authentication. This file should redirect the client to the proper location. Apache will set several REDIRECT_ - prefixed environment variables to help you out, and the original environment is preserved -- see http://httpd.apache.org/docs/trunk/custom-error.html.

In your .htaccess, do as your second example above, but make the ErrorDocument an internal document:

SSLOptions +StrictRequire
SSLRequireSSL
SSLRequire %{HTTP_HOST} eq "example.com"
ErrorDocument 403 /err_redirect.php
AuthName "Locked"
AuthUserFile "/home/.htpasswd"
AuthType Basic
require valid-user
<Files /err_redirect.php>
  AuthType none
</Files>

Then, in that error document, send the appropriate HTTP status and Location header. Here's a simple example in php:

<?php
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
?>

Solution 2

This works perfect for what I'm trying to do, I have some PHP based admintools in respective directories under /admin/, in /admin/.htaccess I have listed:

SSLOptions +StrictRequire
SSLRequireSSL
SSLRequire %{HTTP_HOST} eq "www.example.com"
ErrorDocument 403 https://www.example.com/admin/

AuthName "Enter your credentials"
AuthType Basic
AuthUserFile /etc/httpd/passwd/passwordfile
Require user valid-user

when going to non-secure example.com/admin it redirects it to secure example.com/admin, then prompts for authentication.

Solution 3

I had the same issue, and I use this now:

AuthType Basic
AuthName "Protected area"
# your auth provider setup here
Require expr "%{ENV:HTTPS} !~ /on/i"
Require valid-user

RewriteEngine On

# Redirect alias to preferred hostname  
RewriteCond expr "! %{HTTP_HOST} -strmatch '%{SERVER_NAME}'"
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]

# Redirect http:// to https://
RewriteCond expr "%{ENV:HTTPS} !~ /on/i"
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Basically it grants access if http:// is used, but redirects all requests to https:// in this case.

I use "%{ENV:HTTPS} !~ /on/i" because I found some systems (e.g. behind SSL terminating proxies) don't set HTTPS to "off" as apache does with http://, or set it to "on" instead of "On" with https://. I also added the redirect to the SERVER_NAME, in case somebody wants it.

I do not have a certificate for all my legacy aliases, so it is essential to redirect to the default hostname first in this case.

Share:
15,659

Related videos on Youtube

cwd
Author by

cwd

Updated on September 17, 2022

Comments

  • cwd
    cwd over 1 year

    I am trying to force SSL with .htaccess on a shared host. This means there I only have access to .htaccess and not the main VirtualHost configuration. I know you can put a rule in the VirtualHost config file to force SSL which will be picked up there (and acted upon first), preventing double authentication, but I can not get to that.

    Here is the progress I have made:

    Config 1

    This works pretty well but it does force double authentication if you visit http://example.com - once for http and then once for https. Once you are logged in, it automatically redirects http://example.com/page1.html to the https coutnerpart just fine:

    RewriteEngine On
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    
    
    RewriteEngine on
    RewriteCond %{HTTP_HOST} !(^www\.example\.com*)$
    RewriteRule (.*) https://www.example.com$1 [R=301,L]
    
    
    AuthName "Locked"
    AuthUserFile "/home/.htpasswd"
    AuthType Basic
    require valid-user
    

    Config 2

    If I add the following to the top of the file, it works a lot better in that it will switch to SSL before prompting for the password:

    SSLOptions +StrictRequire
    SSLRequireSSL
    SSLRequire %{HTTP_HOST} eq "example.com"
    ErrorDocument 403 https://example.com
    

    It is clever how it will use the SSLRequireSSL option and the ErrorDocument 403 to redirect to the secure version of the site. My only complaint is that if you try to access http://example.com/page1.html, it will redirect to https://example.com/

    So it is forcing SSL without a double-login, but it is not properly forwarding non-SSL resources to their SSL counterparts.

    Regarding the first config, Insyte mentioned "using mod_rewrite to perform a simple redirect is a bit of overkill. Use the Redirect directive instead. It's possible this may even fix your problem, as I believe mod_rewrite rules are some of the last directives to be processed, just before the file is actually grabbed from the filesystem"

    I have not had no such luck on finding a force-ssl config option with the redirect directive and so have been unable to test this theory.

    • Admin
      Admin over 5 years
      Using mod_rewrite to do the HTTP to HTTPS redirection in ".htaccess" does not work as it gets done AFTER authentication. BUT if set in server configs it happens BEFORE. The mod_rewrite can preserve sub-page components of the redirected URL, and does not need the server name and page hardcoded into the rule.
  • Stephen Ostermiller
    Stephen Ostermiller over 7 years
    Clever to use your 403 directive as a redirect
  • xsrf
    xsrf over 5 years
    No... Granting access when http:// is used means that there is no password required and thus is never transmitted.