I'm using the following web security configuration for my Spring boot app:
@EnableWebSecurity
@Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AccountRepository accountRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/login").deleteCookies("auth_code").invalidateHttpSession(true)
.and()
// We filter the api/signup requests
.addFilterBefore(
new JWTSignupFilter("/signup", authenticationManager(), accountRepository),
UsernamePasswordAuthenticationFilter.class)
// We filter the api/login requests
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in
// header
.addFilterBefore(new JWTAuthenticationFilter(userDetailsServiceBean()),
UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsServiceBean()).passwordEncoder(passwordEncoder());
}
@Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return new CustomUserDetailsService(accountRepository);
}
@Bean
public PasswordEncoder passwordEncoder(){
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
As you can see, I use BCryptPasswordEncoder.
I have two problems:
1.Where is the salt for the BCryptPasswordEncoder stored ? According to my findings, it's random each time and it's stored somewhere in the database, but I didn't define any column for it. I'm confused over how it works.
2.I have a Signup filter:
public class JWTSignupFilter extends AbstractAuthenticationProcessingFilter {
private AccountRepository accountRepository;
@Autowired
private PasswordEncoder passwordEncoder;
public JWTSignupFilter(String url, AuthenticationManager authManager,
AccountRepository accountRepository) {
super(new AntPathRequestMatcher(url, "POST"));
setAuthenticationManager(authManager);
this.accountRepository = accountRepository;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException,
IOException, ServletException {
CustomUserDetails creds = new ObjectMapper().readValue(
req.getInputStream(), CustomUserDetails.class);
if (accountRepository.findByUsername(creds.getUsername()) != null) {
throw new AuthenticationException("Duplicate username") {
private static final long serialVersionUID = 1L;
};
}
CustomUserDetails userDetails = new CustomUserDetails(
creds.getUsername(), creds.getPassword(), true, true, true,
true,
AuthorityUtils.commaSeparatedStringToAuthorityList("USER_ROLE"));
accountRepository.save(userDetails);
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(creds.getUsername(),
creds.getPassword()));
}
@Override
protected void successfulAuthentication(HttpServletRequest req,
HttpServletResponse res, FilterChain chain, Authentication auth) {
TokenAuthenticationService.addAuthentication(res, auth.getName());
}
}
As you can see I create a new UserDetails and save it in the account repository.
If I encode the password while creating the UserDetails
object, it would create not the same password as when logging in. (the econded passowrds are different) I think this should be because of the different salts being used.
Any idea how I can fix this ?