[Guide] Build an Auth Flow (Client-Side Checks First) - implementation notes
The Auth Flow guide is very explicit about treating redirects as normal navigation: planned, recorded, and rendered as evidence. It also pushes a route-first check posture (no scattered leaf guards) and a durable auth vault for session truth that can move across file routes and component routes without being re-derived.
How did you model the redirect ledger so it stayed readable (not just a log dump), and what did you render as evidence? Did "client-side checks first" reduce guard sprawl for you, or did you still need leaf checks for edge cases? How did you handle returnTo and provider hints (URL as hint vs route doc as truth) without creating security footguns? What did you store as derived session evidence (source/version/status) so screenshots were actionable?
Comments (18)
Back to latestThe redirect ledger is the best idea in the guide.
Once redirects are recorded, "why did it bounce me" becomes answerable.
We kept the ledger minimal: only record entries when you cross a file-route boundary or change auth status.
ts
type Entry = { from: string; to: string; reason: string; at: number };
function record(authVault: any, e: Entry) {
const next = [...authVault.read('ledger'), e].slice(-20);
authVault.write('ledger', next);
authVault.write('lastRedirectReason', e.reason);
}
Then the shell renders data-auth-reason and screenshots become meaningful.
Counterpoint: client-side checks first can create a false sense of safety if people forget server enforcement.
We had to be explicit in docs that the goal is a stable routing story, not security guarantees.
Agree. The guide's framing helped us: it's about UX + debuggability first, with a clear posture.
We still enforce access server-side; the client check just keeps the route story coherent.
We rendered a small auth evidence line in the shell: status, source, returnTo (sanitized).
It made support debugging much easier without exposing tokens.
We treated returnTo as URL hint only and wrote the winning value into the route doc as evidence (returnToSource=hint|local).
Then we allowlist paths in the shell so you can't redirect to arbitrary origins.
We ended up with a single gate component at the /app entry that self-corrects in render.
If not authenticated, it records the redirect and jumps to login. No scattered checks.
A misunderstanding I had: I thought the callback route should immediately "finish" auth before rendering anything.
The guide treats it like a normal route that writes session keys and renders evidence as it goes.
We stored derived session.debug.source (hint|callback|local) and it paid off in every bug report.
You can instantly tell if the session came from a callback or from a cached local token.
Docs tie-in: this is routing + safety docs combined.
Related: Routing and Navigation and Security and Safety.
We made the login form a route document with derived canSubmit and status lanes like the guide suggests.
It made submit behavior consistent and prevented double-submits.
Snippet: a simple gate that records an evidence reason before redirecting:
tsx
function RequireAuth({ children }: { children: React.ReactNode }) {
const auth = useVaultMirror('auth');
const jump = useRouteJump();
if (auth.read('session').status !== 'authenticated') {
auth.write('ledger', [...auth.read('ledger'), { from: '/app', to: '/auth/login', reason: 'anonymous', at: Date.now() }]);
jump.to('/auth/login');
return null;
}
return <>{children}</>;
}Counterpoint: recording ledgers in a vault can leak sensitive info if you aren't careful about what you store.
We kept reasons generic and never store tokens/emails in the ledger.
Same. We treat the ledger like security logs: only store what you can safely ship to clients.
The evidence should explain motion, not contain secrets.
Provider hints were easiest when they only set the initial mode, and the route doc becomes truth immediately.
If the URL keeps winning forever, the login screen feels inconsistent.
We shipped a debug-only panel that shows the last ledger entry and session lane.
It made auth bugs feel like normal bugs instead of "auth is cursed".
The "route story first" planning section is worth copying into internal docs.
If you plan the map and the evidence keys, implementation decisions get a lot simpler.
I liked that logout is treated as a normal route transition with evidence.
It keeps auth behavior from being a special case that nobody can test reliably.
We had an edge case where returnTo pointed at a route that no longer exists.
The guide's posture of self-correcting navigation in render made it easy to handle (bounce to /app and record reason).
Auth flows got calmer once redirects were treated as first-class state transitions with evidence, not mysterious side effects.