cedivad
cedivad

Reputation: 2644

Apache .htaccess redirect to HTTPS before asking for user authentication

This is my .htaccess:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

AuthUserFile /etc/hi
AuthName "hi"
AuthType Basic
require valid-user

It asks for user authentication using http, meaning that password will be sent in plain text. It will than redirect to the https version and ask the password again.

How can i fix it?

Upvotes: 31

Views: 32105

Answers (9)

Boris Dalstein
Boris Dalstein

Reputation: 7748

Here is the only solution that worked in one of my configurations:

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

<If "%{SERVER_PORT} != '80'">
    AuthUserFile /etc/hi
    AuthName "hi"
    AuthType Basic
    require valid-user
</If>

Notably, this is for an Apache 2.4 over which I have no control (shared hosting). It seems that the %{HTTPS} variable is not defined on this config, and any solution based on SSLRequireSSL generated a 500 Internal Server Error.


(Side note: In case you prefer a 403 Forbidden instead of a 301 Permanent Redirect when serving HTTP requests, use RewriteRule ^(.*)$ - [F,L] instead)

Upvotes: 2

MarkApp
MarkApp

Reputation: 21

None of the above worked for me, but this did. My only concern is if there are certain conditions whereby the auth is not triggered allowing someone access without the credentials. I'm not sure there are, but maybe you bright people may say otherwise.

This code redirects non-www to www and http to https, with .htaccess folder auth.

This is the contents of the htaccess file in the directory you want to protect:

RewriteEngine on
# ensure www.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/foldername/$1 [L,R=301]
# ensure https
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/foldername/$1 [L,R=301]

# Apache 2.4 If
<If "%{HTTPS} == 'on' && %{HTTP_HOST} =~ /www/">
AuthType Basic
AuthName "Protected folder"
AuthUserFile "/home/etc/.htpasswds/public_html/foldername/passwd"
require valid-user
</If>

Upvotes: 2

Molomby
Molomby

Reputation: 6579

If you're running Apache 2.4 you can use configuration sections to solve this quite easily.

Eg...

# Redirect to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

# Authenticate users only when using HTTPS
# Enable for <v2.4
 # SSLRequireSSL
 # ErrorDocument 403 /secure-folder/
# Enable for >v2.4
<If "%{HTTPS} == 'on'">
    AuthType Basic
    AuthName "Special things"
    AuthUserFile /etc/blah.htpasswd
    # Prevent this 'Require' directive from overriding any merged previously
   <IfVersion >= 2.4>
      AuthMerging And
   </IfVersion>
    Require valid-user
# Enable for >v2.4
</If>

Upvotes: 24

Adam
Adam

Reputation: 29019

The checked solution https://stackoverflow.com/a/15940387/2311074 does work on Firefox on Ubuntu 16.04, but it does not work on Firefox on Win 7.

If you want to protect your folder https://yourdomain.com/securefolder then you need to create in that folder a .htaccess with the following content:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

SSLRequireSSL
ErrorDocument 403 https://yourdomain.com/securefolder
AuthType Basic
AuthName "Admin"
AuthUserFile /outside/your/www/folder/.htpasswd
Require user admin Admin

The way it works is that when you are calling the website through http:// instead of https:// it will redirect you to the error page. The trick is to use the correct link with the https:// as your default error page.

Upvotes: 4

lmeurs
lmeurs

Reputation: 16899

Our client's webapp is installed in his webuser directory. Authorisation is handled before mod_rewrite rules (https://serverfault.com/a/443185/253111), and we could not get the accepted answer to work, so mod_rewrite seemed not an option.

Eventually we explicitly required SSL and used the webapp's root over HTTPS as 403 and 404 error documents. So when one visits any page over HTTP (which is unauthorized, hence the 403) or a non existing page (404), he is being redirected to ie. https://DOMAIN.TLD/~WEBUSER/admin.

This is the .htaccess file with some extra info in the comments.

### INFO: Rewrites and redirects are handled after authorisation
### @link https://serverfault.com/a/443185/253111

### INFO: Log out of a HTPASSWD session
### This was not always possible, but Firefox and Chrome seem to end sessions
### when a new one is trying to be using ie.:
### https://logout:[email protected]/~WEBUSER/
### @link http://stackoverflow.com/a/1163884/328272

