@Override
  public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException {
    JWT_LOGGER.trace("Authentication request received for " + request.toString());
    if (!(request instanceof HttpServletRequest) && !(response instanceof HttpServletResponse)) {
      return Authentication.UNAUTHENTICATED;
    }

    String serializedJWT;
    HttpServletRequest req = (HttpServletRequest) request;
    // we'll skip the authentication for CORS preflight requests
    if (HttpMethod.OPTIONS.name().equalsIgnoreCase(req.getMethod())) {
      return Authentication.NOT_CHECKED;
    }
    serializedJWT = getJwtFromBearerAuthorization(req);
    if (serializedJWT == null) {
      serializedJWT = getJwtFromCookie(req);
    }
    if (serializedJWT == null) {
      String loginURL = _authenticationProviderUrlGenerator.apply(req);
      JWT_LOGGER.info("No JWT token found, sending redirect to " + loginURL);
      try {
        ((HttpServletResponse) response).sendRedirect(loginURL);
        return Authentication.SEND_CONTINUE;
      } catch (IOException e) {
        JWT_LOGGER.error("Couldn't authenticate request", e);
        throw new ServerAuthException(e);
      }
    } else {
      try {
        SignedJWT jwtToken = SignedJWT.parse(serializedJWT);
        String userName = jwtToken.getJWTClaimsSet().getSubject();
        request.setAttribute(JWT_TOKEN_REQUEST_ATTRIBUTE, serializedJWT);
        UserIdentity identity = login(userName, jwtToken, request);
        if (identity == null) {
          ((HttpServletResponse) response).setStatus(HttpStatus.UNAUTHORIZED_401);
          return Authentication.SEND_FAILURE;
        } else {
          return new UserAuthentication(getAuthMethod(), identity);
        }
      } catch (ParseException pe) {
        String loginURL = _authenticationProviderUrlGenerator.apply(req);
        JWT_LOGGER.warn("Unable to parse the JWT token, redirecting back to the login page", pe);
        try {
          ((HttpServletResponse) response).sendRedirect(loginURL);
        } catch (IOException e) {
          throw new ServerAuthException(e);
        }
      }
    }

    return Authentication.SEND_FAILURE;
  }
@Test
  public void testRedirect() throws IOException, ServerAuthException {
    JwtAuthenticator authenticator = new JwtAuthenticator(TOKEN_PROVIDER, JWT_TOKEN);

    HttpServletRequest request = mock(HttpServletRequest.class);
    expect(request.getMethod()).andReturn(HttpMethod.GET.asString());
    expect(request.getQueryString()).andReturn(null);
    expect(request.getHeader(HttpHeader.AUTHORIZATION.asString())).andReturn(null);
    expect(request.getCookies()).andReturn(new Cookie[] {});
    expect(request.getRequestURL()).andReturn(new StringBuffer(CRUISE_CONTROL_ENDPOINT));

    HttpServletResponse response = mock(HttpServletResponse.class);
    response.sendRedirect(TOKEN_PROVIDER.replace(JwtAuthenticator.REDIRECT_URL, CRUISE_CONTROL_ENDPOINT));
    expectLastCall().andVoid();

    replay(request, response);
    Authentication actualAuthentication = authenticator.validateRequest(request, response, true);
    verify(request, response);
    assertEquals(Authentication.SEND_CONTINUE, actualAuthentication);
  }