/** Validate the token and return it. */
  private PersistentToken getPersistentToken(String[] cookieTokens) {
    if (cookieTokens.length != 2) {
      throw new InvalidCookieException(
          "Cookie token did not contain "
              + 2
              + " tokens, but contained '"
              + Arrays.asList(cookieTokens)
              + "'");
    }
    String presentedSeries = cookieTokens[0];
    String presentedToken = cookieTokens[1];
    PersistentToken token = persistentTokenRepository.findOne(presentedSeries);

    if (token == null) {
      // No series match, so we can't authenticate using this cookie
      throw new RememberMeAuthenticationException(
          "No persistent token found for series id: " + presentedSeries);
    }

    // We have a match for this user/series combination
    log.info("presentedToken={} / tokenValue={}", presentedToken, token.getTokenValue());
    if (!presentedToken.equals(token.getTokenValue())) {
      // Token doesn't match series value. Delete this session and throw an exception.
      persistentTokenRepository.delete(token);
      throw new CookieTheftException(
          "Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.");
    }

    if (token.getTokenDate().plusDays(TOKEN_VALIDITY_DAYS).isBefore(LocalDate.now())) {
      persistentTokenRepository.delete(token);
      throw new RememberMeAuthenticationException("Remember-me login has expired");
    }
    return token;
  }
 private void addCookie(
     PersistentToken token, HttpServletRequest request, HttpServletResponse response) {
   setCookie(
       new String[] {token.getSeries(), token.getTokenValue()},
       TOKEN_VALIDITY_SECONDS,
       request,
       response);
 }
  @Override
  @Transactional
  protected UserDetails processAutoLoginCookie(
      String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) {

    PersistentToken token = getPersistentToken(cookieTokens);
    String login = token.getUser().getLogin();

    // Token also matches, so login is valid. Update the token value, keeping the *same* series
    // number.
    log.debug(
        "Refreshing persistent login token for user '{}', series '{}'", login, token.getSeries());
    token.setTokenDate(new LocalDate());
    token.setTokenValue(generateTokenData());
    token.setIpAddress(request.getRemoteAddr());
    token.setUserAgent(request.getHeader("User-Agent"));
    try {
      persistentTokenRepository.saveAndFlush(token);
      addCookie(token, request, response);
    } catch (DataAccessException e) {
      log.error("Failed to update token: ", e);
      throw new RememberMeAuthenticationException("Autologin failed due to data access problem", e);
    }
    return getUserDetailsService().loadUserByUsername(login);
  }
  @Override
  protected void onLoginSuccess(
      HttpServletRequest request,
      HttpServletResponse response,
      Authentication successfulAuthentication) {
    String login = successfulAuthentication.getName();

    log.debug("Creating new persistent login for user {}", login);
    PersistentToken token =
        userRepository
            .findOneByLogin(login)
            .map(
                u -> {
                  PersistentToken t = new PersistentToken();
                  t.setSeries(generateSeriesData());
                  t.setUser(u);
                  t.setTokenValue(generateTokenData());
                  t.setTokenDate(new LocalDate());
                  t.setIpAddress(request.getRemoteAddr());
                  t.setUserAgent(request.getHeader("User-Agent"));
                  return t;
                })
            .orElseThrow(
                () ->
                    new UsernameNotFoundException(
                        "User " + login + " was not found in the database"));
    try {
      persistentTokenRepository.saveAndFlush(token);
      addCookie(token, request, response);
    } catch (DataAccessException e) {
      log.error("Failed to save persistent token ", e);
    }
  }