1 Reply Latest reply on Nov 17, 2010 7:33 PM by wcone

    Cached JAAS Login Credentials Problem

    wcone

      I'm running JBoss 5.1.0.GA.  I have a Swing client app that is authenticating and making calls on some EJB3 stateless session beans.  The client app is performing a JAAS login using LoginContext configured for the org.jboss.security.ClientLoginModule.  The SLSB is configured to use a security domain that authenticates with a DatabaseServerLoginModule.

       

      I have no problem logging in.  However, if I login as USER1, then logout, then login as USER2, the server authenticates me as USER1 for both logins.  It seems to be caching the login credentials, somewhere.  After some reading on the Wiki, I made sure my DatabaseServerLoginModule is not configured for password-stacking=useFirstPass.  I also found the Wiki page on caching login credentials.  I'd rather not completely disable caching, but I saw the section on flushing specific credentials, so I thought that would solve my problem.  I wrote some code to programmatically remove the specified user from the cache using the JaasSecurityManager MBean.  That code works: it removes the principal from the domain's cached list.  However, removing the principal from there doesn't solve the problem, so that must not be the only place the credentials are being cached.

       

      At the moment, I'm at a loss.  Anyone seen this before or have some tips on what I should look for?

       

       

      {quote:title=Client App's auth.conf}

      swing-client {    org.jboss.security.ClientLoginModule  required; };

      {quote}

       

       

      The Client App's Login Approach

       

      {code:java}

      LoginContext lc = new LoginContext("swing-client", this);

      lc.login();

      try {

         MyBeanRemote bean = (MyBeanRemote) new InitialContext().lookup("MyApp/MyBean/remote");

         String hello = bean.sayHello();

         JOptionPane.showMessageDialog(this, hello);

         bean.invalidate(); // flushes the server's credential cache  

      } finally {

         lc.logout();

      }

      {code}

       

       

      aplus-

      client {

         org.jboss.security.ClientLoginModule  required;
      };

       

       

      The CallbackHandler.handle() Approach

       

      {code:java}

      public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

         LoginDialog loginDialog = new LoginDialog(this, true);

         loginDialog.setVisible(true);

         if (loginDialog.isOkPressed()) {

            for (Callback callback : callbacks) {

               if (callback instanceof NameCallback)

                  ((NameCallback)callback).setName(loginDialog.getUserName());

               else if (callback instanceof PasswordCallback)

                  ((PasswordCallback)callback).setPassword(loginDialog.getPassword());

               else

                  throw new UnsupportedCallbackException(callback, "Unsupported callback");

            }

         } else {

            loginCanceled();

         }

      }

      {code}

       

       

      The Server's application policy from the login-conf.xml file

       

      {code:xml}

        <application-policy name="myapp-domain">      <authentication>         <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">            <module-option name="unauthenticatedIdentity">guest</module-option>            <module-option name="dsJndiName">java:/myappds</module-option>            <module-option name="principalsQuery">select user_pass from myapp_user where user_name = ?</module-option>            <module-option name="rolesQuery">select role_name, 'Roles' from myapp_user_role where user_name = ?</module-option>            <module-option name="hashAlgorithm">SHA-1</module-option>            <module-option name="hashEncoding">base64</module-option>         </login-module>       </authentication>    </application-policy>

      {code}

       

      The Server's SLSB Approach:

       

      {code:java}

      @Stateless

      @SecurityDomain("myapp-domain")

      public class MyBean implements MyBeanLocal, MyBeanRemote {

       

         public String sayHello() {

            String user = context.getCallerPrincipal().getName();

            return String.format("Hello, %s", user);

         }

       

         public void invalidate() {

            Principal user = context.getCallerPrincipal();       String userName = null;       try {          String domain = "myapp-domain";          userName = user.getName();          ObjectName jaasMgr = new ObjectName("jboss.security:service=JaasSecurityManager");          Object[] params = {domain, user};          String[] signature = {"java.lang.String", Principal.class.getName()};          MBeanServer server = (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0);          server.invoke(jaasMgr, "flushAuthenticationCache", params, signature);       } catch (Exception e) {          String msg = String.format("Server error flushing %s from the authentication cache", userName);          throw new EJBException(msg, e);       }

         }

       

         @Resource

         private SessionContext context;

      }

      {code}

        • 1. Re: Cached JAAS Login Credentials Problem
          wcone

          Argh!  I knew I must have been missing something obvious, and unfortunately my (simplified) sample code, above, completely removed the source the the problem.  I've created a LoginContext and called login() from the main thread, but since this is a Swing app, I'm making the EJB calls from a background thread.  That's when the issue comes up.

           

          So I need to make sure the security context of the background thread matches that of the main thread.  What is the best practice for doing this?  I suppose I could create another LoginContext in the background thread and call login() and logout() on it.  Better options?