Authentik OIDC authentication for the admin dashboard #10
Reference in New Issue
Block a user
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?
Goal
Replace simple password auth with Authentik OIDC so the photographer logs in with their existing homelab SSO account. Authentik is already running at
auth.jerodrigged.com.Authentik setup (one-time, manual)
lisilou-portfoliohttps://<portfolio-domain>/api/auth/callbackopenid profile emailapi/.envDependencies
API changes
New env vars (
api/.env)New routes (
api/auth.js)GET /api/auth/login— builds authorization URL and redirects to AuthentikGET /api/auth/callback— exchanges code for tokens, validates ID token, stores user in session, redirects to/dashboardGET /api/auth/logout— destroys session, redirects to Authentik end_session_endpointGET /api/auth/me— returns current session user (used by dashboard to check auth state)Session middleware
express-sessionwithconnect-sqlite3store (reuses existing SQLite DB file)/api/admin/*routes protected byrequireAuthmiddleware that checksreq.session.user/api/admin/*return401with{ loginUrl: "/api/auth/login" }nginx change
/dashboard→ servesrc/dashboard.html/api/auth/→ proxy to api service (same as/api/)Acceptance
/dashboardwhen not logged in redirects through Authentik/dashboardwith active session/api/auth/mereturns the logged-in user's name/emailScope expanded: two Authentik groups required —
lisilou-photographers(dashboard access) andlisilou-clients(client portal access). Self-registration enrollment flow covered in #12. API must check group claims from the OIDC token to differentiate access levels. requireAdmin middleware for /api/admin/* and requireAuth for /api/client/*.Implemented:
lisilou-portfolioin Authentik via API (client_type=confidential, implicit-consent flow, per-provider issuer, scope mappings for openid/profile/email). Redirect URIs registered:https://lisilou.com/api/auth/callback,https://dev-lisilou.jerodrigged.com/api/auth/callback(new dev domain, Cloudflare Tunnel -> nginx -> CT114), andhttp://192.168.1.192:8080/api/auth/callbackas a direct-IP fallback.api/auth.js— login/callback/logout/me routes using openid-client v5 (pinned to v5 since v6 is ESM-only and this codebase is CJS).api/session-store.js— custom express-session store backed by the existing better-sqlite3 db (newsessionstable), avoiding a second native sqlite dependency (connect-sqlite3 pulls insqlite3, which fails to build in some environments).requireAdmininapi/server.jsnow accepts EITHER an OIDC session OR the existingADMIN_SECRETbearer token, so the current Playwright suite and admin scripts (CSV export, etc.) keep working unchanged./api/auth/loginredirects to a correctly-formed authorization URL at auth.jerodrigged.com with proper state/nonce/session cookie.Remaining manual step: OIDC_CLIENT_ID/SECRET/ISSUER/REDIRECT_URI need to be added to
api/.envon CT114 (sent to the repo owner directly, not committed).This unblocks #12 and #13.