Backend interview: How would you upgrade cookie login to device-bound sessions?
Prompt and context
An existing login system keeps users signed in with long-lived cookies. Security wants to reduce cross-device replay after cookie theft, but cannot upgrade every client at once or cause mass logout during key rotation, browser restart, or device recovery. Design a DBSC integration covering registration, refresh, revocation, fallback, audit, and gradual rollout.
What the interviewer is testing
- Whether you separate the long-lived identity session, short-lived authorization cookie, and device private key.
- Whether you can explain registration and refresh endpoints, challenge-response, and server-side binding records.
- Whether you handle non-exportable keys, unsupported browsers, missing cookies, and device migration.
- Whether you design revocation, key rotation, concurrent refresh, and anomaly detection.
- Whether compatibility and security boundaries appear in rollout, monitoring, and rollback.
Questions to clarify first
- Which accounts or operations require device binding, and which may keep ordinary cookies?
- What are the maximum session lifetime, refresh interval, and acceptable re-login rate?
- Do you need multiple devices, enterprise proxies, devices without TPMs, or cross-site subdomains?
- After proof failure, should the system sign out, fall back to MFA, or freeze high-risk actions?
- Can the existing gateway pass registration and refresh headers, and which fields may be logged?
A 30-second answer
“I would keep the existing login state as a compatibility layer. After login, a Secure-Session-Registration response asks the browser to create a device key. The server stores only the public key, session identifier, refresh endpoint, scope, and status, then replaces the long-lived cookie with a short-lived cookie. When it expires, the browser calls the refresh endpoint with a key proof; the server verifies the signature, challenge, session, and risk policy before issuing a new cookie. Registration or refresh failures fall back to an ordinary session or MFA according to capability and risk. Revocation, rotation, audit, and rollout metrics control expansion.”
Step-by-step deep dive
1. Define trust boundaries and state
The login service still authenticates the user; the DBSC layer proves that the browser holds the private key bound to the session. Store sessionId, public key, key version, refresh URL, scope, short-lived cookie name, status, and last proof time. Never store the private key or treat the public key itself as the user identity.
2. Register a device-bound session
After successful login, return the registration response header. The browser generates a key pair and submits the public key to the registration endpoint. The server validates a one-time registration token, login session, and origin, writes the binding, and returns JSON session instructions plus a short-lived cookie. Registration must be idempotent so retries cannot create an unrevocable orphan binding.
Secure-Session-Registration: (ES256); path="/StartSession"
Set-Cookie: auth_cookie=short-lived; Max-Age=600; Secure; HttpOnly; SameSite=Lax3. Verify key proof during refresh
When the short-lived cookie is near expiry, the browser calls the refresh endpoint with a DBSC proof JWT. Validate the signature algorithm, challenge, session identifier, time window, key version, and scope, then atomically advance the challenge or refresh counter. Do not silently extend an old cookie after a failed proof; return an observable reason and apply risk policy.
4. Handle fallback and multiple devices
DBSC is additive. Keep an ordinary session when the browser or hardware does not support it, while requiring MFA for high-risk actions. Store one binding per device; revoking one device deletes only that binding, while global logout revokes all bindings and ordinary sessions. The fallback path needs a shorter lifetime and rate limits so it cannot become a bypass.
5. Design rotation, concurrency, and recovery
Key rotation creates a new version with a short overlap window; the old version is allowed only one controlled migration. Use a session lock or conditional version update so concurrent refreshes cannot overwrite each other’s challenges. Browser restore, site-data clearing, or a lost key revokes the old binding and requires re-authentication; a refresh failure should not automatically become a permanent ban.
6. Monitor, audit, and roll out gradually
Record registration success, proof failures, refresh latency, fallback rate, device-revocation reason, and browser-version distribution, but never private keys. Start with low-risk accounts and compare hijack alerts with login success. If failures rise, remove the registration response header to stop new bindings while keeping the ordinary-cookie path. Write policy and key-version changes to an immutable audit log.
Example of a strong answer
“DBSC proves only that the browser holds the private key bound to a session; the existing login system still authenticates the user. After login, the server uses a registration response header to make the browser create a key and submit its public half, then replaces the long-lived cookie with a short-lived one. The refresh endpoint validates the proof JWT’s signature, challenge, session, time, and scope before atomically advancing the challenge and issuing a new cookie. The server stores public key, status, version, and audit data, never the private key. Multiple devices get separate bindings, and revocation can target one device or the whole user. Unsupported clients use a restricted ordinary session or MFA. During rollout, monitor proof failures, fallback, and login success; if risk rises, remove the registration header and keep compatibility.”
Common mistakes
- Treating the public key as the user identity → binding and authentication principals get mixed → use it only as session proof material.
- Only shortening the long-lived cookie → a thief can still replay it during its lifetime → bind the short-lived cookie to key proof.
- Skipping replay protection at refresh → one proof can be reused → bind a one-time challenge, time window, and atomic state update.
- Signing everyone out when unsupported → compatibility and availability suffer → fall back to an ordinary session or MFA by capability and risk.
- Treating DBSC as irrevocable → a lost device cannot be isolated → provide device-level and user-level revocation with audit.
Follow-ups and responses
Does a private key stop every form of cookie theft?
No. DBSC mainly reduces direct replay after a cookie is exported to another device. Malware controlling the original device, attacks during login, or a compromised server still require other defenses. State the threat model and residual risk explicitly.
Why keep an ordinary-session path?
Browser, hardware, and enterprise-network capabilities differ, and DBSC is still evolving as a standard. A restricted compatibility path avoids mass logout; high-risk actions can require stronger checks instead of making login fail.
How do you prevent concurrent refresh races?
Use conditional updates on sessionId and key version, accept only the current challenge, and atomically write the next challenge and cookie version. Duplicate requests can receive the same result or be asked to refresh again, preventing responses from overwriting one another.
What happens during device migration or restore?
Register it as a new device rather than copying the old private key. Keep the old binding for a short grace period with risk checks; after re-authentication, create a new public-key binding and let the user revoke the old record from device management.