feat: Keycloak OIDC auth — protect write operations #22

Closed
opened 2026-03-15 01:08:28 +00:00 by forgejo_admin · 0 comments

Lineage

plan-pal-e-docs → Phase F5 (phase-pal-e-docs-frontend-auth)

Repo

forgejo_admin/pal-e-app

User Story

As a platform operator
I want write operations to require Keycloak authentication
So that unauthenticated users cannot create or modify notes via the frontend

Context

pal-e-app now has write capability (Quick-Jot, PR #21) but zero authentication. Anyone on the tailnet can create notes. Keycloak is deployed at https://keycloak.tail5b443a.ts.net and the OIDC flow is proven in westside-app (Auth.js + Keycloak provider, PR #9).

Architecture: read-only operations (browse, search, dashboard, boards) remain public. Only write operations (POST /api/notes) require authentication. The FAB button should only appear for authenticated users.

Keycloak realm: master (same as westside-app). Need a new pal-e-app client registered.

Reference implementation: ~/westside-app/src/auth.ts + ~/westside-app/src/hooks.server.ts

File Targets

Files to create:

  • src/auth.ts — Auth.js config with Keycloak provider
  • src/hooks.server.ts — SvelteKit hooks for session handling
  • src/routes/signin/+page.svelte — sign-in page
  • src/routes/signout/+page.svelte — sign-out page
  • k8s/pal-e-auth-secrets.enc.yaml — SOPS-encrypted client secret

Files to modify:

  • src/routes/+layout.svelte — show user/sign-out when authenticated, sign-in when not; hide FAB when not authenticated
  • src/routes/+layout.server.ts — pass session to layout
  • src/routes/api/notes/+server.ts — require auth for POST
  • package.json — add @auth/sveltekit dependency

Files NOT to touch:

  • src/routes/search/ — read-only, stays public
  • src/routes/dashboard/ — read-only, stays public
  • src/routes/boards/ — read-only (board moves already have their own proxy)

Acceptance Criteria

  • Unauthenticated users can browse notes, search, view dashboard, view boards
  • Unauthenticated users CANNOT see the Quick-Jot FAB
  • Unauthenticated users who POST to /api/notes get 401
  • Clicking "Sign in" redirects to Keycloak login, then back to pal-e-app
  • Authenticated users see their name in nav + "Sign out" link
  • Authenticated users see the FAB and can create notes
  • Sign out clears session and Keycloak SSO (hit Keycloak logout endpoint)
  • Session cookie is HttpOnly, Secure, SameSite=Lax

Test Expectations

  • Manual: visit app unauthenticated — no FAB, can browse/search
  • Manual: sign in via Keycloak — FAB appears, can create note
  • Manual: sign out — FAB disappears, session cleared
  • Manual: POST /api/notes without session — 401 response

Constraints

  • Reuse Auth.js + Keycloak pattern from westside-app — don't invent new auth
  • SOPS encrypt the client secret (Age key: age15ct78fr4scv4vxzj3k6q76wshywzlu0mdc64a624e264dst7zfaq6tjzjr)
  • AUTH_SECRET env var needed for Auth.js session encryption
  • Keycloak realm URL: https://keycloak.tail5b443a.ts.net/realms/master
  • Dark theme: sign-in button matches accent (#e94560)

Checklist

  • PR opened with Closes #20
  • No unrelated changes
  • SOPS secret properly encrypted
  • Keycloak client registered
  • phase-pal-e-docs-frontend-auth — plan phase
  • plan-pal-e-docs — parent plan
### Lineage `plan-pal-e-docs` → Phase F5 (`phase-pal-e-docs-frontend-auth`) ### Repo `forgejo_admin/pal-e-app` ### User Story As a platform operator I want write operations to require Keycloak authentication So that unauthenticated users cannot create or modify notes via the frontend ### Context pal-e-app now has write capability (Quick-Jot, PR #21) but zero authentication. Anyone on the tailnet can create notes. Keycloak is deployed at `https://keycloak.tail5b443a.ts.net` and the OIDC flow is proven in westside-app (Auth.js + Keycloak provider, PR #9). Architecture: read-only operations (browse, search, dashboard, boards) remain public. Only write operations (`POST /api/notes`) require authentication. The FAB button should only appear for authenticated users. Keycloak realm: `master` (same as westside-app). Need a new `pal-e-app` client registered. Reference implementation: `~/westside-app/src/auth.ts` + `~/westside-app/src/hooks.server.ts` ### File Targets Files to create: - `src/auth.ts` — Auth.js config with Keycloak provider - `src/hooks.server.ts` — SvelteKit hooks for session handling - `src/routes/signin/+page.svelte` — sign-in page - `src/routes/signout/+page.svelte` — sign-out page - `k8s/pal-e-auth-secrets.enc.yaml` — SOPS-encrypted client secret Files to modify: - `src/routes/+layout.svelte` — show user/sign-out when authenticated, sign-in when not; hide FAB when not authenticated - `src/routes/+layout.server.ts` — pass session to layout - `src/routes/api/notes/+server.ts` — require auth for POST - `package.json` — add `@auth/sveltekit` dependency Files NOT to touch: - `src/routes/search/` — read-only, stays public - `src/routes/dashboard/` — read-only, stays public - `src/routes/boards/` — read-only (board moves already have their own proxy) ### Acceptance Criteria - [ ] Unauthenticated users can browse notes, search, view dashboard, view boards - [ ] Unauthenticated users CANNOT see the Quick-Jot FAB - [ ] Unauthenticated users who POST to /api/notes get 401 - [ ] Clicking "Sign in" redirects to Keycloak login, then back to pal-e-app - [ ] Authenticated users see their name in nav + "Sign out" link - [ ] Authenticated users see the FAB and can create notes - [ ] Sign out clears session and Keycloak SSO (hit Keycloak logout endpoint) - [ ] Session cookie is HttpOnly, Secure, SameSite=Lax ### Test Expectations - [ ] Manual: visit app unauthenticated — no FAB, can browse/search - [ ] Manual: sign in via Keycloak — FAB appears, can create note - [ ] Manual: sign out — FAB disappears, session cleared - [ ] Manual: POST /api/notes without session — 401 response ### Constraints - Reuse Auth.js + Keycloak pattern from westside-app — don't invent new auth - SOPS encrypt the client secret (Age key: `age15ct78fr4scv4vxzj3k6q76wshywzlu0mdc64a624e264dst7zfaq6tjzjr`) - `AUTH_SECRET` env var needed for Auth.js session encryption - Keycloak realm URL: `https://keycloak.tail5b443a.ts.net/realms/master` - Dark theme: sign-in button matches accent (#e94560) ### Checklist - [ ] PR opened with `Closes #20` - [ ] No unrelated changes - [ ] SOPS secret properly encrypted - [ ] Keycloak client registered ### Related - `phase-pal-e-docs-frontend-auth` — plan phase - `plan-pal-e-docs` — parent plan
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/pal-e-docs-app#22
No description provided.