# Authentik OIDC — React + Node Demo stack showing the standard OIDC split: | Layer | Token | Purpose | |-------|-------|---------| | **React frontend** | ID Token | Login, user profile (`sub`, `email`, `name`) | | **Node API** | Access Token | `Authorization: Bearer` on protected routes | ``` ┌─────────────┐ OIDC (PKCE) ┌──────────────┐ │ React │ ◄──────────────────► │ Authentik │ │ (Vite) │ ID + Access tokens │ (Provider) │ └──────┬──────┘ └──────────────┘ │ Bearer access_token ▼ ┌─────────────┐ JWKS verify JWT ┌──────────────┐ │ Express │ ◄────────────────── │ Authentik │ │ API :3001 │ │ JWKS │ └─────────────┘ └──────────────┘ ``` ## Prerequisites - Node.js 18+ - Running [Authentik](https://goauthentik.io/) instance ## 1. Configure Authentik 1. In Authentik Admin → **Applications** → **Providers** → **Create** → **OAuth2/OpenID Provider**. 2. Set: - **Client type**: Public (for SPA + PKCE) - **Redirect URIs**: `http://localhost:5173` - **Signing Key**: your instance default - **Scopes**: `openid`, `profile`, `email` (defaults are fine) 3. Create an **Application** and link it to this provider. 4. Note: - **Client ID** (slug or UUID from provider) - **Issuer / OpenID Configuration URL** — typically `https:///application/o//` Copy issuer and client ID into env files (see below). ## 2. Environment files ```bash cp frontend/.env.example frontend/.env cp backend/.env.example backend/.env ``` Edit both files with your Authentik issuer URL and client ID. `OIDC_AUDIENCE` on the backend should match the access token `aud` claim (usually the same client ID for Authentik). ## 3. Install and run ```bash npm run install:all # Terminal 1 — API npm run dev:backend # Terminal 2 — frontend npm run dev:frontend ``` Open http://localhost:5173 → **Sign in** → after login you’ll see ID token claims and can call **GET /api/me** with the access token. ## Project layout ``` frontend/ React + react-oidc-context (ID token for UI) backend/ Express + jose JWKS validation (access token) deploy/ Docker Compose (Authentik + app) for Ubuntu server ``` ## How it works **Frontend** (`react-oidc-context` + PKCE): - Redirects to Authentik for login - Stores session in `localStorage` - Reads **ID token** claims via `auth.user.profile` - Sends **access token** as `Authorization: Bearer ` to the API **Backend** (`jose`): - Fetches JWKS from `{OIDC_ISSUER}.well-known/jwks` - Verifies JWT signature, `iss`, and optional `aud` - Exposes user info from access token claims on `/api/me` ## Troubleshooting | Symptom | Check | |---------|--------| | Redirect URI mismatch | Authentik redirect URI must exactly match `http://localhost:5173` | | Invalid issuer | `VITE_OIDC_AUTHORITY` and `OIDC_ISSUER` must be identical (trailing slash) | | 401 on API | `OIDC_AUDIENCE` must match token `aud`; token must be sent as Bearer | | CORS errors | `CORS_ORIGIN` must match frontend URL | ## Deploy on Ubuntu Server (Docker) See **[deploy/README.md](deploy/README.md)** for Dockerfiles, `docker compose`, and Authentik on Ubuntu (e.g. Azure VM). ```bash cd deploy sudo ./install-ubuntu.sh cp .env.example .env # edit SERVER_HOST, URLs ./start-authentik.sh docker compose --env-file .env up -d --build ``` ## Production notes - Use HTTPS redirect URIs - Prefer httpOnly cookies or BFF pattern if you need to hide tokens from the browser - Rotate signing keys in Authentik as documented - Restrict CORS to your real frontend origin