Saturday, April 18, 2020

Spring REST – JSON Response for Access Denied Request

Learn to return access denied response with error details in jSON format, from a REST API, in cases where principal should be pre-authenticated but is received null in AbstractPreAuthenticatedProcessingFilter.

1. Add Custom AuthenticationEntryPoint

This class is used by ExceptionTranslationFilter to commence an authentication scheme. In case you are using AbstractPreAuthenticatedProcessingFilter to handle pre-authenticated authentication requests as shown in custom token authentication example, by default all unauthenticated users are redirected to the default access denied page i.e. Http403ForbiddenEntryPoint.
The default behavior displays a access denied HTML page.
We can change the behavior defining our own custom AuthenticationEntryPoint. This authentication entry point is added to exceptionHandling() configuration.
  • ExceptionTranslationFilter is used to catch any Spring Security exceptions so that either an HTTP error response can be returned or an appropriate AuthenticationEntryPoint can be launched.
  • The AuthenticationEntryPoint will be called if the user requests a secure HTTP resource but they are not authenticated. This does the job of presenting the appropriate response to the user so that authentication can begin.
In given configuration, we are securing all URLs starting with "/api".
Spring security configuration
httpSecurity.
    antMatcher("/api/**")
    .csrf()
        .disable()
    .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()
        .addFilter(filter)
        /*.addFilterBefore(new ExceptionTranslationFilter(
            new Http403ForbiddenEntryPoint()),
                filter.getClass()
        )*/
        .authorizeRequests()
            .anyRequest()
            .authenticated();
 
//Exception handling configuration
 
httpSecurity
    .exceptionHandling()
    .authenticationEntryPoint((request, response, e) ->
    {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.getWriter().write(new JSONObject()
                .put("timestamp", LocalDateTime.now())
                .put("message", "Access denied")
                .toString());
    });
Please do not use AccessDeniedHandler as it is only applies to authenticated users where user does not required roles.

2. Demo

2.1. Without auth token

API Request
HTTP POST http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/1
 
Headers:
 
Content-Type    application/json
API Response
Response code - 403 Forbidden
 
{
    "message"   : "Access denied",
    "timestamp" : "2019-05-03T23:59:52.103"
}

2.2. With incorrect auth token

API Request
HTTP POST http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/1
 
Headers:
 
Content-Type    application/json
AUTH_API_KEY    123456
API Response
Response code - 403 Forbidden
 
{
    "message"   : "Access denied",
    "timestamp" : "2019-05-04T00:04:15.457"
}

2.2. With CORRECT auth token

API Request
HTTP POST http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/1
 
Headers:
 
Content-Type    application/json
AUTH_API_KEY    abcd123456
API Response
Response code - 200 OK
 
{
    //API response body
}
Drop me your questions related to convert access denied response from an Spring REST API to JSON response using custom authenticationEntryPoint.

No comments:

Post a Comment

How to DROP SEQUENCE in Oracle?

  Oracle  DROP SEQUENCE   overview The  DROP SEQUENCE  the statement allows you to remove a sequence from the database. Here is the basic sy...