Where does RememberMeAuthenticationFilter sit in the filter chain, and how does it turn a cookie into an authenticated user?
answer
- runs late: after login filters, before anonymous
- no-op if already authenticated
- calls rememberMeServices.autoLogin()
- RememberMeAuthenticationProvider checks key hash
- same key on services and provider
basics
~20 sRememberMeAuthenticationFilter runs late in the chain, after normal login filters but before the anonymous filter. If no user is already authenticated, it reads the remember-me cookie via RememberMeServices.autoLogin(), and if valid it authenticates a RememberMeAuthenticationToken through the AuthenticationManager and stores it in the SecurityContext.
solid answer
~40 sRememberMeAuthenticationFilter is a servlet filter positioned near the end of the Spring Security chain — after the primary authentication filters (form login, etc.) and just before AnonymousAuthenticationFilter. On each request it checks whether the SecurityContext already holds an Authentication; if one exists, it does nothing. If the context is empty, it calls rememberMeServices.autoLogin(request, response), which parses and validates the remember-me cookie and, on success, returns a RememberMeAuthenticationToken. The filter then passes that token to the AuthenticationManager, where RememberMeAuthenticationProvider validates that the token's key hash matches the configured key, saves the resulting Authentication in the SecurityContext, and publishes an InteractiveAuthenticationSuccessEvent. If autoLogin fails, the exception is handled (invalid cookies are cleared) and the chain continues, eventually falling through to anonymous authentication.
code
java · 16 lines// Conceptual view of what RememberMeAuthenticationFilter does per request:
if (SecurityContextHolder.getContext().getAuthentication() == null) {
Authentication remembered = rememberMeServices.autoLogin(request, response);
if (remembered != null) {
try {
Authentication result = authenticationManager.authenticate(remembered);
// RememberMeAuthenticationProvider verified the key hash here
SecurityContextHolder.getContext().setAuthentication(result);
securityContextRepository.saveContext(...);
publisher.publishEvent(new InteractiveAuthenticationSuccessEvent(result, getClass()));
} catch (AuthenticationException failed) {
rememberMeServices.loginFail(request, response); // clears bad cookie
}
}
}
chain.doFilter(request, response); // falls through to AnonymousAuthenticationFilter if still nullgo deeper
Know a filter reads the cookie and logs the user in if valid.
Explain the no-op-if-authenticated check and the autoLogin call.
Trace filter -> token -> AuthenticationManager -> RememberMeAuthenticationProvider and the key-hash check.
Reason about chain ordering rationale, event publication, and failure handling / cookie cancellation edge cases.
**Filter chain position.** Spring Security is a chain of servlet filters. `RememberMeAuthenticationFilter` is deliberately placed **late**: after the interactive authentication filters (e.g. `UsernamePasswordAuthenticationFilter`, `BasicAuthenticationFilter`) and **before** `AnonymousAuthenticationFilter`. The ordering matters because remember-me is a *fallback*: it should only kick in when nothing stronger already authenticated the request, and it must run before the anonymous filter so a valid cookie wins over anonymous access. **What it does per request (`doFilter`).** 1. It inspects the current `SecurityContextHolder`. **If an `Authentication` is already present, it does nothing** and continues the chain — remember-me never overrides an existing (stronger) authentication. 2. If the context is empty, it calls `rememberMeServices.autoLogin(request, response)`. - `autoLogin` finds the remember-me cookie, decodes it, and validates it per strategy (hash recompute for TokenBased; series/token lookup for Persistent). Returns `null` if there's no cookie; throws (e.g. `InvalidCookieException`, `CookieTheftException`) on a bad one. 3. If `autoLogin` returns a non-null `RememberMeAuthenticationToken`: - The filter submits it to the `AuthenticationManager` (`authenticate(rememberMeToken)`). - The `RememberMeAuthenticationProvider` handles it: it recomputes the expected key hash and checks it equals the token's `keyHash`; a mismatch throws `BadCredentialsException`. This is why the same `key` must be shared between the `RememberMeServices` and the provider. - On success the returned `Authentication` is placed in the `SecurityContext` (and saved via the `SecurityContextRepository`), and an `InteractiveAuthenticationSuccessEvent` is published so listeners know a login occurred. 4. If `autoLogin` throws, the filter delegates to `rememberMeServices.loginFail(...)` (which typically **cancels/clears the bad cookie**) and to an `AuthenticationFailureHandler` if configured, then continues. The request proceeds unauthenticated and normally reaches `AnonymousAuthenticationFilter`. **The token and provider.** A `RememberMeAuthenticationToken` carries the principal, authorities, and a `keyHash` derived from the shared key. `RememberMeAuthenticationProvider.supports(RememberMeAuthenticationToken.class)` is true; it validates the key. Because the trust level is 'remembered', `AuthenticationTrustResolver.isRememberMe()` returns true, and expression `fullyAuthenticated` is false for these principals. **Why the design is layered this way.** - **Separation**: `RememberMeServices` owns cookie parsing/validation and storage; the *filter* owns chain integration; the *provider* owns key verification inside the `AuthenticationManager`. This mirrors Spring Security's general pattern (filter -> token -> AuthenticationManager -> provider). - **Idempotent fallback**: skipping when already authenticated makes it safe to always have in the chain. **Gotchas.** - If the provider's `key` differs from the services' `key`, every auto-login fails with `BadCredentialsException` even though the cookie is well-formed. The DSL wires both from the same `key(...)`, but manual bean wiring can drift. - A `CookieTheftException` from the persistent strategy surfaces here and results in the cookie being cancelled and (by default) an authentication failure. - Because it runs before the anonymous filter, forgetting to register the filter (e.g. custom chain without `rememberMe()`) means cookies are simply ignored.
- What does RememberMeAuthenticationProvider actually verify?That the RememberMeAuthenticationToken's keyHash equals the hash of the provider's configured key. It proves the token was minted by this application's RememberMeServices; a mismatched key yields BadCredentialsException.
- Why is the filter placed before AnonymousAuthenticationFilter?Remember-me is a fallback that should still win over anonymous access. Running before the anonymous filter means a valid cookie authenticates the request; only if remember-me finds nothing does the chain fall through to anonymous.
saying these in an interview costs you the question
- Saying the filter runs first / before form login
- Thinking it overrides an existing authentication
- Not knowing the key must match between services and provider
- Confusing the filter (chain integration) with RememberMeServices (cookie logic)