### FORCE SSL: Explicitly require the SSL certificate of a certain domain to
### disallow unsigned certificates, etc. ErrorDocument commands are used to
### redirect the user to an HTTPS URL.
### @link http://forum.powweb.com/showthread.php?t=61566
SSLOptions +StrictRequire
SSLRequireSSL
SSLRequire  %{HTTP_HOST} eq "DOMAIN.TLD"

### HTPASSWD AUTHENTICATION
AuthUserFile /var/www/vhosts/DOMAIN.TLD/web_users/WEBUSER/.htpasswd
AuthType Basic
AuthName "Hello"
Require valid-user

### ERROR DOCUMENTS: Redirect user in case of a 403 / 404.
ErrorDocument 403 https://DOMAIN.TLD/~WEBUSER/admin
ErrorDocument 404 https://DOMAIN.TLD/~WEBUSER/admin

Upvotes: 2

user3205494
user3205494

Reputation: 307

I'm running Apache 2.2 and none of the above solutions worked for me. I found a workaround for me here. Basically, you need to set SSLRequireSSL and use some script language in the ErrorDocument to forward users to HTTPS. Unfortunately, in my case this only works when accessing particular files on the server, it does NOT work if just the domain is provided. Here is what I did:

AuthType Basic
AuthName "Password Protected Area"
AuthUserFile /my/path/to/.htpasswd
#Require valid-user

<FilesMatch "(^(?!ssl.php).*)">
        SSLRequireSSL
        ErrorDocument 403 /ssl.php
        Require valid-user
</FilesMatch>

The regex in FileMatch tells apache to SSLRequireSSL for all files except ssl.php - and forward the user to ssl.php if he tries to access without SSL.

My ssl.php looks like this:

if(!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == "" || $_SERVER['HTTPS'] == "off")
{
        $redirect = "https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
        header("HTTP/1.1 301 Moved Permanently");
        header("Location: $redirect");
        exit;
}

What now happens:

The last point is what I am not happy with, if someone has a solution for that, I'd be glad to hear about it. Things I tried to solve this issue:

  • Changed the regular expression to (^$)|(^(?!ssl.php).*) to explicitly also match empty strings. Did not work
  • Added a rewrite rule to rewrite an empty string to index.php. Does not work either.

Upvotes: 2

MXW
MXW

Reputation: 129

Thank you very much, Istador!

My Apache is of version 2.2 (Synology NAS DSM 5.1) so these two do not work on it:

RewriteOptions Inherit
IfVersion

After taking them (and the section of version >= 2.4) out. The whole thing began to work for me.

There are a lot suggestions out there for this topic, I spent two days to try them out.

But only this one works for me.

Here's what I did:

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

AuthType Basic
AuthName "private area"
AuthUserFile /path/to/file/.htdigest

Order Deny,Allow
Deny from all
Satisfy Any
Allow from env=!HTTPS
Require valid-user

So it's verified to work on Apache 2.2, Synology DSM 5.1.

Upvotes: 12

Istador
Istador

Reputation: 173

Molomby's solution works in 2.4 and higher, but doesn't work with the current Debian version 2.2.22.

Ben's / Chris Heald's solutions also didn't work for me in 2.2.22, but that was due to a different order/satisfy configuration. These settings have changed with 2.4 and the solution seems to be incompatible with 2.4 and above (the redirect works, but the browser is just displaying an unauthorized error without asking for credentials).

Here is a combination of both solutions that should work for versions below and above 2.4:

RewriteEngine on
RewriteOptions Inherit # rewrite rules from parent directories
RewriteCond %{HTTPS} off
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

AuthType Digest
AuthName "private area"
AuthDigestProvider file
AuthUserFile /path/to/file/.htdigest

<IfVersion < 2.4>
    Order Deny,Allow
    Deny from all
    Satisfy Any # reset this to 'All' in custom <Files> and <Directory> directives that block access
    Allow from env=!HTTPS
    Require valid-user
</IfVersion>
<IfVersion >= 2.4>
    <If "%{HTTPS} == 'on'">
        AuthMerging And
        Require valid-user
    </If>
</IfVersion>

Requirements: mod_rewrite, mod_auth, mod_digest, mod_version

Upvotes: 1

Ben
Ben

Reputation: 252

I get around it this way. Just allow Non-SSL since it will be redirected then require auth once on SSL...

SetEnvIf %{SERVER_PORT} ^80$ IS_NON_SSL

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

AuthUserFile /etc/hi
AuthName "hi"
AuthType Basic
require valid-user
Allow from env=IS_NON_SSL

Upvotes: 17

Related Questions