Search code examples
javaspringspring-securitybcrypt

Spring Boot BCryptPassword Authentication


I have a simple controller for user authentication:

@RestController
@RequestMapping("/auth")
public class UserController {
    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping("/login")
    public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest loginRequest) {
        try {
            LoginResponse loginResponse = userService.login(loginRequest);
            return new ResponseEntity<>(loginResponse, HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity<>(ResponseHandler.handleLoginResponse(LoginResponseEnums.GENERAL_ERROR, ""), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

And a service for it:

@Service
public class UserServiceImpl implements UserService {
    // FIXME: 6/10/2022 Initialize dummy data for H2, remove on prod
    @PostConstruct
    private void init() {
        userRepository.save(new User("[email protected]", "$2a$10$e8xk4HeAkWwK5DwTFNXgN.ijlYEzlJJDUOcCBLZzTQuWFtQyeaXtW"));
        userRepository.save(new User("[email protected]", "$2a$10$e8xk4HeAkWwK5DwTFNXgN.ijlYEzlJJDUOcCBLZzTQuWFtQyeaXtW"));
    }

    private final UserRepository userRepository;
    private final AuthenticationProvider authenticationProvider;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    private final JwtTokenProvider jwtTokenProvider;

    @Autowired
    public UserServiceImpl(JwtTokenProvider jwtTokenProvider, UserRepository userRepository, AuthenticationProvider authenticationProvider, BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.userRepository = userRepository;
        this.authenticationProvider = authenticationProvider;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.jwtTokenProvider = jwtTokenProvider;
    }

    public LoginResponse login(LoginRequest loginRequest) {
        String email = loginRequest.getEmail();
        String password = loginRequest.getPassword();
        try {
            authenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(email, password));
        } catch (Exception e) {
            return ResponseHandler.handleLoginResponse(LoginResponseEnums.PASSWORD_INCORRECT, "");
        }

        Optional<User> userByEmail = userRepository.findUserByEmail(email);
        if (userByEmail.isPresent()) {
            return ResponseHandler.handleLoginResponse(LoginResponseEnums.SUCCESS, jwtTokenProvider.createToken(email));
        } else {
            return ResponseHandler.handleLoginResponse(LoginResponseEnums.EMAIL_DOES_NOT_EXIST, "");
        }
    }
}

And AuthenticationProviderBean

@Bean
    public AuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider =
                new DaoAuthenticationProvider();
        provider.setPasswordEncoder(bCryptPasswordEncoder());
        provider.setUserDetailsService(userDetailsService);
        return provider;
    }

I have a little problem with

try {
            authenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(email, password));
} catch (Exception e) {
            return ResponseHandler.handleLoginResponse(LoginResponseEnums.PASSWORD_INCORRECT, "");
}

When the original password is presented: "123456", authentication provider authenticates a user, but when i present BCrypt encoded password: "$2a$10$e8xk4HeAkWwK5DwTFNXgN.ijlYEzlJJDUOcCBLZzTQuWFtQyeaXtW", it throws: org.springframework.security.authentication.BadCredentialsException: Bad credentials I want to authenticate user with BCrypt Encoded password, what do i need to change? I want to authenticate user with this request:

{
"Email": "[email protected]"
"Password": "$2a$10$e8xk4HeAkWwK5DwTFNXgN.ijlYEzlJJDUOcCBLZzTQuWFtQyeaXtW"
}

Solution

  • BCryptPasswordEncoder doesn't work that way. It's matches method expects clear text password along with previously encoded password