Review: Keycloak OIDC auth (Twitch login)

review-796-2026-04-03 Doc

review ready

Verdict: READY

Template Completeness

  • [x] Type -- Feature
  • [x] Lineage -- Sub-ticket of #7, depends on #8 + #9
  • [x] Repo -- forgejo_admin/twitch-2k-wager
  • [x] User Story -- As a Twitch viewer / sign in with Twitch / Marcus knows gamertag
  • [x] Context -- Keycloak OIDC via PKCE, realm twitch-2k-wager, client playme2k
  • [x] File Targets -- 5 files listed
  • [x] Acceptance Criteria -- 6 items
  • [x] Test Expectations -- 2 items
  • [x] Constraints -- PKCE, env vars, no raw OAuth
  • [x] Checklist -- present
  • [x] Related -- parent #7, story note, arch note

Traceability

  • [x] story:challenger-auth label -- Challenger Twitch Login
  • [x] story note verified -- story-twitch-2k-wager-challenger-auth (id 1157) exists in pal-e-docs
  • [x] story entry on project page -- challenger-auth row present in project-twitch-2k-wager user-stories table
  • [x] arch:dataflow-twitch-2k-wager label -- Data Flow: Twitch 2K Wager
  • [x] arch note verified -- arch-dataflow-twitch-2k-wager (id 1155) exists in pal-e-docs
  • [x] Forgejo issue -- forgejo_admin/twitch-2k-wager#10, state: open

File Targets

  • [x] src/routes/auth/login/+server.ts -- NEW file. Parent dir src/routes/ exists in repo. Correct SvelteKit server route pattern.
  • [x] src/routes/auth/callback/+server.ts -- NEW file. Standard OIDC callback route.
  • [x] src/routes/auth/logout/+server.ts -- NEW file. Session teardown route.
  • [x] src/hooks.server.ts -- NEW file. SvelteKit server hooks for auth guard.
  • [x] src/lib/auth.ts -- NEW file. Parent dir src/lib/ exists. Keycloak OIDC helpers.
All files are net-new, created on top of the scaffold from #8 (now merged). Directory structure confirmed in repo.

Repo Placement

OK. Issue filed on forgejo_admin/twitch-2k-wager. All file targets are within this repo. Single-repo change.

Dependencies

  • [x] #8 (SvelteKit scaffold + Dockerfile) -- CLOSED. Prerequisite met.
  • [x] #9 (Postgres schema + db.ts) -- CLOSED. Prerequisite met. Challenger record creation depends on DB schema.
  • [x] #11 (Stripe Checkout + webhook) -- parallel, no conflict. Independent subsystem.
  • [x] #7 (parent ticket) -- open, tracking overall progress. No blocker.
All dependencies satisfied. No blockers.

Acceptance Criteria

6 criteria, all verifiable by an agent:
  • "Login with Twitch" button redirect -- testable via route handler response
  • Challenger record creation -- testable via DB query after auth
  • Session persistence -- testable via cookie/session check across navigation
  • Logout clears session -- testable
  • Repeat visitor recognition -- testable via second login
  • "Works on mobile" -- partially testable (responsive layout). Full device test requires manual verification. Acceptable for this scope.
Test expectations reference Keycloak test realm -- agent will need running Keycloak. Acceptable given platform infrastructure is deployed.

Blast Radius

Checked existing Keycloak OIDC patterns across platform. pal-e-app uses keycloak-js (client-side SPA pattern). This ticket correctly uses server-side OIDC routes (adapter-node). Different pattern, no cross-contamination risk. No other SvelteKit apps use server-side Keycloak OIDC -- this is the first implementation of that pattern. No downstream consumers affected. Rollback is straightforward (revert single PR).

Decomposition Assessment

Apply the three-thing limit and five-minute rule:
  • 5 file targets in 1 repo -- all part of a single auth flow (login, callback, logout, guard, helpers). Not 5 discrete changes; it is 1 cohesive feature across 5 files.
  • 6 acceptance criteria -- slightly above 5 threshold, but all within the same concern (auth lifecycle).
  • Estimated agent time: 3-5 minutes. Borderline but within bounds.
  • No independent subtasks that benefit from parallelization -- callback depends on login, guard depends on both, helpers are shared.
No decomposition needed.

Recommendation

No action needed.