You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Gate signed-out document requests at the edge instead of flashing the app-shell skeleton (#975)
* Gate signed-out document requests at the edge instead of flashing the app-shell skeleton
Signed-out visitors to the cloud app were SSR'd the authenticated
app-shell skeleton (sidebar + card grid) until a client-side
/account/me round trip 401'd and swapped in the login page — a
loading preview of an app they were never going to reach.
The sealed session cookie can be verified in the worker itself
(unseal + JWT against cached JWKS; no per-request round trip), so a
new request middleware does exactly that for document navigations:
- signed-out -> 302 to /login?returnTo=<path> before any app HTML is
served; an invalid cookie is also cleared (its presence is what
routes the production root past the marketing site)
- signed-in -> pass through, persisting any rotated sealed session
(refresh tokens are single-use)
- /login is a real route now; returnTo travels with the CSRF state
cookie through the login flow and the callback resumes the original
path (validated to same-origin relative, never /api)
- /cloud (the marketing CTA target, previously a 404) redirects into
the app root
Signed-in loads get faster too: AuthProvider seeds optimistic state
from a new non-HttpOnly display-only auth-hint cookie it maintains on
every confirmed /account/me, so the shell paints without waiting on
the probe; the resolved answer remains the authority. Logout and the
gate clear the hint alongside the session.
Unknown paths get a real 404 page (notFoundComponent) instead of
mounting the auth gate's skeleton.
The unauthenticated-skeleton e2e (the red repro for this report) is
now green and grew scenarios for the deep-link round trip,
open-redirect rejection, signed-in passthrough, and the 404 page.
* Derive auth state idiomatically in AuthProvider
Replace the seven hand-tracked primitive fields with a memoized resolved
state: useMemo on the atom value gives the identify and hint-cookie
effects a dependency that tracks real query transitions, and the
context value is memoized so consumers don't re-render on unrelated
renders.
* Carry returnTo inside the OAuth state parameter instead of a second cookie
The state parameter already round-trips through the identity provider
and is authenticated by the wos-login-state CSRF cookie, so the
destination rides inside it — base64url(JSON { nonce, returnTo }) — and
the wos-login-return-to cookie goes away. The callback re-validates the
decoded returnTo like any other untrusted path.
* Decode the login-state envelope in the auth-session CSRF scenario
The state parameter is now base64url(JSON { nonce, returnTo }), so the
scenario decodes it and asserts the nonce inside instead of expecting
the raw hex value.
* Cover the auth-hint lifecycle and session-gate edges end to end
Five new scenarios over the real WorkOS emulator:
- auth-hint: a confirmed /account/me writes the hint and the NEXT load
paints the real shell while the probe is held open; logout clears the
hint with the session.
- session-gate: an invalid wos-session is cleared on the way to /login
(not just redirected); /cloud routes into the app both signed out and
signed in; and a session whose access token no longer verifies is
refreshed in-flight — the rotated sealed session reaches the browser,
the spent one is revoked server-side (real single-use refresh
tokens), and the rotated one keeps working.
The stale-token path unseals the real session cookie with the same
iron-webcrypto sealing the WorkOS SDK uses, corrupts the JWT signature,
and reseals — exercising the gate's refresh branch without waiting out
a real expiry.
0 commit comments