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!

Advertisements

33 Responses to “Using WebAuthentication in Jboss”

  1. Murali Says:

    Hi,

    This article is really good and you have explained it beautifully. I am going to try it now and was really hoping to get it worked !!

    Thanks again for this wonderful post.

    ~Murali

  2. Damien Says:

    Hi,

    thanks for this tutorial, the best I found for this subject.
    I try to integrate it in my framework, but I’m blecked since 2 days with an exception “request is null”, while calling “login”:
    WebAuthentication pwl = new WebAuthentication();
    pwl.login(login, password);

    java.lang.IllegalStateException: request is null
    at org.jboss.web.tomcat.security.login.WebAuthentication.login(WebAuthentication.java:80)

    it is thrown by WebAuthentication class :

    public class WebAuthentication

    public boolean login(String username, Object credential)
    {
    //Get the active request
    Request request = (Request) SecurityAssociationValve.activeRequest.get();
    if(request == null)
    throw new IllegalStateException(“request is null”);

    Could it be caused by the jboss 4.2.1 version I use ?
    I don’t see differences between 4.2.1 and 4.2.2 in theses classes…
    Should I configure something in tomcat ?

    thanks,

    Damien

  3. roneiv Says:

    Hi Damien,

    Sorry for not having replied to you earlier.

    I believe that the problem is in the difference of the implementation of the security layer in 4.2.1 and 4.2.2. I haven’t tried to do this witth 4.2.1, but all jboss references I find state that WebAuthentication is available from version 4.2.2 and up..

    Probably your easiest try is to test with the newer version of jboss? 🙂

    – E –

  4. Ritesh Tendulkar Says:

    Damien,

    We faced exactly the same problem as you did on Jboss 4.2.2. We narrowed it down to jbossweb-service.jar in our .war file. You need this file at the compile time for WebAuthentication class but since Jboss already has this in its runtime, this file should be excluded from the war.

    Let me know if that helps.

    Ritesh

  5. Micah Says:

    Ritesh & Damien,

    I’m running into the same problem and I am not including the the WebAuthentication class in my war file. Damien, did you find a resolution to this.

    Thanks.

    Micah

  6. Fer Says:

    Hi, i have the same problem:

    java.lang.IllegalStateException: request is null at org.jboss.web.tomcat.security.login.WebAuthentication.login

    I’m using jBoss 4.2.3

    Thanks,

    Fer.

  7. roneiv Says:

    Fer,

    Are you sure that you’re not including the jbossweb-service.jar in your web-app lib folder? It should not be deployed as part of your application, it already exists in jboss inside the server/deploy/jboss-web.deployer dir.

    Regards,

    Eivind

  8. guybedo Says:

    Hi,

    thanks for this article, it helped me a lot but i’m still facing a problem.
    i have set a custom jsf login webapp at /login that uses the same JAAS security-domain than another webapp deployed at /app2.
    I can succesfully login thanks to the jsf login app but when i’m going to the /app2, it seems that my second app does not see that i’m logged in.
    I’m usins jboss 4.2.3 with webauthentication as shown in the article.
    Have any idea ? thanks.

  9. roneiv Says:

    Guybedo,

    Jboss have said that the support for the single-sign-on valve in combination with the programmatic logon (WebAuthentication) will not work till jboss 5. So I don’t think there are any proper solutions to this problem right now.

    Regards,

    Eivind

    • Osvaldo Pina Says:

      Hi,

      Congratulations, very complete article!
      I’m facing a problem trying to get a jboss-4.2.3 work with WebAuthentication authentication and single sign on (ExtendedSingleSignOn valve). I’m facing a lot of problems in the EJB layer (Authentication Failure Exception) and I’m very woried about the fact that it maybe never work. Could you point me where you find this information about sso and programmatic authentication work only in jb 5?
      Thanks in advance!

      • roneiv Says:

        Hi,

        I myself have used the jboss wiki to aqquire the knowledge I have about jboss programmatic logon and SSO.

        I would suggest you to go here, http://www.jboss.org/community/wiki/WebAuthentication, and maybe you from there can find an answer to your question.

        I see that ExtendedSSO are stated to work also with 4.2.3 now, but I’ve never done this myself – so I can’t help you there..

        Regards,

        Eivind

  10. dalil Says:

    Hi,
    When i tray this webauthentication code I have the following errors:
    17:01:51,106 ERROR [UsersRolesLoginModule] Failed to load users/passwords/role files
    java.io.IOException: No properties file: users.properties or defaults: defaultUsers.properties found
    at org.jboss.security.auth.spi.Util.loadProperties(Util.java:315)
    Can any help me?
    Thanks

  11. roneiv Says:

    Dalil,

    This is because of some problems with your login-config and the security-domain that is set up. Somewhere you have done a mistake, and it tries to load the default login module which is the UsersRolesLoginModule.

    Please check the naming you have used in:
    * jboss-web.xml: The security-domain parameter shold be something like java:/jaas/myPolicyName

    * the login-config.xml: The application-policy name parameter should match the way you spelled it in jboss-web.xml. In this example it would be application-policy name = “myPolicyName”

    And then, if you use a njdi lookup for the database, make sure that in the login-config the dsJndiName is set to match your dataSource configuration. Example: java:/userDb-ds

    Then you would need to have a datasource config in your deploy-dir that matches the jndi name like this:
    userDb-ds

    It can also be a connection problem for the datasource you specified, so verify that you can connect to the db with some other tool using the same parameters.

    Good luck!

  12. Montall Says:

    Situation with “java.lang.IllegalStateException: request is null at org.jboss.web.tomcat.security.login.WebAuthentication.login” occurs when you attempt to execute login in a servlet mapped to “form-login-page”. It looks like SecurityAssociationValve is not activated in this case and that make a problem. Try to execute WebAuthentication.login in some test action which is not bound to a secured resource to avoid side effects.

  13. Lisha Says:

    Hi,

    I am also facing same kind of issue and using Jboss 4.2.3. The server log shows that the correct values are passed for user and password (testuser, testuser123) but i am unable to login. I have the required configuration for JAAS in place.

    Also when i try to print the values using the above helper-methods getRemoteUser and getUserPrincipal, I see “null” in my log. Please help as I am unable to login.

    My server log is as below:

    **CUTTED**

  14. roneiv Says:

    Lisha,

    I would need to see your Jaas configuration (login-config) top be able to help you much. But this is just a wild guess, is the role ‘Roles’ included in your rolesProperties/queries? It’s mandatory for jboss that the group/role of the user is ‘Roles’. If it’s not there, login would fail. 🙂

    As it says on this page: http://www.jboss.org/community/docs/DOC-9511

  15. Jonas Says:

    hi,
    thanks for the article!

    i have the same problem with java.lang.IllegalStateException: request is null @ at org.jboss.web.tomcat.security.login.WebAuthentication.login(WebAuthentication.java:88)
    BUT i am using JBoss 5.0.1.GA.
    the jar file jbossweb-service.jar seems not to be contained in the distribution of jboss 5? so i tried to copy jbossweb-service.jar into my WEB-INF/lib from the jboss-4.2.3GA distribution. but this leads to the described problem.

    has anyone got this working with jboss 5? where to get the jbossweb-service.jar (contains the WebAuthentication class) from and where to put it?

    thanks,
    jonas

    • roneiv Says:

      Jonas,

      I’m running jboss 5.0.1 GA myself – even though I haven’t tested WebAuthentication on this version yet. But I find the jar file in the JBOSS_HOME\server\default\deploy\jbossweb.sar directory. It’s named jboss-web-service.jar, and contains the WebAuthentication class.

      Hope that helps you!

      – E-

  16. Jonas Says:

    update on previous post.
    I like those jboss guys, they are so funny. the jar is RENAMED and located at jboss-5.0.1.GA\server\default\deploy\jbossweb.sar\jboss-web-service.jar (notice the difference: jboss-web-service.jar instead of old jbossweb-service.jar).

    so i removed the jar from the WEB-INF/lib but still the same problem with java.lang.IllegalStateException: request is null

    any help would be really appreciated.
    thx,
    jonas

  17. Mabimal Says:

    Hi Eivind,

    I have pointed portal’s db to oracle.I am trying to point my own DB just for login credentials. and for it i created 3 tables in my DB. I have not used encryption for password in DB.

    The changes i made in jboss portal are
    login-config.xml

    java:/HEUSERDS
    SELECT user_password FROM portal_users WHERE user_uname=?
    SELECT portal_roles.role_name, ‘Roles’ FROM portal_roles_membership INNER JOIN portal_roles ON portal_roles_membership.role_rid = portal_roles.role_rid INNER JOIN portal_users ON portal_roles_membership.user_uid = portal_users.user_uid WHERE portal_users.user_uname=?
    Authenticated

    inside authentication tag.

    The dsJndiName here used is to point my DB(Just for login).

    i have not changed

    jdbc/PortalDS
    java:PortalDS

    in jboss-web.xml of portal-server.war/WEB-INF

    Should i mention jdbc/HEUSERDS here?

    I have added

    LoginServlet
    org.bimal.tryout.LoginServlet

    LoginServlet
    /LoginServlet
    [/code]
    in web.xml of portal-server.war/WEB-INF

    and this LoginServlet have been used as the action of login.jsp of portal-server

    The code of LoginServlet.java is as follows

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    String user = req.getParameter(“j_username”);
    String pass = req.getParameter(“j_password”);
    String baseURL = “/portal/auth/dashboard”;

    String referer = null;
    System.out.println(user);

    WebAuthentication webA = new WebAuthentication();

    if(webA.login(user, pass)){
    System.out.println(user);
    System.out.println(pass);

    System.out.println(“Logged in successfully”);
    System.out.println(req.getRemoteUser() +”\n”+ req.getUserPrincipal());
    referer = req.getHeader(“Referer”);
    System.out.println(referer);
    System.out.println(req.getRemoteUser());
    System.out.println(req.getUserPrincipal());
    resp.sendRedirect(baseURL);
    } else {
    referer = req.getHeader(“Referer”);
    System.out.println(referer);
    resp.sendRedirect(baseURL);
    }
    }

    Here in this code, req.getRemoteUser() and req.getUserPrincipal() are not null and they are returning user. but still i am getting

    HTTP Status 500 – No authenticated user while accessing /portal/auth/dashboard when LoginServlet redirects to /portal/auth/dashboard.

    If i point to /portal it shows user logged in, but dashboard link is not present.
    If the user is with admin role then Admin links appear and it’s fully functional too.

    But what is going on with Dashboard.
    The Dashboard, Configure Dashboard links dont appear.

    One thing to mention is I am using JBoss Portal 2.7.2 bundled edition, which has JBoss AS 4.2.3.

    What might be the solution of it.

  18. Michael D. Says:

    So I got this all working well and good without too much trouble in JBoss 4.2.2.

    A few questions though. Is it expected that you store the WebAuthentication in your servlet request’s Session? If not, do you just store the username and password into the Session, and use those to validate the WebAuthentication on each request, by using a servlet filter? At the end of each request you would want to log out too? ( i.e. webAuthentication.logout() )

    If you use the WebAuthentication would you still want to use the LoginContext through a JAAS mechanism and save that into the Session so you can use that for EJB stuff?

    Now I need to figure out what stuff I could try to backport to get the SSO in JBoss working in JBoss 4.2.2, as it seems it only works properly in JBoss 4.2.3 and higher (http://www.jboss.org/community/wiki/WebAuthentication).

  19. Ondrej Medek Says:

    Hi,

    a small mistake in your last code source:

    String redirectUrl = “”;
    String referer = req.getHeader(“Referer”);
    resp.sendRedirect(redirectUrl);

    I think it should be:

    String referer = req.getHeader(“Referer”);
    resp.sendRedirect(referer);

  20. Ondrej Medek Says:

    Great job! I made a nice login form using ZK framework http://zkoss.org. It works event when the login form is set as a in web.xml/

  21. Tony Burleson Says:

    We are using JBoss 4.3.0 and were hitting our heads against that NPE for both the request and response. In our valve class, I set SecurityAssociationValve.activeRequest.set(request); and
    SecurityAssociationValve.activeResponse.set(response);
    to the ThreadLocal public member variable and it works. This is a hack, but it works.

    I wonder where in the lifecycle this class gets created?

  22. isa Says:

    I m using JBoss 5.1.0 and after configuring everything, i can login fine but for some reason the roles are not copied over.
    request.getUserPrincipal is returning the right value but request.isUserInRole always returns false causing an 403 error for protected page.
    any clue on that issue?

  23. Henk Says:

    I’m using JBoss AS 5.1 and after setting up the configuration for the jboss login module everything seems to work. Request.getUserPrincipal works, request.isCallerInRole works and when I call an EJB right after the login, the corresponding methods on the ejbcontext also return the right roles.

    Only, in a new request the login is forgotten. Is this supposed to happen? I do the login from a very simple hello world ear app, with a simple JSF page having a backing bean where I perform the login. My app only has public pages and I didn’t configure anything in web.xml.

  24. kaizaan Says:

    can you add something more about the roles and how to redirect the user to a specific page according to the role assigned to him?


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: