- pnpm 10 workspace + TypeScript strict + ESLint flat + Prettier - CLAUDE.md as canonical brief - docs/tasks/ — 22 task briefs broken out by phase for sub-sessions - docs/decisions/ — ADR scaffold Implements task 01 (repo-init).
2.4 KiB
2.4 KiB
06 — Authentik install + OIDC integration
Goal
Bring up Authentik in the compose stack and integrate famapp as an OIDC client. Logging in at fam.ginnoir.com redirects to auth.ginnoir.com, returns, and creates a session.
Depends on
- 04 (registry, so we have a
userstable to map into) - 05 (compose stack)
Scope
Authentik bootstrap
- Tune env in
deploy/compose.yamlfor authentik-server/worker/db/redis per Authentik's official docs. deploy/authentik/README.md— manual one-time steps Matt runs after first boot:- Visit
auth.ginnoir.com/if/flow/initial-setup/, set the akadmin password. - Create an OIDC Provider for famapp (RS256, redirect URI
https://fam.ginnoir.com/api/auth/callback/authentik). - Create an Application bound to it; copy client ID + secret into famapp's
.env. - Create the two user accounts (Matt + wife) with passkeys.
- Visit
famapp OIDC client
- Install
next-auth@beta(v5) — Auth.js. src/lib/auth.tsconfigures Auth.js with a generic OIDC provider pointed atAUTH_OIDC_ISSUER.- On first login, upsert into
userstable by email; create-or-attach to the single seeded household (task 07 owns the seeding; this task assumes it). - Middleware (
src/middleware.ts) protects everything except/s/*(share viewer),/api/auth/*, and static assets. - A signed-in user is available via a
getCurrentUser()server helper.
Login UX
/loginpage with a single "Sign in with SSO" button.- After login, redirect to
/.
Out of scope
- Forward-auth / Outpost wiring for the rest of Matt's stack (separate later task).
- Account self-service in famapp (Authentik owns identity).
- Automating Authentik provider creation via Terraform/blueprints — manual is fine for now; document it well.
Acceptance criteria
- Hitting
/while signed out redirects to/login. - Signing in with an Authentik account creates/updates a row in
usersand returns to/. getCurrentUser()works in server components and server actions./s/<token>is reachable signed-out (placeholder is fine — real viewer is task 31).- Auth secret comes from
AUTH_SECRETenv, not committed.
Notes
- Authentik's OIDC issuer URL takes the form
https://auth.ginnoir.com/application/o/<app-slug>/. Document this in the README so Matt copies it correctly. - Use Auth.js's database session strategy with the Drizzle adapter so the
usersrow is the source of truth.