2 Replies Latest reply on Feb 4, 2009 1:53 PM by raimundhoelle

    Password aging (password expiration)

    raimundhoelle

      Hello,


      we need to implement a strategy for password aging: if users try to authenticate and their password is to old, they should be directed to the password change page prior they can login.


      I've tried that by extending LdapIdentityStore.authenticate() to throw a PasswordExpiredException and defining an appropriate redirection in pages.xml (like NotLoggedInException).


      Unfortunately this don't work because SeamLoginModule swallows all Exceptions.


      Which other possibilites for implementing that exists?


      Many thanks,
      Raimund


      P. S.: Using Seam 2.1 IdentityManager

        • 1. Re: Password aging (password expiration)
          raimundhoelle

          Now i've found a solution by extending the Identity component.
          Maybe it is interesting for others.


          1. The extended permission store writes the needed information (e. g. passwordExpirationDate) to a new, session scoped component AccountInfo:



          class ExtendedLdapIdentityStore extends LdapIdentityStore {
            ...
            @Override
            public boolean authenticate(String userName, String password) {
              ...
              AccountInfo accountInfo = AccountInfo.instance();
              if (accountInfo != null) {
                ... store additional user info, e. g. Address, Email ...
                ...
                Date passwordExpirationDate = ... get from LDAP-DB ...
                accountInfo.setPasswordExpiredDate( passwordExpirationDate );
              }
              ...
            }
          }
          



          2. Overriding Identity.postAuthenticate():


          ...
          @Install(precedence = Install.FRAMEWORK, classDependencies = "my.own.security.AccountInfo")  
          class ExtendedIdentity extends Identity {
            ...   
            @Override
            protected void postAuthenticate() {
              AccountInfo accountInfo = AccountInfo.instance();
              if (accountInfo != null
                  && accountInfo.getPasswordExpirationDate() != null
                  && accountInfo.getPasswordExpirationDate().before(new Date()) ) {
                if (Events.exists()) Events.instance().raiseEvent(EVENT_PASSWORD_EXPIRED);
                throw new PasswordExpiredException("Password expired");
              }
              super.postAuthenticate();
            }
          }
          



          3. Now i can redirect the user to the password change page:



          components.xml:



             <event type="my.own.security.passwordExpired">
                <action execute="#{redirect.captureCurrentView}"/>
             </event>
             <event type="omy.own.security.passwordChanged">
                <action execute="#{redirect.returnToCapturedView}"/>
             </event>
          



          pages.xml:


             <exception class="my.own.security.PasswordExpiredException">
                <redirect view-id="/error.xhtml">
                  <message>Ihr Passwort ist abgelaufen, sie m&#xfc;ssen es wechseln.</message>
                </redirect>
              </exception>
          




          Note: the user isn't authorized yet, so it is needed to get the actual password together with the new one and authenticate the user first. Unfortunately, the IdentityManager do not support this and identity.login() is not useable while the password is expired.


          My solution is to store the actual password in credentials.password and perform the authentification directly in ExtendedLdapIdentityStore.changePassword().



          Regards,
          Raimund

          • 2. Re: Password aging (password expiration)
            raimundhoelle

            Sorry, pages.xml has to look like that, of course:


               <exception class="my.own.security.PasswordExpiredException">
                  <redirect view-id="/change_password.xhtml">
                    <message>Your password is expired. You have to change it.</message>
                  </redirect>
                </exception>