springjspspring-securitycasspring-security-cas

Spring Security CAS: show client error on login.jsp


I'm using Spring Security with CAS and have the following issue. When the authentication error is thrown from CAS Server (e.g. invalid username/password) it is shown well in form and is displayed correctly using tag:

<form:errors path="*" id="msg" cssClass="alert alert-danger" element="div"/>

But in cases when CAS Server returns success and the AuthenticationException is thrown on CAS Client none of the errors are displayed as basically CAS Client redirects back to http://localhost:8080/cas/login?service=http%3A%2F%2Flocalhost%3A8080%2Fj_spring_cas_security_check

So I can't really display what went wrong on the client side. Is it somehow possible to display an error from client on the same JSP in case it throws AuthenticationException?


Solution

  • Not sure if that's the super clean and right way to do it, but the way I've managed to do that is using cookies.

    All I had to do is to extend SimpleUrlAuthenticationFailureHandler, get there last authentication exception using request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) and write my custom error code cookie. The code is in Scala, but is pretty straightforward:

    class CookieAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler{
    
      val clientErrorCookie = "clientError"
    
      override def onAuthenticationFailure(request: HttpServletRequest, response: HttpServletResponse, exception: AuthenticationException): Unit = {
        val authenticationException = SecurityUtility.getSessionAuthException(request).getOrElse(exception)
    
        ClientErrors.values
          .filter(clientError => clientError.exceptionClass.equals(authenticationException.getClass))
          .foreach(clientError => response.addCookie(new Cookie(clientErrorCookie, clientError.errorCode)))
    
        super.onAuthenticationFailure(request, response, authenticationException)
      }
    }
    

    Then, on the CAS server side I've displayed error on JSP in the following way:

    <c:set var="clientErrorCookie" value="clientError"/>
    <c:if test="${cookie.containsKey(clientErrorCookie)}">
                        <div class="alert alert-danger">
                            <spring:message code="error.client.authentication.${cookie.get(clientErrorCookie).value}"
                                            text="Client authentication error"/>
                        </div>
                    </c:if>
    

    And after the page is loaded and error is shown, I've just removed that cookie in JS:

    function deleteCookie(name) {
                document.cookie = name + '=; Path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
            }
    
    $(document).ready(function(){
              deleteCookie('${clientErrorCookie}');
            }