Careeroza
AccessDeniedHandler
A JSON 403
@Component
public class JsonAccessDeniedHandler implements AccessDeniedHandler {
private final ObjectMapper mapper;
public JsonAccessDeniedHandler(ObjectMapper mapper) {
this.mapper = mapper;
}
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException ex) throws IOException {
String message = ex instanceof CsrfException
? "Invalid or missing CSRF token"
: "You do not have permission to access this resource";
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
mapper.writeValue(response.getOutputStream(),
new ApiError(403, "Forbidden", message, request.getRequestURI()));
}
}Note: Missing or invalid CSRF tokens also arrive here (CsrfException is an AccessDeniedException), which is why a bad CSRF token gives 403, not 401.
Registering Both Handlers
@Bean
SecurityFilterChain api(HttpSecurity http,
JsonAuthenticationEntryPoint entryPoint,
JsonAccessDeniedHandler deniedHandler) throws Exception {
http
// ... cors, csrf, session, authorizeHttpRequests, JWT filter as before
.exceptionHandling(ex -> ex
.authenticationEntryPoint(entryPoint)
.accessDeniedHandler(deniedHandler));
return http.build();
}Example
curl -i localhost:8080/api/admin/users -H "Authorization: Bearer $ASHA_TOKEN"Example output
HTTP/1.1 403 Forbidden
Content-Type: application/json
{"status":403,"error":"Forbidden","message":"You do not have permission to access this resource","path":"/api/admin/users"}