5

I am using Spring to expose and API in a larger application. When accessing endpoints that are behind an authenticated() configuration, my application throws an ugly Tomcat HTML error because of the following code:

@Component
public class EntryPointUnauthorizedHandler implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
            AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied");
    }
}

However, since this is an API I only want to return JSON, like in the rest of my API. For normal exception handling I set up the following @ControllerAdvice:

@ControllerAdvice
public class DefaultExceptionHandler extends ResponseEntityExceptionHandler {

    /**
     * Default internal BadCredentialsException handler. Respond with 401 Unauthorized
     */
    @ExceptionHandler(value = BadCredentialsException.class)
    public ResponseEntity<Object> handleBadCredentialsException(BadCredentialsException e, WebRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return handleExceptionInternal(e, null, headers, HttpStatus.UNAUTHORIZED, request);
    }

    /**
     * Fallback default exception handler. Respond with 500
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<Object> handleFallbackException(Exception e, WebRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return handleExceptionInternal(e, null, headers, HttpStatus.INTERNAL_SERVER_ERROR, request);
    }

    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body,
            HttpHeaders headers, HttpStatus status, WebRequest request) {

        final ErrorResponse error = new ErrorResponse(status, ex.getMessage());

        if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
            request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
        }

        return new ResponseEntity<Object>(error, headers, status);
    }
}

Where ErrorResponse is my own little response wrapper, holding the HttpStatus code and exception message. This gets formatted into JSON fine:

{
    "status": 401,
    "message": "Bad credentials"
}

How can I make sure my AuthenticationEntryPoint which only has a request and response object to return a similar formatted error, instead of the ugly Tomcat HTML page.

1

1 Answer 1

0

You can change the HttpServletResponse as you want. Take a look at: https://stackoverflow.com/a/19788700/1490806

Sign up to request clarification or add additional context in comments.

2 Comments

Writing manual JSON strings or using an ObjectMapper feels very ugly and hacky. Is there really no proper way to do this? It feels like im using Spring incorrectly. What is the point of defining your exception handling in 1 place if you need to do it again in this AuthenticationEntryPoint ?
The spring security filter happens before of spring dispatcher servlet. So I guess spring has no control about exceptions occurred on security filter chain. visola.github.io/img/blog/spring-security-architecture.png I don't know any other way to do that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.