Apache form based login catch bad credentials

39 Views Asked by At

I have Apache 2.4 (httpd) on Red Hat 9.0. I have basic authentication working with ldap and a custom login form.

My httpd.conf has the following

<Directory /var/www/html/private>
    AuthType Form
    AuthName "Login"
    AuthFormProvider ldap
    AuthFormLoginRequiredLocation "/login.shtml?req=%{REQUEST_URI}"
    AuthLDAPURL "ldap://DC:389/OU=Users,dc=x,dc=com?sAMAccountName?sub?(objectClass=*)"
    Require valid-user
    AuthLDAPBindDN username
    AuthLDAPBindPassword pAsSwOrD
    Session On
    SessionCookieName session path=/
</Directory>


<location "/do-login.html">
    SetHandler form-login-handler
    AuthFormLoginRequiredLocation "badlogin.shtml"
    SetEnvIf Referer ^.*req=(.*)&?$ req=$1
    AuthFormLoginSuccessLocation %{ENV:req}
    AuthFormProvider ldap
    AuthLDAPURL "ldap://DC:389/OU=Users,dc=x,dc=com?sAMAccountName?sub?(objectClass=*)"
    Require valid-user
    AuthLDAPBindDN username
    AuthLDAPBindPassword pAsSwOrD
    AuthType form
    AuthName "Login"
    Session On
    SessionCookieName session path=/
</location>

and I have a basic form in login.html

<form method="POST" action="/do-login.html">
  Username: <input type="text" name="httpd_username" value="" />
  Password: <input type="password" name="httpd_password" value="" />
  <input type="submit" name="login" value="Login" />
</form>

What the <directory> directive does is send you to the page you originally requested after you login via the login.html page.

If you get the credentials wrong, the <location> directive sends you to badlogin.html, which is basically the same as login.html, but it has "BAD CREDS, Try again" in red font.

However if u get the creds correct here, it takes you to do-login.html ... 302 Found .. saying The document has moved <here> .. with 'here' being a hyperlink back to itself. Clicking on that link gives me the message "Method Not Allowed, The requested method GET is not allowed for this URL."

do-login has become the referrer here.

How can I get badlogin.html to send me to a legit page? I guess the original referrer is no longer known, so, /private/index.shtml would be a good enough successLocation.

Before I started to use "?req=%{REQUEST_URI}" and "SetEnvIf Referer" I was just using

AuthFormLoginRequiredLocation "/login.shtml" and AuthFormLoginSuccessLocation "/private/index.shtml"

So no matter what page you originally selected, you always ended up at "/private/index.shtml" after successfully logging in. I don't like that. If you chose /private/pageA.shtml or /private/pageB.shtml, you always ended up at /private/index.shtml. With the above directives, if u choose /private/pageB.shtml, it takes you to /private/pageB.shtml after u login. But not if you make a mistake in the creds, and get them right the next try.

I have tried without success :

AuthFormLoginRequiredLocation "/badlogin.shtml?req=%{REQUEST_URI}"

Perhaps there is a way to conditionally set AuthFormLoginSuccessLocation ?

Just trying to account for the scenario that a user does not get creds correct on the first go.

thanks in advance

1

There are 1 best solutions below

0
On

I solved this issue a few weeks ago, and for anyone interested, I just wanted to post how I did it.

I have the original <directory> directive which sends you to the login.html page for authentication, with the originally requested page attached as %{REQUEST_URI}

<Directory /var/www/html/private>
    AuthType Form
    AuthName "Login"
    AuthFormProvider ldap
    AuthFormLoginRequiredLocation "/login.shtml?req=%{REQUEST_URI}"
    AuthLDAPURL "ldap://DC:389/OU=Users,dc=x,dc=com?sAMAccountName?sub?(objectClass=*)"
    Require valid-user
    AuthLDAPBindDN username
    AuthLDAPBindPassword pAsSwOrD
    Session On
    SessionCookieName session path=/
</Directory>

I then have the original <location> directive, that processes the login.html form. If authentication is correct, you go to the page you originally requested, if not, you go to badlogin.html.

<location "/do-login.html">
    SetHandler form-login-handler
    AuthFormLoginRequiredLocation "badlogin.shtml"
    SetEnvIf Referer ^.*req=(.*)&?$ req=$1
    AuthFormLoginSuccessLocation %{ENV:req}
    AuthFormProvider ldap
    AuthLDAPURL "ldap://DC:389/OU=Users,dc=x,dc=com?sAMAccountName?sub?(objectClass=*)"
    Require valid-user
    AuthLDAPBindDN username
    AuthLDAPBindPassword pAsSwOrD
    AuthType form
    AuthName "Login"
    Session On
    SessionCookieName session path=/
</location>

This directive processes do-login.html, which is not a real page. It is the action in the login.html form.

<form method="POST" action="/do-login.html">

I then added a new <location> directive.

<location "/next-login.html">
    SetHandler form-login-handler
    AuthFormLoginRequiredLocation "badlogin.shtml"
    AuthFormLoginSuccessLocation "/private/index.html"
    AuthFormProvider ldap
    AuthLDAPURL "ldap://DC:389/OU=Users,dc=x,dc=com?sAMAccountName?sub?(objectClass=*)"
    Require valid-user
    AuthLDAPBindDN username
    AuthLDAPBindPassword pAsSwOrD
    AuthType form
    AuthName "Login"
    Session On
    SessionCookieName session path=/
</location>

Previously, I had badlogin.html to be same as login.html, but with "BAD CREDS, Try again" in red font. This is still the case. But I changed the action in the form:

   <form method="POST" action="/next-login.html">

This new directive processes next-login.html. Again, this is not a real page, it is the action from the form in badlogin.html.

If authentication is incorrect, you go back to badlogin.html. If correct, the originally requested page is lost by now, so I make you go to a hard-coded page, in this case, /private/index.html

This works fine for me. If anyone can make the new directive take me to the originally requested page, that would be much appreciated.