@Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
      throws AuthenticationException {
    SessionIdToken sessionIdToken = (SessionIdToken) token;
    final Subject subject =
        new Subject.Builder().sessionId(sessionIdToken.getSessionId()).buildSubject();
    final Session session = subject.getSession(false);
    if (session == null) {
      LOG.debug(
          "Invalid session {}. Either it has expired or did not exist.",
          sessionIdToken.getSessionId());
      return null;
    }

    final Object username = subject.getPrincipal();
    final User user = userService.load(String.valueOf(username));
    if (user == null) {
      LOG.debug("No user named {} found for session {}", username, sessionIdToken.getSessionId());
      return null;
    }
    if (user.isExternalUser() && !ldapAuthenticator.isEnabled()) {
      throw new LockedAccountException("LDAP authentication is currently disabled.");
    }

    if (LOG.isDebugEnabled()) {
      LOG.debug("Found session {} for user name {}", session.getId(), username);
    }

    @SuppressWarnings("unchecked")
    final MultivaluedMap<String, String> requestHeaders =
        (MultivaluedMap<String, String>) ThreadContext.get("REQUEST_HEADERS");
    // extend session unless the relevant header was passed.
    if (requestHeaders == null
        || !"true".equalsIgnoreCase(requestHeaders.getFirst("X-Graylog-No-Session-Extension"))) {
      session.touch();
    } else {
      LOG.debug("Not extending session because the request indicated not to.");
    }
    ThreadContext.bind(subject);

    return new SimpleAccount(user.getName(), null, "session authenticator");
  }
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {

    // Check request type.
    //
    if (!(request instanceof HttpServletRequest)) {
      raiseSecurityError(response, "Unexpected request class detected.");
      return;
    }
    HttpServletRequest hsr = (HttpServletRequest) request;

    // Try to match URL against exclude pattern.
    //
    String requestUri = hsr.getRequestURI();
    if (excludePattern != null && excludePattern.matcher(requestUri).matches()) {
      chain.doFilter(request, response);
      return;
    }

    // Extract security token from custom header.
    //
    String token = hsr.getHeader(SECURITY_TOKEN);
    logger.debug("Passed security token: " + token);

    // SecurityResource token must be present.
    //
    if (token == null) {
      logger.info("No token found in request header.");
      raiseSecurityError(response, "Null token detected");
      return;
    }

    // Check if the passed token is associated with a valid session.
    //
    try {
      Session session = SecurityUtils.getSecurityManager().getSession(new DefaultSessionKey(token));
      if (session == null) {
        logger.info("Unable to find a valid session using token.");
        raiseSecurityError(response, "Invalid session token.");
        return;
      }

      // Ensure that the last accessed timestamp gets updated. This should be made
      // internally by Shiro, but it looks like it is not working. Maybe the pattern
      // employed here to get the session is not canonical...
      //
      session.touch();

    } catch (SessionException se) {
      logger.info(se.getMessage());
      raiseSecurityError(response, "Invalid session token. Cause: " + se.getMessage());
      return;
    }

    Subject requestSubject = new Subject.Builder().sessionId(token).buildSubject();
    ThreadState threadState = new SubjectThreadState(requestSubject);
    threadState.bind();
    try {
      chain.doFilter(request, response);
    } finally {
      threadState.clear();
    }
  }