Salt being inserted at inconvenient time
jonas123 Dec 13, 2008 7:10 PMHi ! 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 EVENTPREPERSISTUSER 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