Story short: https://github.com/melardev/JavaSpringBootOAuth2JwtCrudPagination.git
After reading @pakkk response I was not agree, so I decided to try my own thoughs, which also fail, so I decided to take a look at the Spring Security source code itself, what happens is this:
There is a Filter which gets called very very early, the OAuth2AuthenticationProcessingFilter.
This filter tries to extract the JWT from the header, if an exception is thrown it calls
its authenticationEntryPoint.commence() (@pakk was right here)
I have tried to add a Filter to check if it gets called when the Jwt is invalid or present, and it did not, so, adding a custom filter to change the response won't work.
Then I looked where the OAuth2AuthenticationProcessingFilter is configured, and I found out that it is setup on ResourceServerSecurityConfigurer::configure(HttpSecurity http).
With that said, let's see how we can hook into the process.
It turns out to be very easy, since you will be extending the ResourceServerConfigurerAdapter class in your Resource Server application:
@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
// ....
}
You go ahead and override:
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
super.configure(resources);
}
As you can see, yes! you have access to ResourceServerSecurityConfigurer, so now what?
well let's replace the default entry point by ours:
@Autowired
private AuthenticationEntryPoint oauthEntryPoint;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
super.configure(resources);
resources.authenticationEntryPoint(oauthEntryPoint);
}
For a complete source code with example look at:
https://github.com/melardev/JavaSpringBootOAuth2JwtCrudPagination.git
Without this steps, at least for me it wouldn't work, the response provided by @pakkk does not work for me, I checked on the debugger, and by default the entry point used is not ours, even using:
http.and().exceptionHandling().authenticationEntryPoint(oauthEntryPoint)
which was the first thing I tested, to make it work you have to change the entry point directly from the ResourceServerSecurityConfigurer class.
And this is my entrypoint: notice I am sending the ErrorResponse object which is my own class, so I have full control over the response:
@Component
public class OAuthEntryPoint implements AuthenticationEntryPoint {
@Autowired
ObjectMapper mapper;
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
ServletServerHttpResponse res = new ServletServerHttpResponse(httpServletResponse);
res.setStatusCode(HttpStatus.FORBIDDEN);
res.getServletResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
res.getBody().write(mapper.writeValueAsString(new ErrorResponse("You must authenticated")).getBytes());
}
}