First OIDC Client
A complete walkthrough of the Authorization Code flow with PKCE — from redirect to tokens to UserInfo. Covers client registration, token introspection, refresh tokens, and common gotchas.
The Flow at a Glance
Step 1 — Discovery
Every Clavex tenant publishes an OpenID Connect discovery document. Start here — your library will automatically pick up all endpoints.
Step 2 — Client Registration
Register your application via the Admin API. The token_endpoint_auth_method
determines how the client authenticates at the token endpoint.
| auth_method | When to use | Requires |
|---|---|---|
| none | SPAs, mobile apps (public clients) | PKCE mandatory |
| client_secret_post | Server-side apps (simple setup) | client_secret in body |
| client_secret_basic | Server-side apps (HTTP Basic) | client_secret in header |
| private_key_jwt | High-security / FAPI profiles | RS256/ES256 key pair |
Step 3 — Authorization Request
Build the authorization URL. PKCE is always required for public clients and strongly recommended for confidential clients.
# 2. Authorization URL — redirect the user here https://id.clavex.eu/acme/authorize ?client_id=clavex_01925... &redirect_uri=https://app.example.com/callback &response_type=code &scope=openid+email+profile &state=$STATE &code_challenge=$CHALLENGE &code_challenge_method=S256
state matches on callback.
This is your primary CSRF protection. Clavex will reject requests where state is missing.
Step 4 — Token Exchange
After the user logs in, Clavex redirects to your redirect_uri with
?code=AUTH_CODE&state=.... Exchange the code at the token endpoint.
Step 5 — UserInfo & ID Token
Fetch the user's claims from the UserInfo endpoint, or decode them directly from the ID token (a signed JWT — always verify the signature against the JWKS).
# Verify ID token signature (use your library — this is just for inspection) $ echo "$ID_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq . { "iss": "https://id.clavex.eu/acme", "sub": "01925f3a-...", "aud": "clavex_01925...", "exp": 1746892800, "iat": 1746889200, "auth_time": 1746889190 }
Step 6 — Refresh Tokens
Common Errors
| Error | Cause | Fix |
|---|---|---|
| invalid_grant | Code already used, expired, or verifier wrong | Each code is single-use. Check verifier matches the one sent in the auth request. |
| redirect_uri_mismatch | redirect_uri not in client's registered list | Update client registration or fix the URI. Must match exactly (including trailing slash). |
| invalid_client | Wrong client_id or missing auth for confidential client | Check client_id. Confidential clients must supply client_secret or client assertion. |
| login_required | prompt=none but no active session | Remove prompt=none or redirect the user to login. |