The Frontend Must Respect Two Session Layers
Identity can issue perfect device and user-account tokens. If the web app treats them as one cookie jar, you undo the model at the edge.
In the Next.js app that consumes this BC, a request proxy owns session continuity on every matched navigation. Login UI still lives in React. Truth still lives in Identity. The edge’s job is ordering, refresh, and cookie hygiene.
Four cookies, two concerns
| Cookie role | Meaning |
|---|---|
| Device access | Short-lived proof of known client (dsid) |
| Device refresh | Rotating secret for the device family |
| User access | Short-lived proof of logged-in account (uaid) |
| User refresh | Rotating secret for the account session family |
HttpOnly, Secure, SameSite=lax. Expiry follows JWT exp so the browser and proxy agree on “stale.”
What the proxy does on each navigation
If device refresh fails, create a new device session. If user refresh fails or there is no valid device afterward, clear user cookies — do not limp along with a half-authenticated state.
Same-navigation visibility
Refreshing cookies only via Set-Cookie is not enough for Server Components in this request: they read the incoming Cookie header.
So the proxy rebuilds the upstream Cookie header with the new values (or deletions) before NextResponse.next. The browser still gets Set-Cookie for the next navigation. One round-trip, consistent view.
Single-flight against parallel refresh
HTML, RSC, and prefetch can all see an expired token at once. Without dedupe, each calls refresh → refresh-token reuse / race / extra latency.
In-process single-flight maps keyed by token identity: first caller works; others await the same Promise. That only covers one Node isolate. Multi-instance deploys still rely on Identity’s family rotation being correct; the edge only stops a stampede inside one process.
Route policy stays thin
Guest-only routes (for example password reset) redirect away when a user account session is alive. Logged-in gates redirect to login when it is not. Product home vs dashboard is a product choice — the session model should not care.
Some legacy product APIs may still use a separate compat cookie until convergence; the matcher can exclude those paths so the identity proxy does not fight them. That is migration reality, not a second architecture.
What not to put in the frontend
- Provider client secrets
- Password hashing
- “Soft” session inventing a user id in localStorage
- Refreshing user account before device
The edge is a careful client of Identity — not a miniature identity service.
Closing the book
Across nine chapters the arc is the same move, repeated:
| Split | Why |
|---|---|
| Person ≠ User | Reality ≠ access |
| Contact ≠ columns | Channels have lifecycles |
| Citizenship ≠ attribute | Relationships multiply |
| Device session ≠ account session | Client ≠ login |
| Verify ≠ establish | Methods converge |
| Org / geo ≠ free text | Context is structured |
| Edge ≠ source of truth | Delivery respects the model |
Frameworks will change. If the domain splits stay honest, the next framework inherits a system that still matches the world.
Start again or dig in
Return to the book map or revisit Device vs User Sessions when debugging cookie order bugs.