spring-projects/spring-security · error · RememberMeAuthenticationException

Autologin failed due to data access problem

Error message

Autologin failed due to data access problem

What it means

PersistentTokenBasedRememberMeServices wraps any exception raised while persisting the rotated remember-me token (series/token value/date) into a RememberMeAuthenticationException with this message. The library cannot guarantee auto-login correctness if the new token cannot be written, so it aborts the remember-me authentication. The original data-access exception is logged via logger.error("Failed to update token: ", ex).

Source

Thrown at web/src/main/java/org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.java:133

					"PersistentTokenBasedRememberMeServices.cookieStolen",
					"Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack."));
		}
		if (token.getDate().getTime() + getTokenValiditySeconds() * 1000L < System.currentTimeMillis()) {
			throw new RememberMeAuthenticationException("Remember-me login has expired");
		}
		// Token also matches, so login is valid. Update the token value, keeping the
		// *same* series number.
		this.logger.debug(LogMessage.format("Refreshing persistent login token for user '%s', series '%s'",
				token.getUsername(), token.getSeries()));
		PersistentRememberMeToken newToken = new PersistentRememberMeToken(token.getUsername(), token.getSeries(),
				generateTokenData(), new Date());
		try {
			this.tokenRepository.updateToken(newToken.getSeries(), newToken.getTokenValue(), newToken.getDate());
			addCookie(newToken, request, response);
		}
		catch (Exception ex) {
			this.logger.error("Failed to update token: ", ex);
			throw new RememberMeAuthenticationException("Autologin failed due to data access problem");
		}
		return getUserDetailsService().loadUserByUsername(token.getUsername());
	}

	/**
	 * Creates a new persistent login token with a new series number, stores the data in
	 * the persistent token repository and adds the corresponding cookie to the response.
	 *
	 */
	@Override
	protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication successfulAuthentication) {
		String username = successfulAuthentication.getName();
		this.logger.debug(LogMessage.format("Creating new persistent login for user %s", username));
		PersistentRememberMeToken persistentToken = new PersistentRememberMeToken(username, generateSeriesData(),
				generateTokenData(), new Date());
		try {
			this.tokenRepository.createNewToken(persistentToken);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Check application logs for the 'Failed to update token: ' cause to identify the underlying data-access exception
  2. Verify the persistent_logins table exists with columns username, series, token_value, last_used matching the schema in the reference docs
  3. Confirm the DataSource used by JdbcTokenRepositoryImpl (or custom PersistentTokenRepository) is healthy and reachable
  4. If using an in-memory/custom repository, ensure updateToken handles unknown series gracefully and that concurrent logins are not deleting rows
  5. As a last resort clear stale cookies and have users log in again

Example fix

// before
@Bean
public PersistentTokenRepository tokenRepository(DataSource ds) {
    JdbcTokenRepositoryImpl repo = new JdbcTokenRepositoryImpl();
    repo.setDataSource(ds); // table missing -> updateToken fails at autologin
    return repo;
}
// after
@Bean
public PersistentTokenRepository tokenRepository(DataSource ds) {
    JdbcTokenRepositoryImpl repo = new JdbcTokenRepositoryImpl();
    repo.setDataSource(ds);
    repo.setCreateTableOnStartup(true); // creates persistent_logins if absent
    return repo;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify repository/table before autologin is relied upon
try (Connection c = dataSource.getConnection();
     PreparedStatement ps = c.prepareStatement("SELECT 1 FROM persistent_logins LIMIT 1")) {
    ps.executeQuery();
} catch (SQLException e) {
    throw new IllegalStateException("persistent_logins table unavailable", e);
}

Type guard

boolean isTokenRepositoryHealthy(PersistentTokenRepository repo) {
    return repo != null; // plus a DB connectivity probe at startup
}

Try / catch

try {
    SecurityContext ctx = SecurityContextHolder.getContext();
    // ... auto-login flow
} catch (RememberMeAuthenticationException e) {
    logger.warn("Remember-me autologin failed; falling back to login page", e);
    response.sendRedirect("/login");
}

Prevention

When it happens

Trigger: processAutoLoginCookie calls tokenRepository.updateToken(series, tokenValue, date) during automatic login; if that call throws (DB down, table missing, constraint violation, connection timeout), the catch block rethrows this RememberMeAuthenticationException.

Common situations: Remember-me persistence table (persistent_logins) missing or schema mismatch; database connection pool exhausted or DB unreachable; the series row was deleted concurrently (another device logged in and rotated the token); JdbcTemplate token repository misconfigured with a broken DataSource.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/0c941cc7d4f922af. Report an issue: GitHub.