0

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"
}
2
  • Do you mean, in loginrequest.getPassword() you are trying to pass BCrypt password? Commented Jun 11, 2022 at 5:52
  • Yes, for now {"Email": "[email protected]","Password": "123456", is a success authentication request, but i need to make {"Email": "[email protected]","Password": "$2a$10$e8xk4HeAkWwK5DwTFNXgN.ijlYEzlJJDUOcCBLZzTQuWFtQyeaXtW" Commented Jun 11, 2022 at 5:54

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

4 Comments

Is it safe to pass original password in http request?
Main thing is the password sent over the wire and that is there in the database shouldn't be the same. Otherwise if your database is compromised, all your passwords are compromised. If passwords stored in database are encrypted then even if they get encrypted passwords from database they won't be able to login as legitimate users cause your system would expect unencrypted password. And BCrypt being one way encryption, they can't find clear password from hashed password. Similarly, they can't do bruteforce as salt is different in each BCrypt encode call
But if here is a "Man in Middle Attack", hacker can catch the original password from login request and just log in in system, did i wrong?
If there is man in the middle attack and encrypted password is caught then also he can login with it, as your system is expecting encrypted password over the wire. So, for this use case, it doesn't matter whether it is encrypted or clear text. Read my above comment carefully

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.