I was wondering if I could customize the following authorization error:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
I get it when the user request does not have permissions. And I would like to customize it to be quite similar than Spring Boot error:
{
"timestamp":1445441285803,
"status":401,
"error":"Unauthorized",
"message":"Bad credentials",
"path":"/oauth/token"
}
Could it be possible?
Many thanks.
The accepted answer does not work for me using Oauth2. After some research, the exception translator solution works.
Basically, you need to create a WebResponseExceptionTranslator
and register it as your exception translator.
First, create a WebResponseExceptionTranslator
bean:
@Slf4j
@Configuration
public class Oauth2ExceptionTranslatorConfiguration {
@Bean
public WebResponseExceptionTranslator oauth2ResponseExceptionTranslator() {
return new DefaultWebResponseExceptionTranslator() {
@Override
public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
ResponseEntity<OAuth2Exception> responseEntity = super.translate(e);
OAuth2Exception body = responseEntity.getBody();
HttpStatus statusCode = responseEntity.getStatusCode();
body.addAdditionalInformation("timestamp", dateTimeFormat.format(clock.instant()))
body.addAdditionalInformation("status", body.getHttpErrorCode().toString())
body.addAdditionalInformation("message", body.getMessage())
body.addAdditionalInformation("code", body.getOAuth2ErrorCode().toUpperCase())
HttpHeaders headers = new HttpHeaders();
headers.setAll(responseEntity.getHeaders().toSingleValueMap());
// do something with header or response
return new ResponseEntity<>(body, headers, statusCode);
}
};
}
}
Now you need to change your Oauth2 configuration to register the bean WebResponseExceptionTranslator
:
@Slf4j
@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private ClientDetailsServiceBuilder builder;
@Autowired
private WebResponseExceptionTranslator oauth2ResponseExceptionTranslator;
@Autowired
private UserDetailsService userDetailsService;
@Override
public void configure(ClientDetailsServiceConfigurer clients) {
clients.setBuilder(builder);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(
Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.exceptionTranslator(oauth2ResponseExceptionTranslator);
}
}
The final result will be:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource",
"code": "UNAUTHORIZED",
"message": "Full authentication is required to access this resource",
"status": "401",
"timestamp": "2018-06-28T23:55:28.86Z"
}
You can see that I not remove the error
and error_description
from the original body of OAuth2Exception. I recommend to maintain them because these two fields are following the OAuth2 specification. See the RFC and OAuth2 API definitions for more details.
You can also customize the result: override the error
or error_description
(just calling addAdditionalInformation
), identify a specific exception with instance of
to return a different json result, etc. But there are restriction too: if you want to define some field as integer
, I don't think it's possible, because the addAdditionalInformation
method only accepts String
as type.