12 Replies Latest reply on Oct 7, 2003 3:41 PM by juha

    Can't Change Passwords for Authenticated Users

    cavedan

      Our application initializes a new user by allowing them a single login with a default expired credential. Once they are authenticated with the expired credential, users change their password and continue into the application.

      When the JaasSecurityManager's authentication cache times out they are kicked of the system with a 403 error. Likewise, when I flush the authentication cache and re-authenticate them by invoking isValid in the JaasSecurityManagerService they are given the boot on their next interaction with the system (also a 403).

      I have verified that even after the following operations occur (in this order)

      1) The user's credential is updated in the database
      2) The user's credential is updated in the session
      3) The authentication cache is flushed and updated via JaasSecurityManagerService.isValid()

      the old password is still submitted to the LoginModule (an extention of UserPasswordLoginModule) for authentication on the next attempted access.

      I infer from the following lines in my startup log:

      2003-10-01 13:40:33,123 DEBUG [org.jboss.ejb.StatelessSessionContainer] Begin java:comp/env for EJB: CommandExecutorHome
      2003-10-01 13:40:33,123 DEBUG [org.jboss.ejb.StatelessSessionContainer] TCL: java.net.URLClassLoader@a45435
      2003-10-01 13:40:33,204 DEBUG [org.jboss.ejb.StatelessSessionContainer] Binding resource manager: castorils to JDNI ENC as: jdo/castor
      2003-10-01 13:40:33,204 DEBUG [org.jboss.ejb.StatelessSessionContainer] Binding securityDomain: java:/jaas/ils to JDNI ENC as: security/security-domain
      2003-10-01 13:40:33,204 DEBUG [org.jboss.ejb.StatelessSessionContainer] End java:comp/env for EJB: CommandExecutorHome

      ...

      2003-10-01 13:40:34,986 DEBUG [org.jboss.web.catalina.EmbeddedCatalinaService41] Linking security/securityMgr to JNDI name: java:/jaas/ils

      that both my ejb and the embedded tomcat/catalina servlet container are bound to the same securityManager (and therefore both are looking at the updated cache).

      So, am I flushing the cache at the wrong time, is the password stored at another point in the system that I haven't accounted for, or is there some further step I've not yet taken?

      - Many thanks for your time, Dan

        • 1. Re: Can't Change Passwords for Authenticated Users

          When the users change their password and "continue into the application" do they need to relogin with their new password?

          -- Juha

          • 2. Re: Can't Change Passwords for Authenticated Users
            cavedan

            No. The system attempts to re-authenticate them using the new password and the username submitted in the origninal login.

            • 3. Re: Can't Change Passwords for Authenticated Users

              Ok,

              so you're adding new user to database, then attempting isValid(oldUserName, newPassword), are you then doing SecurityAssociation.setCredential(newPassword) if you correctly authenticate?

              -- Juha

              • 4. Re: Can't Change Passwords for Authenticated Users
                cavedan

                Ah ... no. I do not.

                I had, to this point, been focused primarily on the contents of the authentication cache as the culprit in my problem.

                I am correct then, in inferring that the SecurityAssociation is a persistant object that is not updated or altered by isValid or defaultLogin?

                If so, I suppose I should be able to access and update it by means similar to those used in JaasSecurityRealmMgr...

                Thanks.

                - Dan

                • 5. Re: Can't Change Passwords for Authenticated Users

                  > I am correct then, in inferring that the
                  > SecurityAssociation is a persistant object that is
                  > not updated or altered by isValid or defaultLogin?

                  correct


                  > If so, I suppose I should be able to access and
                  > update it by means similar to those used in
                  > JaasSecurityRealmMgr...

                  check the EJB server side security interceptor implementation, org.jboss.ejb.plugins.SecurityInterceptor.

                  -- Juha

                  • 6. Re: Can't Change Passwords for Authenticated Users
                    cavedan

                    Unfortunately adding this code has not altered my results.

                    Here is the code I'm executing to clear and update the security manager:

                    try
                    {
                    ArrayList servers = MBeanServerFactory.findMBeanServer(null);
                    if (servers.size() != 1)
                    throw new ServiceNotFoundException("Should be exactly one mbean server.");
                    mbeanServer = (MBeanServer) servers.get(0);
                    }
                    catch (Exception e)
                    {
                    // catch any exception from jboss and wrap it in a command exception
                    // so that this manager may be used from within the ILS
                    throw new CommandException(e);
                    }
                    ...
                    String securityDomain = "ils";
                    ObjectName jaasName = new ObjectName("jboss.security:service=JaasSecurityManager");

                    mbeanServer.invoke(jaasName, "flushAuthenticationCache", flushParams, flushSignature);
                    boolean isValid = new Boolean(mbeanServer.invoke(jaasName, "isValid", validParams, validSignature).toString()).booleanValue();
                    System.out.println(">>>>>>>>>>>>>>>> VALIDATION RESULT: " + isValid);
                    if(isValid)
                    {
                    char[] passwordChars = null;

                    if( password != null )
                    passwordChars = password.toCharArray();
                    SecurityAssociation.setPrincipal(user);
                    SecurityAssociation.setCredential(passwordChars);
                    }

                    The code above is currently being executed from the exitPoint of my application. Here is what shows up in the log when I run this:

                    2003-10-02 13:24:02,791 INFO [com.ignite.presentation.servlet.ActionServlet] Complete execute changePasswd for dem181 55A47A08747B525507793BFB0F07F60E time=200ms
                    2003-10-02 13:24:02,801 INFO [STDOUT] >>>>>>>>>> COMMAND EXECUTION HAS CHANGED THE USER'S CREDENTIAL. ATTEMPT TO UPDATE SECURITY MANAGER
                    2003-10-02 13:24:02,841 INFO [STDOUT] >>>>>>>>>>>> INVOKED AUTHENTICATION CACHE MANAGER FOR USER: dem181 WITH CREDENTIAL: xxxxxx
                    2003-10-02 13:24:02,841 INFO [STDOUT] >>>>>>>>>>>>>>>> REMOVING PRINCIPAL: dem181 FROM CACHE: org.jboss.util.TimedCachePolicy@330fb9
                    2003-10-02 13:24:02,881 INFO [STDOUT] >>>>>>>>>>>>>> PASSWORD TO VALIDATE: xxxxxx
                    2003-10-02 13:24:02,881 INFO [STDOUT] >>>>>>>>>>>>>> ENCRYPTED TARGET: dad3a37aa9d50688b5157698acfd7aee
                    2003-10-02 13:24:02,891 INFO [STDOUT] >>>>>>>>>>>>>>>>> INSERTING AUTHENTICATION CACHE ENTRY FOR PRINCIPAL: dem181 WITH CREDENTIAL: org.jboss.security.plugins.JaasSecurityManager$DomainInfo@1b56bda
                    2003-10-02 13:24:02,891 INFO [STDOUT] >>>>>>>>>>>>>>>> VALIDATION RESULT: true
                    2003-10-02 13:24:02,891 INFO [STDOUT] >>>>>>>>>> AUTHENTICATION CACHE AND SECURITY ASSOCIATIONS HAVE BEEN RESET
                    2003-10-02 13:24:03,102 INFO [STDOUT] >>>>>>>>>>>>>> PASSWORD TO VALIDATE: zzzzzz
                    2003-10-02 13:24:03,102 INFO [STDOUT] >>>>>>>>>>>>>> ENCRYPTED TARGET: dad3a37aa9d50688b5157698acfd7aee
                    2003-10-02 13:24:03,102 DEBUG [com.ignite.appserver.security.EncryptedPasswordLoginModule] Bad password for username=dem181
                    2003-10-02 13:24:03,112 DEBUG [org.jboss.security.auth.spi.UsersRolesLoginModule] Bad password for username=dem181
                    2003-10-02 13:24:03,112 DEBUG [org.jboss.security.plugins.JaasSecurityManager.ils] Login failure
                    javax.security.auth.login.FailedLoginException: Password Incorrect/Password Required
                    at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:147)
                    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                    at java.lang.reflect.Method.invoke(Method.java:324)
                    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:675)
                    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:129)
                    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:610)
                    at java.security.AccessController.doPrivileged(Native Method)
                    at javax.security.auth.login.LoginContext.invokeModule(LoginContext.java:607)
                    at javax.security.auth.login.LoginContext.login(LoginContext.java:534)
                    at org.jboss.security.plugins.JaasSecurityManager.defaultLogin(JaasSecurityManager.java:462)
                    at org.jboss.security.plugins.JaasSecurityManager.authenticate(JaasSecurityManager.java:417)
                    at org.jboss.security.plugins.JaasSecurityManager.isValid(JaasSecurityManager.java:244)
                    at org.jboss.security.plugins.JaasSecurityManager.isValid(JaasSecurityManager.java:219)
                    at org.jboss.web.catalina.security.JBossSecurityMgrRealm.authenticate(JBossSecurityMgrRealm.java:291)
                    at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:173)
                    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
                    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
                    at org.apache.catalina.valves.CertificatesValve.invoke(CertificatesValve.java:246)
                    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
                    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
                    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
                    at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2415)
                    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
                    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
                    at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)
                    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
                    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)
                    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
                    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:509)
                    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
                    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
                    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
                    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
                    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invoeNext(StandardPipeline.java:643)
                    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
                    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
                    at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
                    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:594)
                    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:392)
                    at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:565)
                    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:619)
                    at java.lang.Thread.run(Thread.java:536)

                    Note that the new password 'xxxxxx' appears to be inserted into the security manager and yet the old one 'zzzzzz' is submitted for validation on the next attempt at access.

                    Is there something fatally flawed in attempting to perform this operation using only the mbean interface? For that matter is there something fatally flawed in attempting to do this from an environment which is essentially outside the context of an ejb method invocation?

                    Thanks for the contiued aid.

                    - Dan

                    • 7. Re: Can't Change Passwords for Authenticated Users

                      hmm,

                      are you running with separated web container... is your ejb proxy sending the old credentials?

                      -- Juha

                      • 8. Re: Can't Change Passwords for Authenticated Users
                        cavedan

                        No, I am running the embedded catalina service.

                        As near as I can tell the old credential is retained in catalina's session facade in a field named org.apache.catalina.authenticator.Constants.SESS_PASSWORD_NOTE.

                        The org.apache.catalina.authenticator.FormAuthenticator retrieves this value and submits it to JbossSecurityManagerRealm and its all downhill from there.

                        I haven't found a good mechanism for updating this value, turning off the caching mechanism that retains it, or otherwise getting around it.

                        - Dan

                        • 9. Re: Can't Change Passwords for Authenticated Users

                          Thanks for the update.

                          I don't have an idea how to hook into Tomcat's side of the security implementation either :-/

                          You could try on tomcat lists, perhaps they have an answer.

                          -- Juha

                          • 10. Re: Can't Change Passwords for Authenticated Users
                            cavedan

                            For those who might be following this thread or those who find it in later days and to whom it is of interest here is my 'final' resolution:

                            Per the Apache Tomcat web site( http://jakarta.apache.org/tomcat/tomcat-4.1-doc/realm-howto.html ):

                            Once a user has been authenticated, the user (and his or her associated roles) are cached within Tomcat for the duration of the user's login. (For FORM-based authentication, that means until the session times out or is invalidated; for BASIC authentication, that means until the user closes their browser). Any changes to the database information for an already authenticated user will not be reflected until the next time that user logs on again.

                            What this means to users of FORM-BASED authentication on Tomcat, of course, is that when the Jboss security manager hits its defaultCacheTimeout interval, any user who has changed their credential during their session will no longer be authenticated, and, since the incoming credential to jboss must come from the servlet container's cache, the user cannot be re-authenticated within the session. Tough beans.

                            I suppose one could hack tomcat if one wanted to, but that someone isn't me.

                            Preliminary testing has shown that this might also be the case with Jetty, but Jetty might have an updatable cache. I don't know.

                            For my application it is not a huge deal to simply bump up the defaultCacheTimeout a bit (to 75 min), so that is what we have done. In the future we might force a re-login after the password change to improve cache/database synchronization, but as far as I can tell, these are the only two ways to maintain synchronization between the credentials stored in the servlet container cache, the security manager cache, and the datasource.

                            Juha, once again, many thanks for your input during my work on this issue.

                            - Dan

                            • 11. Re: Can't Change Passwords for Authenticated Users

                              I've forwarded this to Remy so he might consider this for Tomcat 5 release.

                              -- Juha

                              • 12. Re: Can't Change Passwords for Authenticated Users

                                I've forwarded this to Remy so he might consider this for Tomcat 5 release.

                                -- Juha