1 Reply Latest reply on Dec 13, 2008 7:21 PM by jonas123

    Salt being inserted at inconvenient time

      Hi ! I just came up with a problem while authenticating with a Overriden jpaIdentityStore. The point is, I generate the salt to be stored in the UserAccount entity in uppon the JpaIdentityStore.EVENTPREPERSISTUSER event, like this:


      @Name("registrationEvents")
      public class RegistrationEvents {

              @In
              private UserInfo userInfo;     
                     
              @In    
              private IdentityManager identityManager;
             
              @Observer(JpaIdentityStore.EVENT_PRE_PERSIST_USER)     
              public void insertSalt(UserAccount authenticatingUser){
                     
                      authenticatingUser.setUserInfo(userInfo);
                      authenticatingUser.setSalt(generateSalt());
                     
              }                      //...


      Everything works fine, except that when the event occurs the passwordHash for the userAccount has alreadly been generated. So, previously to the EVENT
      PREPERSISTUSER event the generatePasswordHash(password, getUserAccountSalt(user)) in the JpaIdentityStore has alreadly been invoked, ignoring the salt created afterwards.
      Because of this I had to include the salt logic in my overriden JpaIdentityStore like this



      @Name("jpaIdentityStore")
      @Install(precedence = Install.APPLICATION)
      @Scope(ScopeType.APPLICATION)
      @BypassInterceptors
      @Startup
      public class SaltedJpaIdentityStore extends JpaIdentityStore { 
             
              private static final long serialVersionUID = 4480043794776341553L;

              public SaltedJpaIdentityStore() {
                      super();
                      setUserClass(UserAccount.class);
                      setRoleClass(Role.class);
              }      
             
              private String newSalt;
             
              @Override
              protected String getUserAccountSalt(Object user) {             
                      UserAccount userAccount = (UserAccount) user;
                     
                      if(newSalt != null){
                              userAccount.setSalt(newSalt);
                              newSalt = null;
                      }
                     
                      return userAccount.getSalt();
              }
                     
              @Override
              public boolean createUser(String arg0, String arg1, String arg2, String arg3) {                
                      newSalt = generateSalt();
                      return super.createUser(arg0, arg1, arg2, arg3);
              }
             

              private String byteToBase64(byte[] data) {
                      BASE64Encoder endecoder = new BASE64Encoder();
                      return endecoder.encode(data);
              }
             
              private String generateSalt() {
                      SecureRandom random = null;

                      try {
                              random = SecureRandom.getInstance("SHA1PRNG");
                      } catch (NoSuchAlgorithmException e) {
                              throw new PasswordDigestException(e);
                      }

                      byte[] bSalt = new byte[8];
                      random.nextBytes(bSalt);

                      return byteToBase64(bSalt);
              }
             
      }


      I don't supose this is the better way to do it, if anyone has suggestions please reply! Thanks

        • 1. Re: Salt being inserted at inconvenient time

          Oh my god I inserted the wrong formatting sorry(is there any way to erase it?)... I'll rewrite the post:



          Hi ! I just came up with a problem while authenticating with a Overriden jpaIdentityStore. The point is, I generate the salt to be stored in the UserAccount entity in uppon the JpaIdentityStore's Pre Persist event, like this:



          @Name("registrationEvents")
          public class RegistrationEvents {
          
                  @In
               private UserInfo userInfo;     
                    
               @In     
               private IdentityManager identityManager;
               
                  @Observer(JpaIdentityStore.EVENT_PRE_PERSIST_USER)
                  public void insertSalt(UserAccount authenticatingUser){
                    
                    authenticatingUser.setUserInfo(userInfo);
                    authenticatingUser.setSalt(generateSalt());
                    
                }                      //...



          Everything works fine, except that when the event occurs the passwordHash for the userAccount has alreadly been generated. So, previously to the pre persist event the generatePasswordHash(password, getUserAccountSalt(user)) in the JpaIdentityStore has alreadly been invoked, ignoring the salt created afterwards.
          Because of this I had to include the salt logic in my overriden JpaIdentityStore like this


          @Name("jpaIdentityStore")
          @Install(precedence = Install.APPLICATION)
          @Scope(ScopeType.APPLICATION)
          @BypassInterceptors
          @Startup
          public class SaltedJpaIdentityStore extends JpaIdentityStore {     
               
               private static final long serialVersionUID = 4480043794776341553L;
          
               public SaltedJpaIdentityStore() {
                    super();
                    setUserClass(UserAccount.class);
                    setRoleClass(Role.class);
               }     
               
               private String newSalt;
               
               @Override
               protected String getUserAccountSalt(Object user) {          
                    UserAccount userAccount = (UserAccount) user;
                    
                    if(newSalt != null){
                         userAccount.setSalt(newSalt);
                         newSalt = null;
                    }
                    
                    return userAccount.getSalt();
               }
                    
               @Override
               public boolean createUser(String arg0, String arg1, String arg2, String arg3) {               
                    newSalt = generateSalt();
                    return super.createUser(arg0, arg1, arg2, arg3);
               }
               
          
               private String byteToBase64(byte[] data) {
                    BASE64Encoder endecoder = new BASE64Encoder();
                    return endecoder.encode(data);
               }
               
               private String generateSalt() {
                    SecureRandom random = null;
          
                    try {
                         random = SecureRandom.getInstance("SHA1PRNG");
                    } catch (NoSuchAlgorithmException e) {
                         throw new PasswordDigestException(e);
                    }
          
                    byte[] bSalt = new byte[8];
                    random.nextBytes(bSalt);
          
                    return byteToBase64(bSalt);
               }
               
          }



          I don't suppose this is the better way to do it, if anyone has suggestions please reply! Thanks