Add Keycloak OIDC login flow with role-based route protection #8
Labels
No labels
domain:backend
domain:devops
domain:frontend
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/westside-landing#8
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Lineage
plan-2026-03-08-tryout-prep→ Phase 5 → Phase 5d (westside-app login)Repo
forgejo_admin/westside-appUser Story
As a coach or admin user
I want to log in to the westside-app via Keycloak
So that I can access role-protected dashboards (admin/coach) while the stats page remains public
Context
Keycloak IdP is deployed at
keycloak.tail5b443a.ts.netwith realmwestside-basketball. An OIDC clientwestside-appis configured as a confidential client with:westside-apphttps://westsidekingsandqueens.tail5b443a.ts.net/*player,coach,adminThe app currently has NO auth — admin and coach pages are completely unprotected. This issue adds Keycloak OIDC authentication using Auth.js (
@auth/sveltekit).Client secret (for env var, not to commit):
XdDNmY4g0tbRei1E4pVUSXezoi1wS117File Targets
Files to create:
src/hooks.server.js— SvelteKit server hook with Auth.js handlesrc/routes/auth/[...auth]/+server.js— Auth.js catch-all API route (NOTE: Auth.js for SvelteKit may use hooks only — check@auth/sveltekitdocs and use whichever pattern is current)src/lib/components/AuthStatus.svelte— login/logout UI componentFiles to modify:
package.json— add@auth/sveltekitdependency (usenpm install)src/routes/+layout.server.js— CREATE: root layout server load to inject sessionsrc/routes/+layout.svelte— add AuthStatus component to nav areasrc/routes/admin/+page.server.js— add role guard (requireadminrole, redirect to login)src/routes/coach/+page.server.js— add role guard (requireadminorcoachrole, redirect to login)src/routes/+page.server.js— stays public, no auth required (do NOT break this)k8s/deployment.yaml— addAUTH_SECRET,AUTH_KEYCLOAK_ID,AUTH_KEYCLOAK_SECRET,AUTH_KEYCLOAK_ISSUER,AUTH_TRUST_HOSTenv varsFiles NOT to touch:
src/lib/server/api.js— API helper doesn't need auth headers (basketball-api public endpoints are used)svelte.config.js— adapter config is fine as-isAuth.js Integration Pattern
Route Protection Pattern
Login/Logout UI
Add a simple auth status to the layout:
Acceptance Criteria
/(stats page) without login/adminare redirected to Keycloak login/coachare redirected to Keycloak login/adminpage with full functionality/coachpage but is redirected away from/adminTest Expectations
/admin→ redirected to Keycloak → login → see admin page/coach→ redirected to Keycloak → login → see coach page/→ see stats without loginConstraints
@auth/sveltekit(the official Auth.js SvelteKit adapter), NOT a custom OAuth implementation@auth/sveltekitpackage docsAUTH_SECRETmust be a random 32+ char string for session encryption (generate one, add to k8s secret)AUTH_TRUST_HOST=trueis required because we're behind a Tailscale funnel reverse proxyBASKETBALL_API_URLenv var must be preserved — the app still fetches roster data from basketball-apisrc/lib/server/api.js— those endpoints are public{#if}blocks, not$:reactive statementsChecklist
npm run buildsucceeds)Related
plan-2026-03-08-tryout-prep— parent plan