Summary
Why do I get an HTTP status code 401 with a RESTful API with basic authentication by executing an HTTP POST (csrf enabled). I would expect an 403 status code as the AccessDeniedHandlerImpl write in the log. But the request ist "redirected" to /error an the BasicAuthenticationFilter is not jet executet and the AuthenticationEntryPoint wirte an status 401 with an authentication header. The user is an valid authenticated user, but tries to POST a request without csrf token.
Actual Behavior
Client side receives 401 status code instead of 403
Expected Behavior
Client side receives 403 status code instead of 401
Configuration
see sample
Version
6.01 RELEASE
Sample
@Configuration
@EnableWebSecurity(debug = true)
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests().anyRequest().authenticated();
http.httpBasic(withDefaults());
//Session management
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//Security header setting (disable csrf and set sameOrigin)
return http.build();
}
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
@Bean
public UserDetailsService inMemoryUsers() {
UserDetails user1 = User.builder()
.username("customer@bfh.ch")
.password(passwordEncoder().encode("12345678"))
.roles(Constants.CUSTOMER)
.build();
UserDetails user2 = User.builder()
.username("employee@bfh.ch")
.password(passwordEncoder().encode("12345678"))
.roles(Constants.EMPLOYEE)
.build();
UserDetails admin = User.builder()
.username("admin@bfh.ch")
.password(passwordEncoder().encode("87654321"))
.roles(Constants.ADMINISTRATOR)
.build();
return new InMemoryUserDetailsManager(user1, user2, admin);
}
@GetMapping(path = "/token")
public String getToken(Authentication authentication) {
return "123456";
}
Comment From: marcusdacoregio
Hi @pitFromCH,
The CsrfFilter is executed before the BasicAuthenticationFilter, therefore there will be no request authentication yet. In the ExceptionTranslationFilter, if the authentication is not present, instead of executing the AccessDeniedHandler, Spring Security calls the AuthenticationEntryPoint. That's why you are seeing a 401 instead of 403.
I'm closing this as it seems to be more suited for Stackoverflow, however, you can continue the discussion if you think there is something off.