CodeMed February 2016

How do I configure REST service to manually check encrypted passwords with Spring Security?

A RESTful Spring Boot service needs to manually login users whose credentials are sent via JSON from an AngularJS front end. The code below accomplishes this using unencrypted passwords, but I want the passwords to be encrypted when they are stored in the database. When I add BCryptPasswordEncoder().matches... to the code below, it is still not able to match the encrypted user password. What specific changes need to be made to the code below so that the /login1 method is able to perform manual password checking and thus then be able to perform its custom login procedures?

Here are the four lines of the login process that are failing to do the password match currently, though the failure may be due to the way that the passwords are encrypted in the registration process:

UserDetails user = users.loadUserByUsername(uname);
PasswordEncoder encoder = new BCryptPasswordEncoder();
String encpwd = encoder.encode(rphon.getEncpwd());//takes JSON unencoded string value `password` and encodes it using encoder.encode(...)
if(encoder.matches(user.getPassword(), encpwd)){//this encoder.matches check fails  

Here is the complete relevant code for the two REST services in the Spring Boot app that handle registration (password encryption) and authentication (password matching), respectively. Note that in the present configuration, the client app is sending a password with the value password in unencrypted text, but through an SSL connection:

@RequestMapping(value = "/register", method = RequestMethod.POST)
public @ResponseBody ResultMessage getPin(@RequestBody ResultMessage rmsg) {

    String uname = rmsg.getName();
WebLead wld = myrepo.findByEmailaddress(uname);
    User newusr = new User();
    newusr.setName(wld.getEmailaddress());
    PasswordEncoder encoder = new BCryptPasswordEncoder();
    String pwd = encoder.encode("password");
    newusr.setPasswor        

Answers


tanenbring February 2016

Don't create a new PasswordEncoder every time. Because of how BCrypt handles salting, this won't work. Instead, create a PasswordEncoder bean and autowire it when you need it.

In the SecurityConfiguration add this:

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

Then in your controllers that need access to it, autowire it:

@Autowired 
private PasswordEncoder passwordEncoder;

That should solve your problems.


Arul February 2016

The interface PasswordEncoder has the method defined like this below.

boolean matches(CharSequence rawPassword,
          String encodedPassword)

Verify the encoded password obtained from storage matches the submitted raw password after it too is encoded. Returns true if the passwords match, false if they do not. The stored password itself is never decoded.

Parameters:

  • rawPassword - the raw password to encode and match
  • encodedPassword - the encoded password from storage to compare with

Returns:

  • true if the raw password, after encoding, matches the encoded password from storage

It is expecting to be passed a raw password(either the JSON has it raw or you may have to decode based on how it was encoded, to convert it to raw) as first parameter and the encoded password comes from DB as second parameter.

Post Status

Asked in February 2016
Viewed 2,835 times
Voted 7
Answered 2 times

Search




Leave an answer