0

I'm using Crowd's Java integration into Spring Security which involves configuring Crowds SimpleAuthenticationManager as an authentication provider. The SimpleAuthenticationManager throws several exceptions when a user fails to be authenticated based on why they could not be authenticated. I was wondering within Spring Security how I can capture that exception and return a JSON response to the client?

I've tried adding an AccessDeniedHandler however this receives a new exception which does not have the original exception as a cause.

binarylegit
  • 319
  • 1
  • 4
  • 15

2 Answers2

0

I missed this post when googling and searching StackOverflow: Spring security 3 http-basic authentication-success-handler

Turns out, as this other question/answer points out, you need to extend BasicAuthenticationFilter and implement the onUnsuccessfulAuthentication() method. Then add it to your security configuration with:

http.addFilter(new CustomBasicAuthenticationFilter(authenticationManagerBean()))

EDIT Actually it appears that Spring is still wrapping the exceptions at this point, however you are able to get some slightly more specific exceptions, which is helpful.

binarylegit
  • 319
  • 1
  • 4
  • 15
-1

You can extends ResponseEntityExceptionHandler with the @ControllerAdvice annotation. This will capture exception and you can handle and send a custom response. Example:

@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(CustomExceptionHandler.class);

    public CustomExceptionHandler() {
    }

    // overriding an exception that already is been handled in ResponseEntityExceptionHandler
    @Override
    protected ResponseEntity<Object> handleMissingPathVariable(MissingPathVariableException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
        log.warn(ex.toString());

        final String parameter = ex.getParameter().getParameterName();
        final String detailMessage = ex.getMessage();
        final String message = "Parameter " + parameter + " is missing.";

        final ErrorMessageDTO result = new ErrorMessageDTO(HttpStatus.BAD_REQUEST, message, parameter, detailMessage, null);
        return ResponseEntity.badRequest().body(result);
    }

    // Custom handle to intercept BadCredentialsException
    @ExceptionHandler(BadCredentialsException.class)
    @ResponseBody
    ResponseEntity<Object> handleBadCredentialsException(HttpServletRequest req,
            BadCredentialsException ex) {
        log.warn(ex.toString());

        final ErrorMessageDTO result = new ErrorMessageDTO(HttpStatus.UNAUTHORIZED, ex.getMessage());
        return ResponseEntity.badRequest().body(result);
    }

}
Glim
  • 361
  • 1
  • 10
  • Unfortunately I don't think this will work as the authentication happens before the controller method is actually called so an @ExceptionHandler won't pick up the exceptions that are thrown by it. – binarylegit Apr 27 '18 at 22:09
  • if you are using a stateless aproach, with oauth2, jwt, basic authentication ow something like that, the authentication error is thrown when the rest request is called (and you catch it right before even enter on the controller) – Glim Apr 29 '18 at 00:35