Apache 2.2 redirect to SSL *then* do auth (with solution < but is it crap?)
Asked Answered
E

3

7

Seems to be the place for apache so here goes :)

Age old problem: how so I redirect HTTP->HTTPS, then and only if HTTPS, do an auth?

Oh - and I'd like most of it in a single snippet that can be Include-ed in multiple <directory> or <location> blocks, so no virtual host level random path based rewrites...

Well, here's what I have that does seem to work:

In the top of a VirtualHost block

# Set ssl_off environment variable 
RewriteEngine on
RewriteCond %{HTTPS} =on
RewriteRule ^ - [E=ssl]

In the location or directory block

RewriteEngine on
# Case 1 redirect port 80 SSL
RewriteCond %{HTTPS} !=on
RewriteCond %{SERVER_PORT} =80
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [R=301]

AuthType Basic
AuthBasicProvider external
AuthExternal auth_pam
AuthName "My Underpants"
AuthzUnixgroup on
Order Deny,Allow
Deny from all
Allow from env=!ssl
Satisfy any
Require group nice-users

Pluses

All of that bar the Require's can be abstracted out to a snippet file to Include in one line on each location

It fixes forcing SSL and authentication together for each location, so less chance of mistakes

Minuses

Bloody hell, it is hardly intuitive! Might be fragile for all I know...

Is there a better way (not that I've found...)?

Comments would be very welcome on whether that has any serious flaws :)

Aside Life would be so much easier if Apache had a sensible config syntax with a generic

<If expression> </If>

block that could be used anywhere. It has certain special case blocks such as IfModule, and then you have special case conditionals like RewriteCond (which is very hard to grok if you're not used to it).

Cheers,

Tim

Euplastic answered 23/6, 2011 at 17:47 Comment(3)
You mean you do not want to manage on VH for SSL and one for non-SSL?Buettner
There are decent solutions for this problem if you can move to Apache 2.4, see... https://mcmap.net/q/461307/-apache-htaccess-redirect-to-https-before-asking-for-user-authenticationHumor
Possible duplicate of Apache .htaccess redirect to HTTPS before asking for user authenticationSochi
B
3

If you're wanting to force the entire site to https, you can use the VirtualHost directives, and then it's quite simple:

<VirtualHost *:80>
    ServerName example.com

    RedirectMatch (.*) https://example.com$1

</VirtualHost>

<VirtualHost *:443>
    ServerName example.com

    ...
    ...
    ...
</VirtualHost>
Berhley answered 25/6, 2011 at 20:49 Comment(1)
Simple and effective!Cervantez
A
2

Tim Watts' solution seems to work best for me but needed a bit of tweaking. Also my situation is slightly different in that I wish to allow certain IP addresses without HTTP auth but this just adds an extra line.

mod_rewrite won't inherit config from the VirtualHost by default.

See: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriteoptions

I was going to make use of "RewriteOptions inherit" but it seems that this applies the parent rules AFTER the child ones. In any case, I thought of a different solution.

Within my SSL <VirtualHost> I have the line:

SetEnvIf Request_URI "/" using_ssl=yes

This sets the using_ssl environment variable if the request URI contains a forward slash (i.e. all the time.) It's a bit of hack as I'd prefer to use the unconditional SetEnv but apparently:

The internal environment variables set by this directive are set after most early request processing directives are run, such as access control and URI-to-filename mapping. If the environment variable you're setting is meant as input into this early phase of processing such as the RewriteRule directive, you should instead set the environment variable with SetEnvIf.

(source: http://httpd.apache.org/docs/2.2/mod/mod_env.html#setenv)

My config within my container looks like this:

# Require a basic HTTP auth user
AuthName "realm-name-goes-here"
AuthType Basic
AuthUserFile /var/www/etc/htpasswd
Require valid-user

# OR allow from non-SSL (which will be redirected due to mod_rewrite below!)
Order Allow,Deny
Allow from env=!using_ssl

# OR allow from a trusted IP range
# NB: This allows certain IPs without a username & password
Allow from 192.168.0.0/16

Satisfy Any

# Force a redirect to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=permanent]

You probably want to try with just 'R' instead of 'R=permanent' first for testing purposes.

Hope this is useful for others :)

Abel answered 15/12, 2013 at 14:36 Comment(0)
C
-1

I've tested your solution and it didn't work ...

After a loooong time searching the solution, googling too much and found always the same things which didn't work, I finally did this : I use SSLRequireSSL and an ErrorDocument 403 configured with a static page containing a JavaScript code (thanks to this blog page).

in /etc/apache2/conf.d.opt/redirect_if_not_https.conf :

SSLRequireSSL
ErrorDocument 403 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\
<html><head>\
<title>403 Forbidden</title>\
<script language=\"JavaScript\">\
window.location='https://'+window.location.hostname+window.location.pathname;\
</script>\
</head><body>\
<h1>Forbidden</h1>\
<p>You don't have permission to access that resource using simple HTTP. Please use HTTPS instead.</p>\
</body></html>"

(note that I created /etc/apache2/conf.d.opt/)

And in an app conf, include that file (for example in /etc/apache2/conf.d/trac.conf) :

<LocationMatch "/trac">
    # All the classical configurations here
    # ...

    Include conf.d.opt/redirect_if_not_https.conf
</LocationMatch>
Colonnade answered 19/10, 2011 at 14:18 Comment(1)
This didn't work for me. Page still tries to do basic auth on http.Medico

© 2022 - 2024 — McMap. All rights reserved.