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.