6

Have simple Spring Security webapp with password encoding:

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="personService">
     <security:password-encoder hash="md5" ref="passwordEncoder"> 
        <!--  <security:salt-source user-property="username"/> -->
     </security:password-encoder>
 </security:authentication-provider>
</security:authentication-manager>

Encoding also simple:

 person.setPassword(encoder.encodePassword(person.getPassword(), null));

So in DataBase all passwords will be encoded. Now I want to do authentication of some user with certain username within the apllication. Before(when passswords was in plaintext) it was like this:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                username, password);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);

But now I get encoded password from DB and cant do authentication as before.

The problem. that Spring dont know that password cames from UsernamePasswordAuthenticationToken already encoded. And he is encoding it it second time. Who can help?

Edit

So I see two solutions here:

  1. implement custom DaoAuthenticationProvider where add check if both passwords already hashed
  2. implement custom Authentication and put it in security context manually.

Any others? What is the best?

vacuum
  • 2,273
  • 3
  • 20
  • 32
  • Comprised some of SpringSecurity in [detail here](http://techastute.blogspot.com/2013/01/spring-security-in-detail.html), may be its useful for some one. – raksja Jan 21 '13 at 17:51

1 Answers1

11

You haven't actually said what goes wrong, but the authentication code should be exactly the same as for the non-hashed version.

If you have a hashed password in the database and the corresponding encoder injected into the authentication provider, the password supplied by the user will be hashed by the encoder before comparing it with the database version.

Make sure:

  1. You use the unhashed password value when creating the UsernamePasswordAuthenticationToken
  2. The value in the database really is the same as the hash produced by the encoder. Load it yourself and check it in a test. The database might be storing it in upper case, for example.

Also, you should probably choose something better than plain MD5. You might want to look at bcrypt, for example, which is supported in Spring Security 3.1 and automatically uses a random salt value.

Update

Your suggestion of creating a provider which accepts hashed passwords is not a good one. This would allow anyone who steals a password hash to authenticate with it directly (thus defeating the purpose of hashing in the first place).

Just validate your email URL links, load the information for that user and create an Authentication object for them:

UserDetails user = ... // load user here
Authentication a = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(a);
Shaun the Sheep
  • 22,353
  • 1
  • 72
  • 100
  • The problem is in 1. When creating the UsernamePasswordAuthenticationToken I have only hashed version of password as I load UserDetails object from DB(in my case - by confirmation key) – vacuum Feb 15 '12 at 21:15
  • Using the stored password won't authenticate the user (which I assume is what you are trying to do). If not, you'll need to clarify what you're trying to achieve. There's not much point in calling the authentication manager with a password which you know is correct in advance. – Shaun the Sheep Feb 15 '12 at 21:23
  • I am trying to authenticate user, who clicked on a link from registration email. So UserDetails object came from DB by confirmation key which came from confirm link in email. – vacuum Feb 15 '12 at 21:37
  • 1
    Then there is no point in checking the password. Use a short-lived, random URL in the link, validate the key and just set the security context directly. – Shaun the Sheep Feb 15 '12 at 21:59
  • Great, only one more problem left(: How to set the security context directly? – vacuum Feb 15 '12 at 22:02
  • did you find a solution please ? – Aguid Dec 08 '20 at 20:58