First things first, I want to tell that the “password” column in my db is 255 characters length, and that I persist it correctly to the db:
I’ve already ensured that: BCrypt version and strength matches. Tried using the debugger, didn’t see anything weird in the local variables, until the “passwordEncoder.matches” method didn’t eventually yield “false” and of course googled a lot, but without any success so far..
Nevertheless, I’m still getting this error:
2024-09-07T19:46:13.867+03:00 TRACE 2672624 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Invoking UsernamePasswordAuthenticationFilter (6/13)
2024-09-07T19:46:13.868+03:00 TRACE 2672624 --- [nio-8080-exec-4] o.s.s.authentication.ProviderManager : Authenticating request with DaoAuthenticationProvider (1/2)
2024-09-07T19:46:13.871+03:00 WARN 2672624 --- [nio-8080-exec-4] o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
2024-09-07T19:46:13.871+03:00 DEBUG 2672624 --- [nio-8080-exec-4] o.s.s.a.dao.DaoAuthenticationProvider : Failed to authenticate since password does not match stored value
2024-09-07T19:46:13.871+03:00 TRACE 2672624 --- [nio-8080-exec-4] o.s.s.authentication.ProviderManager : Authenticating request with DaoAuthenticationProvider (1/1)
2024-09-07T19:46:13.873+03:00 WARN 2672624 --- [nio-8080-exec-4] o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
2024-09-07T19:46:13.873+03:00 DEBUG 2672624 --- [nio-8080-exec-4] o.s.s.a.dao.DaoAuthenticationProvider : Failed to authenticate since password does not match stored value
2024-09-07T19:46:13.873+03:00 TRACE 2672624 --- [nio-8080-exec-4] w.a.UsernamePasswordAuthenticationFilter : Failed to process authentication request
org.springframework.security.authentication.BadCredentialsException: Bad credentials
UserDetailsService:
@Service
public class SecurityUserService implements UserDetailsService {
final private JdbcTemplate jdbcTemplate;
public SecurityUserService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public UserDetails loadUserByUsername(String username) {
String sql = "SELECT * FROM user WHERE username = ?";
return jdbcTemplate.query(sql, new SecurityUserMapper(), username).getFirst();
}
}
SecurityUserMapper:
public class SecurityUserMapper implements RowMapper<SecurityUser> {
@Override
public SecurityUser mapRow(ResultSet rs, int rowNum) throws SQLException {
SecurityUser user = new SecurityUser();
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
return user;
}
}
AuthServerConfig:
@Configuration
public class AuthServerConfig {
private final RsaKeyProperties rsaKeys;
private UserDetailsService userDetailsService = new SecurityUserService(new JdbcTemplate());
public AuthServerConfig(RsaKeyProperties rsaKeys, UserDetailsService userDetailsService) {
this.rsaKeys = rsaKeys;
this.userDetailsService = userDetailsService;
}
@Bean
@Order(0)
public SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults());
http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.exceptionHandling((exceptions) -> exceptions.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)));
return http.build();
}
@Bean
@Order(1)
public SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable());
http.userDetailsService(userDetailsService);
http.formLogin(Customizer.withDefaults());
http.httpBasic(Customizer.withDefaults()); // new line
http.logout(logout -> logout.logoutUrl("/login?logout"));
http.authorizeHttpRequests(request -> {
request.dispatcherTypeMatchers(
DispatcherType.FORWARD,
DispatcherType.ERROR).permitAll();
request.requestMatchers("/oauth2/token").permitAll();
request.anyRequest().authenticated();
});
return http.build();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(BCryptVersion.$2A);
}
@Bean
JwtEncoder jwtEncoder() {
JWK jwk = new RSAKey.Builder(rsaKeys.publicKey()).privateKey(rsaKeys.privateKey()).build();
JWKSource<SecurityContext> jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
return new NimbusJwtEncoder(jwks);
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withPublicKey(rsaKeys.publicKey()).build();
}
@Bean
public AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().build();
}
@Bean
RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {
return new JdbcRegisteredClientRepository(jdbcTemplate);
}
}
I’m only learning Spring, so I’ll be very thankful for your help
EDITED
I wasn’t sure how to show what the request looks like when requesting through the login page, so I implemented Basic authentication with all defaults and tried to authenticate against it:
2