Since Spring Security 6 every exception thrown by an endpoint that is configured as .permitAll() will be send as 403 Forbidden to the client. This also suppresses the original errormessage.
To reproduce:
@SpringBootApplication
@RestController
public class Application {
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(a -> a
.requestMatchers(new AntPathRequestMatcher("/unsecured/**")).permitAll()
// .requestMatchers(new AntPathRequestMatcher("/error")).permitAll() // <- You need this line as a workaround
.anyRequest().authenticated()
).build();
}
@GetMapping("/unsecured/error")
public String unsecuredError() {
throw new RuntimeException("Here is an error");
}
}
When calling /unsecured/error you will receive a 403 error instead of 500. Adding the commented line will "fix" this. However, I can't see why this should be the default behaviour. The commented line should not be neccecary.
Comment From: lukasdo
I am not really sure if it is a bug. The problem is the default behaviour of Spring Web Error Handling which provides an /error mapping that handles errors.
When the RuntimeException is thrown Spring wants to redirect to the /error page which is by default secured. That's why an AccessDeniedException is thrown in the AuthorizationFilter when the /error path is not permitted in the SecurityConfig.
Comment From: manuelnagler
There is no redirect happening. I get the error from /unsecured/error. I think users dont care which internal endpoint handles errors.
Comment From: rwinch
Thank you for reaching out @manuelnagler
This is deliberate behavior because some users had private information on their error pages and thus they needed them secured by default. To help with this, Spring Security 6 secures all dispatcher types (including ERROR dispatch) not just REQUEST dispatches. If you want to allow ERROR dispatches, you can update your authorization rules by dispatcher type.
Comment From: fnordian
Is this dispatcher-matcher api also available for webflux? I cannot find it.