Authentication — Concepts & Flow
Overview of the Wakastart OAuth2 PKCE flow: key concepts, complete diagram and Keycloak prerequisites.
Authentication — Concepts & Flow
Since IAM-S0 / IAM-C4 (May 2026) — The Keycloak realm is no longer built on the frontend side. Discovery exposes a public
POST /discover/start-loginendpoint that resolves the realm + client_id from the host and returns a ready-to-follow Keycloak URL. No Wakapp holdsINTERNAL_API_SECRET.
Why this step
Authentication is the most critical flow of your integration. A poorly implemented flow exposes you to vulnerabilities (code interception, CSRF, token leakage). PKCE (Proof Key for Code Exchange) is mandatory and guarantees that an OIDC code stolen in transit is unusable without the code_verifier known only to the legitimate client.
The Wakastart flow adds two steps specific to the platform: start-login (Discovery resolves the realm) and enrich (the BFF enriches the Keycloak JWT with application access rights: admin/team levels and resource.action rights).
Key concepts
- code_verifier: random 43-128 char string, generated client-side, stored in sessionStorage.
- code_challenge:
BASE64URL(SHA256(code_verifier)), sent to Keycloak. - access_token: RS256 JWT issued by Keycloak, short lifetime (5-15 min).
- refresh_token: long-lived token used to obtain new access_tokens.
- wakaToken: JWT signed by the WakaStart authentication service, containing the business rights. Mandatory to call downstream services.
- enrichment: proprietary step that turns the basic Keycloak JWT into an enriched wakaToken.
Complete flow in 10 steps
Loading diagram…
Keycloak prerequisites — OIDC client
For the flow to work, the OIDC client must be configured as follows:
| Parameter | Value | Reason |
|---|---|---|
| Client ID | Value of apps.client_id in the DB (auto-generated from the WID) | Discovery resolves this client_id |
| Client authentication | OFF (public client) | PKCE without a secret — mandatory |
| Authorization | OFF | Not necessary |
| Standard flow | ON | OAuth2 PKCE flow |
| Direct access grants | OFF (recommended) | Avoid Resource Owner Password Credentials |
| Implicit flow | OFF | Deprecated, insecure |
| PKCE Method | S256 | Mandatory |
| Valid redirect URIs | https://app.<tenant>.<platform>/api/auth/callback (exact path, no wildcard) | Exact match on Keycloak — a single callback per environment |
| Web origins | https://app.<tenant>.<platform> | CORS pre-flight |
Security — Never declare a wildcard (
/*) in redirect URIs. Any valid path as a redirect is an Open Redirect target if an application route is compromised (XSS, subdomain takeover). Declare one exact callback per environment (typically/api/auth/callback) and add a second exact callback for logout if needed.
Client authentication: ONcausesInvalid client or Invalid client credentialsat the token exchange — Keycloak expects aclient_secretthat public PKCE does not provide. This is the first thing to check in case of a 401 on callback.
Keycloak Organizations (IAM-C4 — mandatory)
The WakaStart authentication service rejects any Keycloak token without the organization claim. Three conditions must be met:
1. Realm — Organizations feature enabled
Console Keycloak → realm → Realm settings → General → "Organizations enabled"
This automatically creates an organization client scope at the realm level.
2. OIDC client — organization scope attached as default
Console Keycloak → realm → Clients → {client_id} → Client scopes → ajouter "organization" en Default
Automated by npx prisma db seed.
3. User — member of a Keycloak organization
For each Customer in the DB, a Keycloak organization exists (alias = customer.wid). Active users must be members of it.
Automated by npx ts-node prisma/backfill-keycloak-orgs.ts (idempotent).
Without these 3 conditions: enrichment returns 401 and the user sees an "Missing or invalid enriched token" error.
Error handling at the callback
| Case | Symptom | Solution |
|---|---|---|
redirect_uri mismatch | 400 Invalid redirect_uri from Keycloak | Check the exact URI match in the Keycloak console |
Incorrect client_id | 401 Invalid client | Extract client_id from the keycloakUrl, do not hardcode it |
Incorrect code_verifier | 400 invalid_grant | Check verifier/challenge consistency (do not re-encode) |
Missing organization | 401 Missing enriched token | Enable Organizations + attach the scope to the client (see above) |
| Enrich fails | wakastart_token missing from cookies | Log the HTTP response of /api/auth/enrich |
Learn more
- PKCE Implementation: full step-by-step code
- Discovery:
start-loginand extracting thekeycloakUrl - User context /me: post-auth step
- Common pitfalls: diagnosing authentication errors