Spring Oauth2 - Custom Exception Handler

In Spring, Oauth2-based security authentication, when a client sends an access token that needs to be updated, the DefaultTokenServices class raises an InvalidTokenException (see line 235):

https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java

the output when this happens looks something like this:

{"error":"invalid_token","error_description":"Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9" } 

I want to change this conclusion, but I'm lost. Another answer suggested creating a custom exceptionRenderer , but that didn't work either, my custom exception handler is never called in these cases.

There is also something called the exception translator, but in any case they are called.

Part of my Spring configuration:

 <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> <property name="typeName" value="Basic"/> <property name="exceptionRenderer" ref="myExceptionRenderer" /> </bean> <bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> <property name="exceptionRenderer" ref="myExceptionRenderer" /> <property name="exceptionTranslator" ref="listyOauthExceptionTranslator" /> </bean> <bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" > <property name="exceptionRenderer" ref="myExceptionRenderer" /> <property name="exceptionTranslator" ref="myExceptionTranslator" /> </bean> <bean id="myExceptionRenderer" class="com.example.exceptions.MyOauth2ExceptionRenderer" /> <bean id="myExceptionTranslator" class="com.example.exceptions.MyOauth2ExceptionTranslator" /> 

Exception Visualizer:

 public class MyExceptionRenderer implements OAuth2ExceptionRenderer { @Override public void handleHttpEntityResponse(HttpEntity<?> responseEntity, ServletWebRequest webRequest) throws Exception { System.out.println("Thrown exception"); } 

}

I also added a custom Exception Mapper that should get ALL exceptions, but since I assume this is another servlet, does this really not work in this case?

 @Provider public class GenericExceptionMapper implements ExceptionMapper<Throwable> { @Override public Response toResponse(Throwable ex) { System.out.println("MAPPING EXCEPTION"); return Response.status(200).entity().build(); } } 

I could detect AuthenticationException cases, but not any of InvalidTokenExceptions .

Any help on this? Where does Spring really catch this InvalidTokenException and how to set it up so that I can provide custom output?

+6
source share
4 answers

InvalidTokenException extends ClientAuthenticationException . Therefore, you can create your own exception by extending ClientAuthenticationException and throwing it instead of InvalidTokenException

 public class CustomException extends ClientAuthenticationException { public CustomException(String msg, Throwable t) { super(msg, t); } public CustomException(String msg) { super(msg); } @Override public String getOAuth2ErrorCode() { return "my_custom_exception"; } } 

as

 throw new CustomException("Invalid access token: " + accessTokenValue); 

In error caused by InvalidTokenException

  {"error":"invalid_token","error_description":"Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9"} 

invalid_token returned by the getOAuth2ErrorCode() method of InvalidTokenException, and Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9 is the message that you specify when an exception is thrown.

If you throw it away

  throw new CustomException("This is my custom exception"); 

the error will be displayed as

 {"error":"my_custom_exception","error_description":"This is my custom exception"} 

my_custom_exception comes from getOAuth2ErrorCode() from CustomException .

+5
source

The answer does not actually provide a user implementation, the user response will be a point in the code where I can access the default answer, and I can send a POJO instead, for example, if you want to change error_description to error_info or something else , or you can add additional variables to the answer. A solution does exist, but I think it hurts to implement, to say the least, as I copy it from here :

This issue has been resolved. Follow the workaround below: 1 Extend OAuth2Exception to a new class, such as CustomOAuth2Exception. In a custom class, add some specific properties. 2 custom DefaultWebResponseExceptionTranslator and register the custom translator in AuthorizationServerConfiguration. 3 custom two jackson serializers annotated in an OAuth2Exception and annotated your CustomOAuth2Exception with two custom serializers. 4 Use ObjectMapper to override source serializers using custom serializers.

+3
source

This is my solution for custom exceptions AuthorizationServer and ResourceServer. Maybe this will help.

Spring Security Oauth - custom format for OAuth2Exceptions

0
source

to override

 {"error":"invalid_token","error_description":"Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9" } 

you need to inherit the ResourceServerConfigurerAdapter and override the public void configuration (final ResourceServerSecurityConfigurer configuration)

sample code

 package com.org.security; import org.springframework.http.ResponseEntity; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator; import org.springframework.stereotype.Component; @Component public class CustomWebResponseExceptionTranslator extends DefaultWebResponseExceptionTranslator { /** * Modify OAuth2.0 Error Response * @param e * @return ResponseEntity<OAuth2Exception> * @throws Exception */ @Override public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception { ResponseEntity responseEntity = super.translate(e); OAuth2Exception auth2Exception = (OAuth2Exception)responseEntity.getBody(); if (auth2Exception != null) { auth2Exception.addAdditionalInformation("data", null); auth2Exception.addAdditionalInformation("message", auth2Exception.getMessage()); auth2Exception.addAdditionalInformation("statusCode", String.valueOf(auth2Exception.getHttpErrorCode())); } return new ResponseEntity<OAuth2Exception>(auth2Exception, responseEntity.getHeaders(), responseEntity.getStatusCode()); } } package com.org.security; import com.org.exception.CustomAuthExceptionEntryPoint; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; @Configuration @EnableResourceServer public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private ResourceServerTokenServices tokenServices; @Autowired private WebResponseExceptionTranslator oauth2ResponseExceptionTranslator; @Override public void configure(final ResourceServerSecurityConfigurer config) { OAuth2AccessDeniedHandler auth2AccessDeniedHandler = new OAuth2AccessDeniedHandler(); auth2AccessDeniedHandler.setExceptionTranslator(oauth2ResponseExceptionTranslator); OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); authenticationEntryPoint.setExceptionTranslator(oauth2ResponseExceptionTranslator); config.tokenServices(tokenServices).accessDeniedHandler(auth2AccessDeniedHandler).authenticationEntryPoint(authenticationEntryPoint); } } 
0
source

All Articles