spring-projects / spring-security

Spring Security
http://spring.io/projects/spring-security
Apache License 2.0
8.73k stars 5.86k forks source link

For an authenticated user hosted controllers are returning error response (redirected to login) if any subsequent REST calls are returning 401 error #15475

Closed svankamamidi closed 1 month ago

svankamamidi commented 1 month ago

Describe the bug We are using Spring Security OAuth2 with WebFlux, For the rest end points/controllers we are implementing if any of the underlying API return 401 because of their implementation issue, current valid login is removed and subsequent calls are failing and are returned to login link. How to avoid this situation if 401 is returned from few known uri's only. Basically Session had valid authenticated credentials stored.

To Reproduce Using below sample code to simulate a supporting service return 401 @GetMapping(value = "/supporting-service") public ResponseEntity<ArrayList<String>> getDummy(ServerWebExchange exchange) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED //and tried Forbidden).body(new ArrayList<String>()); }

Tried implementing ServerAccessDeniedHandler, my override was never invoked

//Added Security config
//.exceptionHandling(exception -> exception.accessDeniedHandler(customAccessDeniedHandler())

public class CustomAccessDeniedHandler implements ServerAccessDeniedHandler {

@Override
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException accessDeniedException) {
    ObjectMapper objectMapper =  new ObjectMapper();
    log.info(exchange.getRequest().getPath().toString());
    log.info(exchange.getResponse().getStatusCode().toString());
    byte[] bytes;
    try {
        bytes = objectMapper.writeValueAsBytes("Error msg ");
    } catch (JsonProcessingException e) {
        throw new RuntimeException(e);
    }

    exchange.getResponse().getHeaders().add("Content-Type", APPLICATION_JSON_VALUE);
    exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);

    return exchange.getResponse().writeWith(
            Mono.just(
                    new DefaultDataBufferFactory().wrap(bytes)
            ));
}

Expected behavior I placed break point in ServerAuthenticationEntryPointFailureHandler.onAuthenticationFailure() with no hit and server returned subsequent calls with 307 response and location value as /oauth2/auth

Also CustomAccessDeniedHandler->() is never invoked when 401 is retuned as shown above.

https://stackoverflow.com/questions/78740738/for-an-authenticated-user-hosted-controllers-are-returning-error-response-if-any

jzheaux commented 1 month ago

Thanks, @svankamamidi, I've added a comment to the question. Since it was closed, I'd recommend posting a new question in case what I recommended doesn't help.

svankamamidi commented 1 month ago

@jzheaux our concern is handling 401 returned by consumed services; as user is already authenticated for our service hosted end-points. i.e. lets say my controller is making a call to another service end point and somehow it returns 401. In this case still my controllers should continue to work!!

I have observed that, I placed break point in ServerAuthenticationEntryPointFailureHandler.onAuthenticationFailure() with no hits and server returned subsequent calls with 307 response and location value as /oauth2/auth