The first UI in this repo (ADR-0030): Cognito Hosted UI sign-in via authorization-code + PKCE
(RFC 7636), and one page that calls GET /me (ADR-0024) and shows what comes back. Astro,
static output — everything auth-aware runs client-side, which is the correct place for it given
ADR-0022's app client has no secret to protect on a server this slice doesn't have anyway.
src/lib/auth.ts— the PKCE flow itself: verifier/challenge generation (verified against RFC 7636 Appendix B's own test vector), the authorize/token/logout URL builders, the token exchange, andbeginSignIn/completeSignInorchestrating both aroundsessionStorage.src/lib/session.ts— where tokens live after sign-in (localStorage, unlike the PKCE flow's ephemeralsessionStoragestate) and expiry checking.src/lib/api.ts— a typedGET /meclient. Sends the ID token as the bearer, not the access token — see the module docstring for why, and ADR-0030's consequences for the caveat.src/lib/config.ts— reads thePUBLIC_*env vars Vite bundles client-side; fails loudly on anything missing rather than silently pointing atundefined.src/pages/{index,callback,dashboard}.astro— sign in, complete the redirect, show the result.test/— Vitest +happy-dom. See theNODE_OPTIONSnote below before it looks broken.
cp .env.example .env.local # then fill in real values once a backend is deployed
npm ci
npm run dev # http://localhost:4321
npx tsc --noEmit # typecheck
npm test # vitest
npm run build # static output to dist/npm test runs with NODE_OPTIONS=--no-experimental-webstorage. Node ≥22 ships its own
experimental global localStorage (gated on a --localstorage-file flag this project never
sets), which otherwise silently shadows happy-dom's working implementation — sessionStorage
is unaffected (Node's experimental Web Storage only claims localStorage), which is why only
session.ts's tests broke before this was diagnosed and fixed. If you invoke vitest directly
instead of through npm test, set that env var yourself.
No live Cognito user pool or deployed API exists to test this against — see ADR-0030's
consequences for exactly what that leaves unconfirmed (whether HttpUserPoolAuthorizer accepts
an ID token the way api.ts assumes) and what's already been verified as precisely as it can be
without one (the PKCE math itself, against the RFC's own worked example).