I have a login form with spring security jdbc authentication, it works well with normal form submission.
Now i've encrypted the user password on client side with javascript, i use cryptoJs
and the encrypted password is submitted to the server, the problem is that i have to decode the password before let spring check the password hash in the database and i can't figure how to do that, i've tried with a custom filter
public class LoginFilter extends UsernamePasswordAuthenticationFilter{
public LoginFilter(AuthenticationManager auth){
super.setAuthenticationManager(auth);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException{
//Decode password
return super.attemptAuthentication(request, response);
}
}
it intercept the request, i can get the password and decode it but i can't pass to the UsernamePasswordAuthenticationFilter
, how can i pass to spring the decoded password instead of the encoded submitted by the user?
P.S. I'm not using Https and i know that javascript encryption is probably useless
I've found a solution, not sure if it is the best possible but it works, Spring uses a PasswordEncoder
object to check that the password typed by the user match the stored (and hashed) password.
I was using a BCryptPasswordEncoder
which uses the method matches(rawPass,encodedPass)
to check the password, so i've created my own PasswordEncoder
in this way
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.usersByUsernameQuery(USER_QUERY)
.authoritiesByUsernameQuery(ROLE_QUERY)
.dataSource(dataSource)
.passwordEncoder(new PasswordEncoder(){
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
// Decoding stuff on the encrypted password sended by the client (rawPassword)
return encoder.matches(decryptedPassword, encodedPassword);
}
@Override
public String encode(CharSequence rawPassword) {
//Same crypto operation to get the plain password
return encoder.encode(decryptedPassword);
}
});
}
so the client send the encrypted password to the server, the custom PasswordEncoder
decrypt it to get back the plain password then pass it to the BCryptPasswordEncoder
, Spring security will handle the rest of the authentication process