Spring-security-oauth: How to customize my own exception handler in token endpoint?

Created on 26 Oct 2015  路  20Comments  路  Source: spring-projects/spring-security-oauth

The exceptions thrown in each endpoint are caught by @ExceptionHandler methods in the same class. What i want to do is to catch these exceptions (such as OAuth2Exception, InvalidTokenException) in my @ExceptionHandler and then customize the output.

The raw exception output is something like {"error": "...", "error_description": "..."} which is not what i want. I expect the output to be {"code": 400, "message": "..."}.

stackoverflow

Most helpful comment

This is proving to be painful to implement, we have to add lots of code just to handle exceptions in a proper way, still not all of them are captured with this workaround, and yes, it is a workaround, because the solution is not 'Spring-ish' look at the amount of code we have to do/test (and still it is not fully working) and compare it with exception handling in the MVC layer for example, there should be a solution to capture all exceptions in the authorisation process, and a proper way to add custom responses for these endpoints. I would love to see this issue re-opend.

All 20 comments

This problem has been solved. Follow the workaround below:
1 extend OAuth2Exception to a new class, such as CustomOAuth2Exception. In the custom class, add some specific properties.
2 custom DefaultWebResponseExceptionTranslator and register the custom translator in AuthorizationServerConfiguration.
3 custom two jackson serializers annotated in OAuth2Exception and annotated your CustomOAuth2Exception with the two custom serializers.
4 use ObjectMapper to override initial serializers with custom serializers.

That's not really a workaround (WebResponseExceptionTranslator is provided for precisely this use case).

I'm sorry Dave, if that's not really workaround to solve this problem, what's the true. Because right now I am facing this problem and not solved yet.

You don't need a workaround you need WebResponseExceptionTranslator (it's what it was designed for).

I used steps, which @jzbjyb specified and I can see that not all OAuth2 errors are caught in custom DefaultWebResponseExceptionTranslator.
So in case I send invalid refresh token the error is caught in my custom translator, but for instance, when I send invalid access token the error is NOT caught in custom translator, but only in DefaultWebResponseExceptionTranslator.
Are there any other places where I can register custom exception translator?
Maybe you have some thoughts why do I have that not all errors/exceptions are caught in custom exception translator?

Thanks to @dsyer 's suggestions! I came across the same problem just as @isaranchuk 's description. When I send invalid access token, the error is not caught by my custom translator. What i know is that ExceptionHandler in oauth2's endpoint trigger translate() method of the translator class. But for InvalidTokenException, I don't know where it is handled.

@jzbjyb as I can see AuthorizationEndpoint extends AbstractEndpoint where exception translator is initialized, see.
Seems there is an additional place where we need to define exception translator.
@dsyer what do you think?

How to set CustomOAuth2Exception in DefaultWebResponseExceptionTranslator ?

In order to do this you need to extend DefaultWebResponseExceptionTranslator, so inheritance and polymorphism will be your friends.
Check @jzbjyb comment where you can find all steps to achieve appropriate result.

Can someone please elaborate on @jzbjyb 's step 4? on how to use OjectMapper ?

@jzbjyb How can i configure CustomOAuth2Exception,custom DefaultWebResponseExceptionTranslator in my security xml file.Can u elaborate your steps??

@dsyer how can i set WebResponseExceptionTranslator in my xml configuration file

This is proving to be painful to implement, we have to add lots of code just to handle exceptions in a proper way, still not all of them are captured with this workaround, and yes, it is a workaround, because the solution is not 'Spring-ish' look at the amount of code we have to do/test (and still it is not fully working) and compare it with exception handling in the MVC layer for example, there should be a solution to capture all exceptions in the authorisation process, and a proper way to add custom responses for these endpoints. I would love to see this issue re-opend.

Hi hassalih. Why is not springish in your opinion? When you have to customize a flow you add new handlers or translator or new service implementation. My needs were to customize only the response returned to the client compliant a specification.
I didn't need to change the flow, only change the response syntax.
If you have a better solution you are welcome.
Every algorithm is improvable infinitely for definition

Hi @lettierimarco
Look at the solution mentioned above, it is designed while looking at the problem from inside the code without looking at the outside world requirements, if I have a an exception and would like to send a response about it, then fine, I can send the response in a POJO and put in that POJO whatever properties/data I want, but here, you have to customise a hole lot of code to achieve a specific error design, I think the problem can be tracked down to this interface ( and many TokenEndpoint methods using it in the return statement)

public interface WebResponseExceptionTranslator { ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception; }

The question is why the output is ResponseEntity<OAuth2Exception> ? We are sending a RESPONSE to the outside world from our web service, the structure of the response has to be flexible enough to be manipulated, say a POJO class which can be extended easily without thinking about serialisers. Something like ResponseEntity<POJOClass> My point is that the way of calling the translator is correct, we need to call a translator, but the translator has to translate an inner exception to a POJO facing the outside world, the problem here, the translator is translating from an exception to another exception !! and your only solution is to extend that exception !!

@hassalih you can rewrite the DefaultOAuth2ExceptionRenderer and change the output with your format. Just change the
Object body = responseEntity.getBody();

to

OAuth2Exception exception = (OAuth2Exception) responseEntity.getBody(); CustomResponse<Object> response = new CustomResponse<Object>(exception.getOAuth2ErrorCode(), exception.getLocalizedMessage()); // You can define your own response format here. if (response != null) { writeWithMessageConverters(response, inputMessage, outputMessage); }

After rewrite, you need to register it to
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint" p:exceptionRenderer-ref="**exceptionRenderer**" /> <bean id="exceptionRenderer" class="com.***.security.oauth2.provider.error.DefaultOAuth2ExceptionRenderer" />

Then the output is pretty well as what you want.

Hi All ,
I am using Spring Security OAuth JWT token based implementation .
I want to handle Invalid Login Count if user hit oauth/token URI and enter invalid login credential ,At which place and How I can handle/check/catch invalid login exception to maintain login count for invalid attempts

Wow, this is probably one of the most difficult customization points I've ever experienced in Spring since it was called Interface21. There is no elegant way to handle this. Even inheritance can't be used as most methods are private.

Sorry for commenting on closed issue.
Probably easiest way is to make a custom OAuth2ExceptionJackson2Serializer, and then use it on your custom exception:

@JsonSerialize(using = MyOAuth2ExceptionJackson2Serializer.class)
public static class MyOAuth2Exception extends OAuth2Exception {
  // ...

@jzbjyb From your comments , I have learned much when I am facing the same question . Do you have a solution to handle all of the exceptions in OAuth2 to provide a uniform response format ? Thanks ahead .

Was this page helpful?
0 / 5 - 0 ratings