javaspring-securityspring-boot-security

All exceptions are converted to HTTP 401 on public endpoints


i have problem on spring boot starter security V3.0.0

For this configuration :


    @Bean
    public SecurityFilterChain filterChain( final HttpSecurity http ) throws Exception {
        http
                .cors().and().csrf().disable()
                .sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS )
                .and()
                .anonymous()
                .and()
                .authorizeHttpRequests()
                .requestMatchers( HttpMethod.OPTIONS ).permitAll()
                .requestMatchers( "/system/**" ).hasRole( new SecurityRole( Role.ROLE_SYSTEM ).toString() )
                .requestMatchers( "/admin/**" ).hasRole( new SecurityRole( Role.ROLE_AUTH_ADMIN ).toString() )
                .requestMatchers( "/identity/**" ).hasRole( new SecurityRole( Role.ROLE_AUTH_IDENTITY ).toString() )
                .requestMatchers( "/guest/**" ).permitAll()
                .anyRequest().authenticated()
                .and()
                .oauth2ResourceServer( OAuth2ResourceServerConfigurer::jwt );

        return http.build();
    }

All exceptions thrown by "/guest/**" endpoint are converted to HTTP 401 whitout body. Even when I issue an HTTP 409 with this class :

@ResponseStatus( code = HttpStatus.CONFLICT )
public class HttpConflictException extends RuntimeException {
    public HttpConflictException( String message ) {
        super( message );
    }
}

IMPORTANT : When no exception is thrown, the query works

If this line

.requestMatchers( "/guest/**" ).permitAll()

is replaced by this

 .requestMatchers( "/**" ).permitAll()

it works. But this option seems too dangerous. Am I not understanding something? I haven't seen anything in the documentation that can help with this issue.

Dependencies :

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-jose</artifactId>
</dependency>

Thank you.


Solution

  • Ok, I found a solution that seems to work.

    Adding this line fixes the problem :

    .dispatcherTypeMatchers( DispatcherType.ERROR ).permitAll()
    

    Complete code :

    @Bean
        public SecurityFilterChain filterChain( final HttpSecurity http ) throws Exception {
            http
                    .cors().and().csrf().disable()
                    .sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS )
                    .and()
                    .anonymous()
                    .and()
                    .authorizeHttpRequests()
                    .dispatcherTypeMatchers( DispatcherType.ERROR ).permitAll()
                    .requestMatchers( HttpMethod.OPTIONS ).permitAll()
                    .requestMatchers( "/guest/**" ).permitAll()
                    .requestMatchers( "/system/**" ).hasRole( new SecurityRole( Role.ROLE_SYSTEM ).toString() )
                    .requestMatchers( "/admin/**" ).hasRole( new SecurityRole( Role.ROLE_AUTH_ADMIN ).toString() )
                    .requestMatchers( "/identity/**" ).hasRole( new SecurityRole( Role.ROLE_AUTH_IDENTITY ).toString() )
                    .anyRequest().authenticated()
                    .and()
                    .oauth2ResourceServer( OAuth2ResourceServerConfigurer::jwt );
    
            return http.build();
        }
    

    Documentation : https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html