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.