Search code examples
springspring-securityspring-oauth2spring-authorization-serverspring-boot-security

How to handle OAuth2AuthenticationException: Client authentication failed: client_id in Spring Security


I'm implementing new Spring Authorization server (spring-security-oauth2-authorization-server version 1.0.0). I have created following two classes to handle exceptions:

public class RestExceptionTranslationFilter implements AuthenticationFailureHandler {
   @Override
   public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
      // Code to handle the exception
   }
}

public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
   public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException {
      // Code to handle the exception
   }
}

I have registered both of them like this:

public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
...
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer();  
authorizationServerConfigurer.tokenEndpoint(tokenEndpoint ->
             ((OAuth2TokenEndpointConfigurer)tokenEndpoint).errorResponseHandler(new RestExceptionTranslationFilter())
);
...
http.exceptionHandling(exceptions ->
            exceptions.authenticationEntryPoint(new RestAuthenticationEntryPoint()));
}

Now I'm able to handle the OAuth2AuthenticationException exceptions and other exceptions and to return the response that my implementation requires. For example, this exception is handled correctly:

org.springframework.security.oauth2.core.OAuth2AuthenticationException: OAuth 2.0 Parameter: grant_type
    at org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter.throwError(OAuth2TokenEndpointFilter.java:260) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
    at org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter.doFilterInternal(OAuth2TokenEndpointFilter.java:159) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]

But, what's confusing me, and I cant solve it, why the same OAuth2AuthenticationException exception is not handled by this configuration in case when its thrown like this from ClientSecretAuthenticationProvider:

org.springframework.security.oauth2.core.OAuth2AuthenticationException: Client authentication failed: client_id
    at org.springframework.security.oauth2.server.authorization.authentication.ClientSecretAuthenticationProvider.throwInvalidClient(ClientSecretAuthenticationProvider.java:151) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
    at org.springframework.security.oauth2.server.authorization.authentication.ClientSecretAuthenticationProvider.authenticate(ClientSecretAuthenticationProvider.java:99) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]

Is it possible to handle this exception and how as I would really like not to disclose the message "error": "invalid_client" to the possible attackers?


Solution

  • Take a look at Configuring Client Authentication in the reference. It would be very similar to how you configured the tokenEndpoint():

        authorizationServerConfigurer
            .clientAuthentication(clientAuthentication ->
                clientAuthentication
                    .errorResponseHandler(new RestExceptionTranslationFilter()) 
            );
    

    Note: "TranslationFilter" is probably not the best name for an AuthenticationFailureHandler, but is a minor detail.