1

I have an application which uses Spring Security to authenticate users. Users and hashed/salted passwords are stored in database. Nothing special hele, USER table with username/password fields. The app uses BCryptPasswordEncoder for hashing function. Now I need to migrate some legacy user data to the application. The legacy data passwords are hashed with other hashing function, lets say, MD5. I can insert the legacy data into the same USER table, but then I have password hashed with different hash functions.

How can I configure Spring Security to select appropriate hashing function when authenticating legacy users / new users?

UPDATE

"MigrateUsersPasswordEncoder" wrom here seems an excellent solution for the problem

Community
  • 1
  • 1
never
  • 671
  • 1
  • 6
  • 18

2 Answers2

1

A bcrypt password has a very distinct presentation which can be tested using a regular expression. The most simple solution I can imagine is creating a password encoder composite which can be used by the authentication manager. It should decide what encoder to use based on the password's representation.

Simple example:

class PasswordEncoderComposite implements PasswordEncoder {
    private Pattern BCRYPT_PATTERN = Pattern.compile("\\A\\$2a?\\$\\d\\d\\$[./0-9A-Za-z]{53}");

    public String encode(CharSequence rawPassword) {
        if (BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
            return new BCryptPasswordEncoder().encode(rawPassword);
        } else {
            return new StandardPasswordEncoder().encode(rawPassword);
        }
    }

    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        if (BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
            return new BCryptPasswordEncoder().matches(rawPassword, encodedPassword);
        } else {
            return new StandardPasswordEncoder().matches(rawPassword, encodedPassword);
        }
    }
}
Bart
  • 17,070
  • 5
  • 61
  • 80
0

Havent tried this myself:

You could migrate the old users into your new db and keep the MD5 hashes in the password column.

You create two AuthenticationProviders. One for BCrypt and one for MD5. Order them so that BCrypt will be checking first. If the frist provider fails the second will check against an MD5 hash.

During a password change you can only use the BCrypt hasher so that after a while all users will use a BCrypted password.

You might be able to force the user to update their password after a successful login via the MD5 hash.

Martin Frey
  • 10,025
  • 4
  • 25
  • 30
  • Martin, could you please give me a link to AuthenticationVoters documentation/ reference? failed to find anything useful by myself – never May 07 '14 at 09:58
  • I think i got the wrong name :) it should be authenticationprovider. I have modified the answer. – Martin Frey May 07 '14 at 12:44
  • You are better to use a single `AuthenticationProvider` and you don't need to force a password change to convert the password to bcrypt. You have the plaintext password available when the user authenticates. See my answers [here](http://stackoverflow.com/questions/17240744/spring-security-3-1-4-and-shapasswordencoder-deprecation/17348888#17348888) and [here](http://stackoverflow.com/questions/13762772/how-to-change-password-hashing-algorithm-when-using-spring-security/13772382#13772382) which address the same question. – Shaun the Sheep May 07 '14 at 12:57
  • Thank You Luke! Your answers are what I needed – never May 08 '14 at 05:33