2

I am trying to build a Proxy HTTP Authorisation page using mod_auth_form

My goal is to have a single Auth page in the DocumentRoot directory, then once the user is connected, just Proxy all routes to the "real" application, running on localhost with another port.

I set up my vhost with Auth directives under the root Location :

<VirtualHost *:80> 
    ServerName subdomain.example.com

    DocumentRoot /var/www/subdomain.example.com/web/

    <Location /login.html>
        Order allow,deny
        Allow from all
    </Location>

    <Location />
        SetHandler form-login-handler

        AuthType Form
        AuthName realm
        AuthFormProvider file
        AuthUserFile /var/www/subdomain.example.com/.htpasswd
        AuthFormLoginRequiredLocation "http://subdomain.example.com/login.html"

        require valid-user

        Session On
        SessionCookieName session path=/
        SessionCryptoPassphrase any-secret-passphrase      
    </Location>

    ProxyPass /login.html !
    ProxyPassReverse /login.html !
    ProxyPass / http://localhost:8888
    ProxyPassReverse / http://localhost:8888

    ErrorLog ${APACHE_LOG_DIR}/subdomain.example.com/error.log
    CustomLog ${APACHE_LOG_DIR}/subdomain.example.com/access.log combined
</VirtualHost>

EDIT Everything I needed was to reverse the order of the <Location></Location> directives... And add a special Location for the form handler. Working solution:

<VirtualHost *:80> 
    ServerName subdomain.example.com

    DocumentRoot /var/www/subdomain.example.com/web/

    <Location />
        AuthType Form
        AuthName realm
        AuthFormProvider file
        AuthUserFile /var/www/subdomain.example.com/.htpasswd
        AuthFormLoginRequiredLocation "http://subdomain.example.com/login.html"
        AuthFormLoginSuccessLocation "http://subdomain.example.com/"

        require valid-user

        Session On
        SessionCookieName session path=/
        SessionCryptoPassphrase any-secret-passphrase      
    </Location>

    <Location /login_check.html>
        SetHandler form-login-handler

        AuthType Form
        AuthName realm
        AuthFormProvider file
        AuthUserFile /var/www/subdomain.example.com/.htpasswd
        AuthFormLoginRequiredLocation "http://subdomain.example.com/login.html"
        AuthFormLoginSuccessLocation "http://subdomain.example.com/"

        require valid-user

        Session On
        SessionCookieName session path=/
        SessionCryptoPassphrase any-secret-passphrase      
    </Location>

    <Location /login.html>
        Order allow,deny
        Allow from all
    </Location>

    ProxyPreserveHost On
    ProxyPass /login.html !
    ProxyPassReverse /login.html !
    ProxyPass / http://localhost:8888
    ProxyPassReverse / http://localhost:8888

    ErrorLog ${APACHE_LOG_DIR}/subdomain.example.com/error.log
    CustomLog ${APACHE_LOG_DIR}/subdomain.example.com/access.log combined
</VirtualHost>

When I try to access to subdomain.example.com, I am redirected to subdomain.example.com/login.html (Which is fine!)

The content of this /var/www/subdomain.example.com/web/login.html page:

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8' />
        <meta name='viewport' content='width=device-width' />
        <title>Authentication</title>
    </head>
    <body>
        <form method='POST' action='/login_check.html'>
            <div class='form-group'>
                <label for='httpd_username'>Username</label>
                <input id='http_username' class='form-control' type='text' name='httpd_username' value='' />
            </div>
            <div class='form-group'>
                <label for='httpd_password'>Password</label>
                <input id='httpd_password' class='form-control' type='password' name='httpd_password' value='' />
            </div>
            <div class='form-group'>
                <input class='btn btn-success' type='submit' name='login' value='Login' />
            </div>
        </form>
    </body>
</html>

However, this login.html page is never displayed, I receive a TOO_MANY_REDIRECTS error:

The webpage at http://subdomain.example.com/login.html has resulted in too many redirects.

It seems that this special route has to be "down locked" by the Auth process... But I have no idea how to enable that...

I have tried to add another ErrorDocument 401 /login.html directive, but it did not change anything.

Flo Schild
  • 5,104
  • 4
  • 40
  • 55
  • 1
    You could try mapping `http://localhost:8888` to a subdirectory of your subdomain (e.g. `ProxyPass /proxy/ http://localhost:8888/`) so it won't interfere with your `login.html` — at least as a temporary solution for testing. If that works, you can investigate why the `Location /login.html` doesn't seem to have an effect. (Also, your two parameters to `ProxyPass` should either both have a trailing slash or both have none.) – n.st Jun 08 '15 at 13:41
  • Thanks! Indeed, the subfolder solution works ; Except I finish with a /proxy/ in my URL, which I would prefer to avoid... Is there anyway to avoid it while keeping the subfolder? In an other hand, how can I investigate why my ```````` is not working? (What do you mean with the ProxyPass parameters?) – Flo Schild Jun 08 '15 at 14:23
  • 1
    There should be a way to make your original directory layout work, but I can't say for sure how without testing the whole thing myself. I'd wager a guess that Apache is evaluating the `` blocks in the order it finds them, so the second block would override the first one. Have you tried swapping them? As for the `ProxyPass` parameters: Either have `ProxyPass /monit/ http://localhost:2812/` or `ProxyPass /monit http://localhost:2812`. I'm not entirely sure why, but I used to be unable to access some pages if only one of the parameters had a trailing slash. – n.st Jun 08 '15 at 14:32
  • 1
    You might also want to use the `retry=0` parameter to disable Apache's retry delay when the proxied site is unavailable (otherwise Apache will serve an error page for a minute after you try to access the proxied site while localhost:8888 is down): `ProxyPass / http://localhost:8888/ retry=0` (Check the parameter section of the [ProxyPass documentation](https://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass) for details.) – n.st Jun 08 '15 at 14:39
  • Gosh... It was indeed just a problem of directive order... Putting /login.html at the end solves the problem... I really thought it would have been easier. Thanks a lot!! I'll also check the ````retry=0```` parameter :) – Flo Schild Jun 08 '15 at 14:42
  • Glad to hear it was that simple in the end. :) By the way, instead of editing the solution into your question, you could also post it as answer and mark it as accepted to provide a reference if anyone else should encounter a similar problem. – n.st Jun 08 '15 at 20:46
  • Yep, good idea. If you want to, as the solution comes from you, you can do it and I'll accept it ? Otherwise I'll do it in a few time :) – Flo Schild Jun 09 '15 at 08:34

2 Answers2

2

Apache parses configuration directives in the order it sees them and applies them to the specified location and everything underneath it, so the require valid-user from your <Location /> block overrides the Allow from all from your <Location /login.html> block — you end up requiring authentication to access anything (including login.html), so you start off unauthorized when accessing login.html and are redirected to login.html to log in. There's the loop for you.

n.st
  • 946
  • 12
  • 27
2

I had the same problem using Apache 2.4, but for a different reason. With Apache 2.4+, instead of using:

<Location /login.html>
    Order allow,deny
    Allow from all
</Location>

Use:

<Location /login.html>
    Require all granted
</Location>
Mike Godin
  • 3,727
  • 3
  • 27
  • 29