hanko-auth: stale <cookieName>_session_state in localStorage restarts the login flow mid-passcode when the window regains focus
Checklist
- I could not find a solution in the existing issues or docs.
- I agree to follow this project's Code of Conduct.
Describe the bug
Environment: Hanko Cloud, @teamhanko/hanko-elements 2.7.0 (frontend-sdk bundled). Browser-independent; reproduced on Chromium and Safari.
Description
The SDK persists a session marker in localStorage under _session_state ({expiration, lastCheck}). When a session ends without an explicit logout — natural expiry, or the account being deleted — the marker is left behind with a future expiration.
On the next visit to a page hosting hanko-auth, the SDK reads the marker, assumes "logged in", and starts the session check scheduler as soon as the window gains focus. GET /sessions/validate then reports the session invalid, a session-expired event is dispatched, and hanko-auth in login/registration mode re-initializes the entire flow.
The timing makes this especially harmful: the window regains focus exactly when the user returns from their email client with the one-time passcode — the passcode step vanishes, the user is back at the email field and must request a new code. Because it only happens when a stale marker exists, it looks intermittent and is very confusing to users.
Reproducing the bug
Steps to reproduce
On a page hosting hanko-auth, with no valid session, run (default cookie name shown): localStorage.setItem('hanko_session_state', JSON.stringify({expiration: Date.now() + 3600000, lastCheck: 0})) Reload the page, start a registration, request a passcode, stay on the passcode entry step. Blur the window, then focus it again. Observe in the network/event log: GET /sessions/validate → hanko-session-expired CustomEvent → a new POST /login (flow re-initialization). The passcode step is lost.
Expected behavior
A login/registration flow that is already past its initial state should not be reset by a stale marker. The invalid validate result could clear the marker without restarting an active flow — or the session check could be skipped entirely while an unauthenticated flow is in progress.
Workaround we applied: we remove the localStorage key before initializing the elements on our sign-in page (safe for us, since our server redirects authenticated users away from that page), but this relies on an internal key name.
Logs
Configuration
Hanko Version
hanko-elements 2.7.0 (backend: Hanko Cloud SaaS)
OS Hanko Backend
None
OS Version Hanko Backend
No response
OS
None
OS Version
No response
Browser Version
Any (reproduced on Chromium and Safari)
Environment
None
Additional Context
Related to the passkey onboarding issue I just filed (#2867). Reported first via Hanko Cloud support.
Source: teamhanko/hanko