Expected Behavior

I would expect a 5xx series HTTP response after encountering the stack trace below.

Current Behavior

Instead, the stack trace below manifests itself as a 401 HTTP response.

Context pom.xml

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
      <version>2.3.8.RELEASE</version>
</dependency>

stack trace snippet

DEBUG | org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter | Authentication request for failed!
org.springframework.security.authentication.AuthenticationServiceException: An error occurred while attempting to decode the Jwt: Couldn't retrieve remote JWK set: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://identity.acme.com/auth/realms/acme-app/protocol/openid-connect/certs": No subject alternative DNS name matching identity.acme.com found.; nested exception is javax.net.ssl.SSLHandshakeException: No subject alternative DNS name matching identity.acme.com found.
at org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider.authenticate(JwtAuthenticationProvider.java:88)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
at org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:124)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)

In this case, our Resource Server encounters a problem connecting to the Authorization Server, so from the perspective of the Resource Server trying to connect to the Authorization Server, I would expect this condition to result in a 5xx HTTP status to indicate to the client who sent the JWT to the Resource Server that there is a problem on the server side and not with the JWT itself.

Comment From: jzheaux

Thanks for the report, @kabennett.

Spring Security's authentication filters handle all authentication failures the same by default. You can change this behavior for Resource Server by registering a custom authentication entry point, which you can base off of the defaults like so:

@Bean 
AuthenticationEntryPoint entryPoint() {
    AuthenticationEntryPoint bearer = new BearerTokenAuthenticationEntryPoint();
    return (request, response, exception) -> {
        if (exception instanceof AuthenticationServiceException) {
            throw exception;
        }
        bearer.commence(request, response, exception);
    };
}

// ...

http
    .oauth2ResourceServer((oauth2) -> oauth2
        .authenticationEntryPoint(entryPoint)
    );

This works because Resource Server throws an InvalidBearerTokenException when it's the client's fault and AuthenticationServiceException when it's the server's fault.

Comment From: jzheaux

Thanks again for reporting this, @kabennett. I've added https://github.com/spring-projects/spring-security/issues/9429 as a related ticket.