0

Sorry for noob question, I am still learning Spring boot. I want to implement custom error like default spring 404 not found when someone hit wrong API:

{
    "timestamp": "2022-03-20T17:01:07.453+00:00",
    "status": 404,
    "error": "Not Found",
    "path": "/api/v1/testing"
}

The problem, when I hit the wrong API the Exception always bubble up/catch to my custom AuthenticationEntryPoint and not bubble up to RestControllerAdvice or NoHandlerFoundException.

I am using Spring Security with oauth2-resource-server with my SecurityFilterChain:

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .csrf(csrf -> csrf.disable())
                .cors().and()
                .authorizeHttpRequests(auths -> auths
                        .antMatchers(ALLOW_LIST_URIS).permitAll()
                        .anyRequest().authenticated()
                )
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt
                                .jwtAuthenticationConverter(jwtAuthenticationConverter())))
                .oauth2ResourceServer(oAuth2 -> oAuth2.authenticationEntryPoint(authenticationEntryPoint))
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .build();
    }

and my AuthenticationEntryPoint (this class always called):

@Slf4j
@Component
@RequiredArgsConstructor
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    private final Jackson2ObjectMapperBuilder mapperBuilder;

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
            throws IOException {
        log.warn("Someone has tried to access without Authentication(AuthenticationException): {}",
                authException.getMessage());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        mapperBuilder.build()
                .writeValue(response.getOutputStream(), new ErrorResDto(HttpStatus.UNAUTHORIZED, UNAUTHORIZED_MESSAGE));
        response.getOutputStream().flush();
    }
}

I have tried to solve with

spring.mvc.throw-exception-if-no-handler-found=true
server.error.whitelabel.enabled=false
spring.web.resources.add-mappings=false
@Slf4j
@RestControllerAdvice
public class CustomExceptionHandling {
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<ErrorResDto> handleNoHandlerFoundException (NoHandlerFoundException e) {
        log.error("NoHandlerFoundException init");
        return createHttpResponse(HttpStatus.NOT_FOUND, MAPPING_NOT_FOUND);
    }

    private ResponseEntity<ErrorResDto> createHttpResponse(HttpStatus httpStatus, String message) {
        ErrorResDto errorResponse = new ErrorResDto(httpStatus, message);
        return new ResponseEntity<>(errorResponse, errorResponse.getHttpStatus());
    }
}

the exceptions always bubble up/catch to my custom AuthenticationEntryPoint and not bubble up to RestControllerAdvice or NoHandlerFoundException.

For now my output always like this:

{
    "rc": 401,
    "message": "Full authentication is required to access this resource",
    "httpStatus": "UNAUTHORIZED"
}

even I hit wrong API like /testing/testing/testing. I want to custom 404 error not found like this:

{
    "rc": 404,
    "message": "Path not found",
    "httpStatus": "NOT_FOUND"
}

Thanks.

2 Answers2

0

This is expected behaviour - Springs exception handling (@ControllerAdvice, @ExceptionHandler) is not involved for logic in filters. For those you could either

  • handle exceptions in custom AuthenticationEntryPoint (which you have). Warning: only spring AuthenticationExceptions can be handled this way! (as mentioned in https://stackoverflow.com/a/75470234)
  • add a custom OncePerRequestFilter (which you add early on in the chain, e.g. before LogoutFilter for example) in which you catch the exceptions and send out the appropriate response. (see https://stackoverflow.com/a/48584634)
Stijn V
  • 358
  • 3
  • 13
0

I recommend to open your server.error.path (by default =/error) in your ALLOW_LIST_URIS. I had the same problem, and it works.

banan3'14
  • 3,810
  • 3
  • 24
  • 47
larbadge
  • 1
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – banan3'14 Aug 09 '23 at 09:46