Grails Spring Security Rest Custom Authentication Failure Response
Contents
The grails spring security rest plugin only returns a 401 status code for failed authentication. This creates a problem because you do not know the specific reason for failure and are forced to show the user a generic error message. The issue can be solved by overriding RestAuthenticationFailureHandler and registering your own implementation as a bean in resources.groovy
. Grails plugins compile first allowing you to override classes as needed. In particular you override this method:
void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
log.debug "Setting status code to ${statusCode}"
response.setStatus(statusCode)
response.addHeader('WWW-Authenticate', 'Bearer')
}
And generate the response body based on the type of AuthenticationException
as shwon below:
void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
response.setStatus(statusCode)
response.addHeader('WWW-Authenticate', 'Bearer')
if (exception instanceof AccountExpiredException) {
msg = g.message(code: "springSecurity.errors.login.expired")
} else if (exception instanceof CredentialsExpiredException) {
msg = g.message(code: "springSecurity.errors.login.passwordExpired")
} else if (exception instanceof DisabledException) {
msg = g.message(code: "springSecurity.errors.login.disabled")
} else if (exception instanceof LockedException) {
msg = g.message(code: "springSecurity.errors.login.locked")
} else {
msg = g.message(code: "springSecurity.errors.login.fail")
}
PrintWriter out = response.getWriter()
response.setContentType("aplication/json")
response.setCharacterEncoding("UTF-8")
out.print(new JsonBuilder([message: msg]).toString())
out.flush()
}
And there you have it. A more pleasant response for the user.