Using WebAuthentication in Jboss

Hi!

Because of a respone to my blog post Perform programmatic logon I decided to provide a bit more complete example of how to use the jboss WebAuthentication. I will show how to do the logon in two ways, by an action in a handler and
by doing it in a servler. Logging in by executing an action in a handler could be nice in cases where you have a page that is open to the public, but if you log in you get access
to more information or features.

First I provide an example of a login-config that I’ve tested and used successfully with the WebAuthentication method,

<application-policy name = "myApplication">
      <authentication>
      <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required">
        <module-option name = "dsJndiName">java:/myDatasource-ds</module-option>
        <module-option name = "principalsQuery">Select password from user_table where user_name =?</module-option>
        <module-option name = "rolesQuery">Select 'user', 'Roles', 'RoleGroups' from user_table where user_name =?</module-option>
        <module-option name ="hashAlgorithm">md5</module-option>
        <module-option name="hashEncoding">hex</module-option>
        <module-option name="debug">false</module-option>
     </login-module>
     <login-module code="org.jboss.security.ClientLoginModule" flag="required" />
     </authentication>
 </application-policy>

Create a LoginHandler or something similar, with a method login() and two helper-methods getRemoteUser and getUserPrincipal. Something like this:

public class LoginHandler
{

public String login()
{
        WebAuthentication webAuthentication = new WebAuthentication();

        String hardcodedUserName = "user@somewhere.com";
        String hardcodedPassword = "user123";

        if (webAuthentication.login(hardcodedUserName, hardcodedPassword))
        {
           System.out.println("Logged in successfully");;

            log.debug("userPrincipal: " + getUserPrincipal());
            log.debug("remoteUser: " + getRemoteUser());
        }
        else
        {
            log.debug("Login failed");
        }

        return "";
}
public String getUserPrincipal()
{
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        return externalContext.getUserPrincipal() != null ? externalContext.getUserPrincipal().toString() : "null";
}

public String getRemoteUser()
{
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        String remoteUser = externalContext.getRemoteUser();
        return remoteUser;
}

}

For this example we basically hardcode the username/password, and just test if we get login to work. You should of course use a page and navigation-rules or smth similar to set the username/password as properties in the loginHandler.
Then create a simple jsp, but don’t put it inside your protected folder. Create it one level up so that you can access it without being asked to log in.

In this jsp you will have a stupid commandButton, as well as two outputs that displays the remoteUser and userPrincipal:

<f:view >
    <t:document>
    <t:documentHead>
       <f:loadBundle basename="MessageResources" var="messages" />
    </t:documentHead>

    <f:verbatim>
        <body>
    </f:verbatim>
    <h:form>
        <h:panelGrid>
            <h:commandButton value="Login" action="#{loginHandler.login}"></h:commandButton>
            <h:outputText value="User Principal: #{loginHandler.userPrincipal}"></h:outputText>
            <h:outputText value="Remote User: #{loginHandler.remoteUser}"></h:outputText>
        </h:panelGrid>
    </h:form>
    <f:verbatim>
        </body>
    </f:verbatim>
    </t:document>
</f:view>

Now, launch your application by going to this page. You will see that userPrincipal shows “null” and remoteUser is empty. Press the Login button.
When the page reloads it should display your username in both outputTexts. If you check your log or console it should say “Logged in successfully.”
The user is now properly set in the web container. Also, if you now try to change the url to go to one of your protected pages,
you should not be redirected to any login.jsp, but the page should display properly – because you are already logged on.

Then, to do the logon from a servlet there’s really not a big difference. I set up my web.xml to use a FORM-based logon, like this:

<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
     <form-login-page>/login.faces</form-login-page>
     <form-error-page>/loginFailed.faces</form-error-page>
    </form-login-config>
   </login-config>

I also register my LoginServlet in web.xml like this:

<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.test.servlet.LoginServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/LoginServlet</url-pattern>
  </servlet-mapping>

My login.jsp is 99% the same as when using j_security_check, we just point the action to the LoginServlet instead:

<form method="POST" name="loginform" action="${pageContext.request.contextPath}/LoginServlet">
<table style="vertical-align: middle;">
<tr>
<td>Username:</td>
<td><input type="text" name="j_username"/></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="j_password"/></td>
</tr>
<tr>
<td><input type="submit" value="Login" /></td>
</tr>
</table>
</form>

My LoginServlet uses the parameters that was originally passed to the j_security_check. Also, if we successfully log on, we get the “Referer” from the request to redirect to the page that originally was the target for the user. I did not include the code that handles if the logon failed here:

public class LoginServlet extends HttpServlet
{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
        // TODO Auto-generated method stub
        doPost(req, resp);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
        String user = req.getParameter("j_username");
        String pass = req.getParameter("j_password");
        WebAuthentication webAuthentication = new WebAuthentication();
        if(    webAuthentication.login(user, pass))
        {
            String redirectUrl = "";
            String referer = req.getHeader("Referer");
            resp.sendRedirect(redirectUrl);
            return;
        }
        else
        {
            System.out.println("Login attempt failed " + user);
            ...
            Handle incorrect logon, go back to login page etc
            ...
        }
    }
}

So, to test this, start your application by pointing directly to some page that is protected. Your login.jsp should be presented, and when you press Login
the servlet uses the credentials you passed in the forms, authenticates and redirect you to the page.
For debug reasons you could add the same outputTexts here on this page (remoteUser and userPrincipal), and they SHOULD show the user you logged in with now.
There is also no problem to navigate to other protected pages.

Hope that these examples might help anybody that struggles with this!