public void testGetToken() throws Exception {
    AuthenticationFilter filter = new AuthenticationFilter();
    try {
      FilterConfig config = Mockito.mock(FilterConfig.class);
      Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE))
          .thenReturn(DummyAuthenticationHandler.class.getName());
      Mockito.when(config.getInitParameter(AuthenticationFilter.SIGNATURE_SECRET))
          .thenReturn("secret");
      Mockito.when(config.getInitParameterNames())
          .thenReturn(
              new Vector(
                      Arrays.asList(
                          AuthenticationFilter.AUTH_TYPE, AuthenticationFilter.SIGNATURE_SECRET))
                  .elements());
      filter.init(config);

      AuthenticationToken token =
          new AuthenticationToken("u", "p", DummyAuthenticationHandler.TYPE);
      token.setExpires(System.currentTimeMillis() + 1000);
      Signer signer = new Signer("secret".getBytes());
      String tokenSigned = signer.sign(token.toString());

      Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
      HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
      Mockito.when(request.getCookies()).thenReturn(new Cookie[] {cookie});

      AuthenticationToken newToken = filter.getToken(request);

      assertEquals(token.toString(), newToken.toString());
    } finally {
      filter.destroy();
    }
  }
 /**
  * Returns the {@link AuthenticationToken} for the request.
  *
  * <p>It looks at the received HTTP cookies and extracts the value of the {@link
  * AuthenticatedURL#AUTH_COOKIE} if present. It verifies the signature and if correct it creates
  * the {@link AuthenticationToken} and returns it.
  *
  * <p>If this method returns <code>null</code> the filter will invoke the configured {@link
  * AuthenticationHandler} to perform user authentication.
  *
  * @param request request object.
  * @return the Authentication token if the request is authenticated, <code>null</code> otherwise.
  * @throws IOException thrown if an IO error occurred.
  * @throws AuthenticationException thrown if the token is invalid or if it has expired.
  */
 protected AuthenticationToken getToken(HttpServletRequest request)
     throws IOException, AuthenticationException {
   AuthenticationToken token = null;
   String tokenStr = null;
   Cookie[] cookies = request.getCookies();
   if (cookies != null) {
     for (Cookie cookie : cookies) {
       if (cookie.getName().equals(AuthenticatedURL.AUTH_COOKIE)) {
         tokenStr = cookie.getValue();
         try {
           tokenStr = signer.verifyAndExtract(tokenStr);
         } catch (SignerException ex) {
           throw new AuthenticationException(ex);
         }
         break;
       }
     }
   }
   if (tokenStr != null) {
     token = AuthenticationToken.parse(tokenStr);
     if (!token.getType().equals(authHandler.getType())) {
       throw new AuthenticationException("Invalid AuthenticationToken type");
     }
     if (token.isExpired()) {
       throw new AuthenticationException("AuthenticationToken expired");
     }
   }
   return token;
 }
  public void testDoFilterAuthenticated() throws Exception {
    AuthenticationFilter filter = new AuthenticationFilter();
    try {
      FilterConfig config = Mockito.mock(FilterConfig.class);
      Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE))
          .thenReturn(DummyAuthenticationHandler.class.getName());
      Mockito.when(config.getInitParameterNames())
          .thenReturn(new Vector(Arrays.asList(AuthenticationFilter.AUTH_TYPE)).elements());
      filter.init(config);

      HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
      Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://foo:8080/bar"));

      AuthenticationToken token = new AuthenticationToken("u", "p", "t");
      token.setExpires(System.currentTimeMillis() + 1000);
      Signer signer = new Signer("alfredo".getBytes());
      String tokenSigned = signer.sign(token.toString());

      Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
      Mockito.when(request.getCookies()).thenReturn(new Cookie[] {cookie});

      HttpServletResponse response = Mockito.mock(HttpServletResponse.class);

      FilterChain chain = Mockito.mock(FilterChain.class);

      Mockito.doAnswer(
              new Answer() {
                @Override
                public Object answer(InvocationOnMock invocation) throws Throwable {
                  Object[] args = invocation.getArguments();
                  HttpServletRequest request = (HttpServletRequest) args[0];
                  assertEquals("u", request.getRemoteUser());
                  assertEquals("p", request.getUserPrincipal().getName());
                  return null;
                }
              })
          .when(chain)
          .doFilter(Mockito.<ServletRequest>anyObject(), Mockito.<ServletResponse>anyObject());

      filter.doFilter(request, response, chain);

    } finally {
      filter.destroy();
    }
  }
  /**
   * If the request has a valid authentication token it allows the request to continue to the target
   * resource, otherwise it triggers an authentication sequence using the configured {@link
   * AuthenticationHandler}.
   *
   * @param request the request object.
   * @param response the response object.
   * @param filterChain the filter chain object.
   * @throws IOException thrown if an IO error occurred.
   * @throws ServletException thrown if a processing error occurred.
   */
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
      throws IOException, ServletException {
    boolean unauthorizedResponse = true;
    int errCode = HttpServletResponse.SC_UNAUTHORIZED;
    AuthenticationException authenticationEx = null;
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    boolean isHttps = "https".equals(httpRequest.getScheme());
    try {
      boolean newToken = false;
      AuthenticationToken token;
      try {
        token = getToken(httpRequest);
      } catch (AuthenticationException ex) {
        LOG.warn("AuthenticationToken ignored: " + ex.getMessage());
        // will be sent back in a 401 unless filter authenticates
        authenticationEx = ex;
        token = null;
      }
      if (authHandler.managementOperation(token, httpRequest, httpResponse)) {
        if (token == null) {
          if (LOG.isDebugEnabled()) {
            LOG.debug("Request [{}] triggering authentication", getRequestURL(httpRequest));
          }
          token = authHandler.authenticate(httpRequest, httpResponse);
          if (token != null && token.getExpires() != 0 && token != AuthenticationToken.ANONYMOUS) {
            token.setExpires(System.currentTimeMillis() + getValidity() * 1000);
          }
          newToken = true;
        }
        if (token != null) {
          unauthorizedResponse = false;
          if (LOG.isDebugEnabled()) {
            LOG.debug(
                "Request [{}] user [{}] authenticated",
                getRequestURL(httpRequest),
                token.getUserName());
          }
          final AuthenticationToken authToken = token;
          httpRequest =
              new HttpServletRequestWrapper(httpRequest) {

                @Override
                public String getAuthType() {
                  return authToken.getType();
                }

                @Override
                public String getRemoteUser() {
                  return authToken.getUserName();
                }

                @Override
                public Principal getUserPrincipal() {
                  return (authToken != AuthenticationToken.ANONYMOUS) ? authToken : null;
                }
              };
          if (newToken && !token.isExpired() && token != AuthenticationToken.ANONYMOUS) {
            String signedToken = signer.sign(token.toString());
            createAuthCookie(
                httpResponse,
                signedToken,
                getCookieDomain(),
                getCookiePath(),
                token.getExpires(),
                isHttps);
          }
          filterChain.doFilter(httpRequest, httpResponse);
        }
      } else {
        unauthorizedResponse = false;
      }
    } catch (AuthenticationException ex) {
      // exception from the filter itself is fatal
      errCode = HttpServletResponse.SC_FORBIDDEN;
      authenticationEx = ex;
      LOG.warn("Authentication exception: " + ex.getMessage(), ex);
    }
    if (unauthorizedResponse) {
      if (!httpResponse.isCommitted()) {
        createAuthCookie(httpResponse, "", getCookieDomain(), getCookiePath(), 0, isHttps);
        if (authenticationEx == null) {
          httpResponse.sendError(errCode, "Authentication required");
        } else {
          httpResponse.sendError(errCode, authenticationEx.getMessage());
        }
      }
    }
  }
  private void _testDoFilterAuthentication(boolean withDomainPath) throws Exception {
    AuthenticationFilter filter = new AuthenticationFilter();
    try {
      FilterConfig config = Mockito.mock(FilterConfig.class);
      Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE))
          .thenReturn(DummyAuthenticationHandler.class.getName());
      Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TOKEN_VALIDITY))
          .thenReturn("1000");
      Mockito.when(config.getInitParameter(AuthenticationFilter.SIGNATURE_SECRET))
          .thenReturn("secret");
      Mockito.when(config.getInitParameterNames())
          .thenReturn(
              new Vector(
                      Arrays.asList(
                          AuthenticationFilter.AUTH_TYPE,
                          AuthenticationFilter.AUTH_TOKEN_VALIDITY,
                          AuthenticationFilter.SIGNATURE_SECRET))
                  .elements());

      if (withDomainPath) {
        Mockito.when(config.getInitParameter(AuthenticationFilter.COOKIE_DOMAIN))
            .thenReturn(".foo.com");
        Mockito.when(config.getInitParameter(AuthenticationFilter.COOKIE_PATH)).thenReturn("/bar");
        Mockito.when(config.getInitParameterNames())
            .thenReturn(
                new Vector(
                        Arrays.asList(
                            AuthenticationFilter.AUTH_TYPE,
                            AuthenticationFilter.AUTH_TOKEN_VALIDITY,
                            AuthenticationFilter.SIGNATURE_SECRET,
                            AuthenticationFilter.COOKIE_DOMAIN,
                            AuthenticationFilter.COOKIE_PATH))
                    .elements());
      }

      filter.init(config);

      HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
      Mockito.when(request.getParameter("authenticated")).thenReturn("true");
      Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://foo:8080/bar"));
      Mockito.when(request.getQueryString()).thenReturn("authenticated=true");

      HttpServletResponse response = Mockito.mock(HttpServletResponse.class);

      FilterChain chain = Mockito.mock(FilterChain.class);

      final boolean[] calledDoFilter = new boolean[1];

      Mockito.doAnswer(
              new Answer() {
                @Override
                public Object answer(InvocationOnMock invocation) throws Throwable {
                  calledDoFilter[0] = true;
                  return null;
                }
              })
          .when(chain)
          .doFilter(Mockito.<ServletRequest>anyObject(), Mockito.<ServletResponse>anyObject());

      final Cookie[] setCookie = new Cookie[1];
      Mockito.doAnswer(
              new Answer() {
                @Override
                public Object answer(InvocationOnMock invocation) throws Throwable {
                  Object[] args = invocation.getArguments();
                  setCookie[0] = (Cookie) args[0];
                  return null;
                }
              })
          .when(response)
          .addCookie(Mockito.<Cookie>anyObject());

      filter.doFilter(request, response, chain);

      assertNotNull(setCookie[0]);
      assertEquals(AuthenticatedURL.AUTH_COOKIE, setCookie[0].getName());
      assertTrue(setCookie[0].getValue().contains("u="));
      assertTrue(setCookie[0].getValue().contains("p="));
      assertTrue(setCookie[0].getValue().contains("t="));
      assertTrue(setCookie[0].getValue().contains("e="));
      assertTrue(setCookie[0].getValue().contains("s="));
      assertTrue(calledDoFilter[0]);

      Signer signer = new Signer("secret".getBytes());
      String value = signer.verifyAndExtract(setCookie[0].getValue());
      AuthenticationToken token = AuthenticationToken.parse(value);
      assertEquals(System.currentTimeMillis() + 1000 * 1000, token.getExpires(), 100);

      if (withDomainPath) {
        assertEquals(".foo.com", setCookie[0].getDomain());
        assertEquals("/bar", setCookie[0].getPath());
      } else {
        assertNull(setCookie[0].getDomain());
        assertNull(setCookie[0].getPath());
      }
    } finally {
      filter.destroy();
    }
  }