"Token has been expired" in Sulu remember-me authentication without built-in credential expiration management
0 reputation · 12 Dec 2022, 08:44 UTC
0 reputation · 12 Dec 2022, 08:44 UTC
Sulu delegates authentication to Symfony Security through the sulu_user provider and enforces least-privilege access using the sulu_security.role hierarchy and Symfony voters. When a remember-me token exceeds its configured lifetime, Symfony throws an AuthenticationException containing "Token has been expired", which Sulu propagates unchanged. However, core Sulu does not automatically enforce password expiration, and it lacks a built-in administrative interface to list, warn about, or reset expired credentials.
This absence leaves integrators to decide whether to implement password-age policies, token rotation, or custom listeners around the optional sulu_user.password_expired event. Without a centralized UI for monitoring credential state, compliance auditing and incident response become project-specific concerns. The framework surfaces expired remember-me tokens as a hard authentication failure but does not extend the same enforcement to password age or provide remediation tooling.
What is the intended architectural boundary between Sulu's framework responsibilities and project-specific credential lifecycle management? Should integrators treat Symfony-level remember-me expiration as the only credential-expiry signal, or is a custom password-age policy expected in least-privilege deployments? How can teams audit and remediate expired credentials when no built-in Sulu admin interface exists?
Assuming a recent Sulu release that delegates authentication to Symfony Security, Sulu treats remember-me token expiration as a framework-level session concern, not a password-lifecycle feature. The "Token has been expired" exception is raised by Symfony's remember-me service when the persistent cookie exceeds its configured lifetime. Sulu propagates this unchanged because it does not own the remember-me token store or its TTL policy. Core Sulu also does not ship password-age enforcement or an administrative interface for listing, warning about, or resetting expired credentials.
Confirmed behavior: Symfony's remember-me implementation validates the token's expiry timestamp on each auto-login attempt. When the timestamp is in the past, it raises an AuthenticationException with the message "Token has been expired". Sulu's sulu_user provider and sulu_security role hierarchy sit downstream of this check; they do not intercept or reinterpret the exception.
Likely architectural boundary: Sulu focuses on content access control and role management. Session persistence, cookie lifetime, and token rotation belong to the Symfony firewall configuration. Password-age policies, credential auditing, and remediation are intentionally left to the integrator because they vary by compliance regime and deployment.
Treat Symfony remember-me expiration as a session-persistence signal only. It does not indicate that a user's password is too old. If your least-privilege deployment requires password rotation, you must implement it explicitly:
passwordUpdatedAt (or equivalent) field to your user entity.UserCheckerInterface or an authentication event listener that blocks login when the password age exceeds your policy.sulu_user.password_expired event if you want Sulu-aware hooks, but do not expect core Sulu to enforce the policy automatically.Because Sulu provides no admin screen for credential state, audit directly at the data layer:
passwordUpdatedAt predates your compliance window.Confirm the remember-me lifetime in config/packages/security.yaml under the remember_me key. Use the Symfony Profiler's Security tab during a failing request to verify that the exception originates from the remember-me service, not from a Sulu voter or provider. Test with a token whose TTL has elapsed to confirm propagation.
Are you required to enforce password rotation by policy, or only clean up stale remember-me cookies? The answer determines whether you need a custom UserChecker and user-entity changes, or simply a scheduled cleanup of the token table.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.