1 2 Previous Next 15 Replies Latest reply on Apr 5, 2002 10:48 AM by luke_t

    Client Authentication using JAAS and JBoss

    coyner_b

      I have been pondering and attempting to determine an appropriate way for a client GUI application to authenticate a user with JBoss without having to invoke an EJB with security permissions.
      The goal is to:
      1) pop-up a GUI login screen
      2) user enters their user name and password
      3) user clicks "Login" button
      4) user is accepted or denied to the GUI app.

      Now to detail how Step 4 is confusing. I have my client setup to use JAAS and invoke the org.jboss.security.ClientLoginModule. Which, as we all now does not perform any authentication, but rather, binds the credentials with JBoss. Below is my client side auth.conf file.

      clientauth {
      org.jboss.security.ClientLoginModule required;
      };

      Now before I continue I must point out that I am trying to authenticate users against a Database. So this screams out to use org.jboss.security.auth.spi.DatabaseServerLoginModule. Below is an example of my server side auth.conf file. I have left out some things on purpose for this post.

      serverauth {
      org.jboss.security.auth.spi.DatabaseServerLoginModule required
      };

      Okay... I have a unit test that:
      1) logs in the client
      2) accesses an EJB with security restrictions causing JBoss to invoke the DatabaseServerLoginModule
      3) successfully authenticates the user for the unit test

      I am able to successfully authenticate users using the steps described above. That was the easy part. The problem I want to discuss is how a Client GUI app can authenticate a user with JBoss using JAAS without invoking an EJB. The reason is that a GUI application should not allow users access to the GUI until they have been successfully authenticated with the server. I have done tons of Google searches and there does not seem to be any thing relating to this topic. Does any one have a good answer?

      Thanks,
      Brian Coyner

        • 1. Re: Client Authentication using JAAS and JBoss
          jwkaltz

          > The problem I want to discuss is how a Client GUI app
          > can authenticate a user with JBoss using JAAS without
          > invoking an EJB. The reason is that a GUI
          > application should not allow users access to the GUI
          > until they have been successfully authenticated with
          > the server. I have done tons of Google searches and
          > there does not seem to be any thing relating to this
          > topic. Does any one have a good answer?

          The easiest way is to invoke an EJB whose sole purpose is to check your login. It does this implicitly if the bean it protected, it doesn't need to do any business code; you can just have a protected ping so to speak. When the user has entered username and password, call that EJB, if no exception occurs enter your application, if a security exception occurs then authorization has failed.

          • 2. Re: Client Authentication using JAAS and JBoss
            coyner_b

            I actually did do what you are speaking of... but had coined this as a "hack". There has to be some "clever" way to authenticate a user with the server without invoking a no-op method on a secured stateless session bean. One other problem with this approach is the exception returned back to the client; a SecurityException (wrapped in the RemoteException). A SecurityException does not provide any details about the failed login. For example... I believe it says "... Authentication Failed: principal=your_username. This does not provide the client GUI any decent information to tell the user what happened. But what JBoss sees is a real LoginException, thus allowing for more detailed information to be retrieved and logged on the server. Look at the server log ($JBOSS_DIST/log) and you will see a detailed message of the failed login.

            I would assume that most people need the exact functionality I am speaking of, and would like to hear more about their struggles and solutions.

            One solution I was thinking of was writing my own client database login module. Actually I have already tried this but coined this as a "hack" too. The reason why is because I am duplicating functionality that the server (DatabaseServerLoginModule) gives me for "free".

            I know this is what needs to be done...
            clientauth {

            //authenticate with the server
            com.yourcompany.blah.LoginMeIntoTheServerModule
            required;

            //bind the credentials if okay
            org.jboss.security.ClientLoginModule required;
            };

            Any more thoughts?

            Brian Coyner

            • 3. Re: Client Authentication using JAAS and JBoss

              > Any more thoughts?

              Why do you want to use JBoss at all? It seems a bit like overkill to run a J2EE server just to provide authentication for your GUI application.

              If you want to run using a proper authentication protocol, then look at the SRP login module.

              What are you actually trying to secure, and how important is it? If it's only access to the application then that will be easily hackable anyway.

              Also, a client shouldn't be given any more reasons for a failed logon, other than that it failed, so I dont' see why you want to propagate more information.

              Luke.

              • 4. Re: Client Authentication using JAAS and JBoss
                coyner_b

                I am using JBoss because I have an application that is running EJBs.

                Now back to my original question... The point I am trying to make is that JAAS and JBoss provide a very clean, "out of the box" implemenation for authenticating and authorizing users on the server. But what is not currently provided "out of the box" is the ability to authenticate a user with the server (JBoss) from the client without going invoking a no-op secured EJB.

                I am not looking for a complete answer, but rather, some suggestions, ideas, and paths to take to implement such an idea. I am totally capable of creating a solution, but wanted to know what other people are doing.

                Once again... A user should not have access to an application until they have been properly authenticated. This means that the user must have a valid username and password associated with the application. This does not mean that once the user in the application that they have full reign. There would still be role and group based authorization. Unless I am totally crazy this seems logical!

                Brian Coyner

                • 5. Re: Client Authentication using JAAS and JBoss
                  jleech

                  Perhaps your no-op ejb method would seem like less of a hack to you if you named it something like login() .. besides I believe you will need to get something back from JBoss that tells you whether the user is logged in successfully or not.

                  • 6. Re: Client Authentication using JAAS and JBoss
                    coyner_b

                    I actually did name my bean something worthy...

                    public class LoginMgrBean implements SessionBean {
                    public void login() {
                    //no-op
                    }
                    }

                    I still think of this approach as a hack. But I am more than willing to change my mind if others out there do not see this as a hack. So feel free to convince me.

                    Brian

                    • 7. Re: Client Authentication using JAAS and JBoss
                      boris2

                      Well, I don't think it's a hack either.

                      You can name your bean something like Session, and make it into a stateful session bean. That way, a single instance of the bean on the app server corresponds to a single instance of the UI, and their lifetimes are pretty much locked together. Later on, you might want to add further functionality to the Session, e.g. returning the list of all roles granted to the currently logged in user on the app server. You might manage a GUI's ACLs with the help of information served through such Session bean.

                      Also (I'm not 100% sure about this...), I don't think you even need the no-op method. The EJBCreate (home interface's create()) method cannot be invoked without adequate permission, so just creating the bean will cause the authentication/authorization to go through.

                      • 8. Re: Client Authentication using JAAS and JBoss
                        coyner_b

                        Thanks for your idea! I like your idea of the stateful session bean. I have created a UI to manage users, roles, and groups and tied them together with stateless session beans and entity beans. So far so good. I was actually thinking of adding in the concept of a user session for each UI instance, much like you said. So I find this encouraging to know that someone else thinks this too.

                        As for the create method on the Home interface, you are absolutely correct! I just tried it and it works. So a no-op method call is a waste. Thanks!

                        Have you actually implemented a real-world solution using this technique?

                        Brian

                        • 9. Re: Client Authentication using JAAS and JBoss

                          > But what is not currently provided "out of the box" is the ability to authenticate a user with the server
                          >(JBoss) from the client without going invoking a no-op secured EJB.

                          Yes there is. Like I said before - use the SRP login module.

                          • 10. Re: Client Authentication using JAAS and JBoss
                            dannz89

                            I have the same problem.

                            Does it not say in the JBoss book that there is container managed as well as Bean managed security?

                            I tried to migrate a WAR file I was using under Apache/Tomcat to JBoss (2.4.4/Tomcat4.0.1 bundle.)

                            The WAR unpacks fine and the JSP logon page compiles OK. The servlets also start up OK. (The EmbeddedCatalinaServiceSX even says it has 'configured an authenticator of type FORM') which is in line with what's specified in web.xml/logon JSP for the webapp. Now shouldn't the container take over somehow? How do I tell it where/what to authenticate against?

                            When I log on however, I am 'allowed in' to the application regardless of what user/password (or nothing) I enter. Furthermore, even when I put in a user that is valid according to the authenticator module I set up in auth.conf, it doesn't make any difference, the application still thinks I do not have any roles. This suggests to me that my webapp does not know or is not being told about the authenticator I have set up in auth.conf.

                            I tried setting up a <security-domain></security-domain> in standardjboss.xml but that didn't do anything either.

                            Any ideas?

                            Regards,
                            Daniel

                            • 11. Re: Client Authentication using JAAS and JBoss
                              roger01

                              Does the method described in http://main.jboss.org/thread.jsp?forum=49&thread=9264 help answer the original question?

                              Roger

                              • 12. Re: Client Authentication using JAAS and JBoss
                                dannz89

                                I can now log on to the Web app using the FORM based authentication. (I added a jboss.xml with a <security-domani></security-domain> pair and an authenticator in the auth.conf file.

                                I can now not seem to keep a valid HTTP session alive. I can log on and bring up my applet but as soon as I try to call the servlet again, it reports that the session is invalid. The code I am using is (req is the HTTP request sent from my Applet:

                                if (! req.isRequestedSessionIdValid() || req.getRemoteUser() == null || req.getSession(false) == null)
                                {
                                //send session status back or redirect or whatever.
                                ...
                                }

                                • 13. Re: Client Authentication using JAAS and JBoss

                                  If you're calling it from an applet then you'll presumably have to handle the session IDs yourself. How are you doing this (or are you)?

                                  Luke.

                                  • 14. Re: Client Authentication using JAAS and JBoss
                                    dannz89

                                    When the applet makes a call to the servlet using an HTTP message, the servlet before doing anything else checks the validity of the session as described.

                                    If the session is invalid (e.g. timeout due to idleness), the servlet packages up an object array and sends it back as follows:
                                    private void redirectToLogin(HttpServletResponse res, int reason, String message)
                                    throws IOException
                                    {
                                    // Return an object requesting that the BaseApplet redirects to the login page.
                                    //
                                    Object[] messages = {message};

                                    Object[] obj = new Object[3];
                                    obj[0] = new Integer(reason);
                                    obj[1] = messages;
                                    obj[2] = null;

                                    // Write the object back.
                                    //
                                    ObjectOutputStream out = new ObjectOutputStream(res.getOutputStream());
                                    out.writeObject(obj);
                                    out.flush();
                                    out.close();
                                    }

                                    The applet has a standard handling method (overloaded method callServlet()) for the returned object which checks that the session is still valid then returns the object to whatever called it in turn, note the use of the Constants class. This holds (as the name suggests) a bunch of global constants which are really just intetegers in general. INVALID_SESSION is just a number:
                                    public Object callServlet(Properties props, String servletName)
                                    {
                                    URL url = null;
                                    try
                                    {
                                    url = new URL(this.get("code_base") + servletName);
                                    }
                                    catch (Exception e)
                                    {
                                    e.printStackTrace();
                                    }

                                    //This method as you can see is overloaded
                                    //When it gets called here, it just sends an HTTP
                                    //message and gets the returned object (hopefully
                                    //useful data) back.
                                    Object obj = callServlet(props, url);

                                    // See if the session has expired.
                                    // Static data requests do not return session status so an exception will be thrown. Ignore it.
                                    //
                                    try
                                    {
                                    if (((Integer) ((Object[]) obj)[0]).intValue() == Constants.INVALID_SESSION)
                                    {
                                    // Session is old. Redirect back to a page that will trigger the login process.
                                    //
                                    if (Constants.DEBUGGING)
                                    {
                                    System.out.println("Session has expired.");
                                    }

                                    sendError("Your login has timed out. The current action has been cancelled.");
                                    url = new URL(this.get("code_base") + "html/");
                                    ((AppletContext) this.get("applet context")).showDocument(url);
                                    }
                                    else if (((Integer) ((Object[]) obj)[0]).intValue() == Constants.INVALID_VERSION)
                                    {
                                    sendError("This is an old version. Please quit the browser to reload a new version");
                                    }
                                    }
                                    catch (Exception ignore) {}

                                    return obj; //to whatever function asked for it. (It will contain useful data if it didn't hit the invalid session processing.)
                                    }

                                    The handling works but the problem is that after login, the session seems to immediately be invalid. The very first call made by my Applet is 'rejected' because the session has become invalid (i.e. the handling in the Servlet decides this.)

                                    Daniel

                                    1 2 Previous Next