As it is explained in the documentation, you can annotate your password with
You could also use
@UserPassword(hash = "md5")
public String getPasswordHash() { return passwordHash; }
public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
hash= "none"which doesnt hash the password which is what I did at first. The reason why I didnt start using md5 at once is because you needed a default username and password to be able to log into your seam application. And since I was using an import.sql script that created a default user for me, I had no way of knowing how to hash the password.
So what I needed to do is manually somehow hash a password which I could put in my import.sql script, so that I could enable hashing and correctly log in to my seam application. However this was easier said then done.
I tried changing the @UserPassword(hash="md5") and try to log in, but for obvious reason the login failed, because it was expecting a hashed password.
So then I got the idea to call a method that doesn't require login, which creates a user for us, that is called from a button in the login page. However when I persisted the user, the password was saved as clear text. This baffled me, because I thought that seam would handle that automatically. But if you actually look at the user entity and the setHashPassword method, it is not annotated, and it only sets a string. So it was obvious it only persisted the password as string.
In Seam you can also use IdentityManager to create a user for you. This will perform the hashing for you. So I tried to call
identityManager.createUser("username","password","firstname","lastname");
However, identityManager requires that you are correctly Authenticated, and it threw an exception
org.jboss.seam.security.AuthorizationException: Authorization check failed for permission seam.user,create
So apparently IdentityManager requires the correct permissions, which must be set in your drools setting in security.drl, but I didn't want to do that, since that is not how I wanted to configure my seam application.
So what I did, was look in the seam source and IdentityManager class and find the exact code that performs the hashing for us, and do that manually. And this worked great. Here is the source.
public String saveProcessUser() {
// Check if a new password has been entered
if (currentUser.getPasswordHash() != null && !"".equals(currentUser.getPasswordHash())) {
if (!currentUser.getPasswordHash().equals(passwordVerify)) {
StatusMessages.instance().addFromResourceBundle("admin.wrongPassword");
return "failure";
}
}
// If passwordVerify is not empty, it generally means its a new password
if (!passwordVerify.equals("")) {
String hashPass = generatePasswordHash(currentUser.getPasswordHash(), currentUser.getUsername());
log.debug("Setting new hash password: " + hashPass);
currentUser.setPasswordHash(hashPass);
}
if (getCurrentUser().getId() != null) {
entityManager.flush();
} else {
entityManager.persist(currentUser);
}
FacesMessages.instance().addToControlFromResourceBundle("successMessage", "admin.user.saved");
return "success";
}
/**
* This method will generate a hash password
*
* @param password - The password in cleartext
* @param salt - The username is used as salt
* @return - hash password based on password and username
*/
private String generatePasswordHash(String password, String salt) {
AnnotatedBeanProperty<UserPassword> userPasswordProperty = new AnnotatedBeanProperty<UserPassword>(ProcessUser.class, UserPassword.class);
// Will get the hash value from annotation UserPassword in ProcessUser.class
String algorithm = userPasswordProperty.getAnnotation().hash();
return PasswordHash.instance().generateSaltedHash(password, salt, algorithm);
}
Note that the method saveProcessUser() is called from the user administration form, and the currentUser object is my User entity. Seam will inject all the methods for us, so we dont have to do that. So we check if the verifyPassword is set and correct and then we hash the password. If the @UserPassword is set to something other than none, then it will correctly save a user and you can finally copy the hashed password in your import.sql script.
PS: You first should have the @UserPassword(hash="none") and then go to your user registration and then just print out what the password is, and then copy that to your import.sql script. When the authentication correctly works with either md5 or sha, then you can safely add the user to the database.