OIDC Authentication
Configure OpenID Connect SSO for AllureDeck with role mapping from identity provider group claims.
Overview
AllureDeck supports two authentication methods operating simultaneously:
- Local authentication — static admin/viewer credentials via environment variables
- OIDC SSO — OpenID Connect with any compliant identity provider
Local auth serves as a break-glass fallback when SSO is enabled.
| Role | Permissions |
|---|---|
| admin | Full access: create/delete projects, manage reports, manage users, system settings, API keys |
| editor | Upload results, generate reports, manage known issues, set default branches |
| viewer | Read-only access to all reports, dashboards, and analytics |
How It Works
AllureDeck uses the Authorization Code + PKCE flow. The entire OIDC exchange happens server-side — the frontend only provides an SSO button.
Browser AllureDeck API Identity Provider | | | |-- click "Sign in with SSO" -> | | |-- redirect with PKCE -------> | | | | |<---- authorization code -----| | | | | |-- exchange code + verifier -> | |<---- ID token ---------------| | | | | | validate token, extract claims, | | resolve role from groups, | | JIT-provision user record, | | issue AllureDeck JWT cookies | | | |<-- redirect with cookies ---| |
Key security properties:
- PKCE (S256) on every authorization request
- State parameter encrypted with AES-GCM in an httpOnly cookie
- Nonce validated in the ID token to prevent replay attacks
- Group claims read from the signed ID token only (not userinfo endpoint)
- JIT provisioning — user records created on first login, updated on subsequent logins
Configuration Reference
All OIDC settings are provided via environment variables. Variables marked with * are required when OIDC_ENABLED=true — the server refuses to start if they are missing.
| Environment Variable | Required | Default | Description |
|---|---|---|---|
| OIDC_ENABLED | No | false |
Master toggle for SSO |
| OIDC_ISSUER_URL | Yes* | — | IdP discovery URL (must support /.well-known/openid-configuration) |
| OIDC_CLIENT_ID | Yes* | — | OAuth2 client ID registered with the IdP |
| OIDC_CLIENT_SECRET | Yes* | — | OAuth2 client secret (confidential client) |
| OIDC_REDIRECT_URL | Yes* | — | Callback URL: https://<your-domain>/api/v1/auth/oidc/callback |
| OIDC_SCOPES | No | openid,profile,email |
Comma-separated OIDC scopes |
| OIDC_GROUPS_CLAIM | No | groups |
JWT claim name containing group memberships |
| OIDC_ADMIN_GROUPS | No | — | Comma-separated group IDs mapping to admin role |
| OIDC_EDITOR_GROUPS | No | — | Comma-separated group IDs mapping to editor role |
| OIDC_DEFAULT_ROLE | No | viewer |
Role assigned when no group matches |
| OIDC_STATE_COOKIE_SECRET | Yes* | — | AES encryption key for state cookies (exactly 32 bytes) |
| OIDC_POST_LOGIN_REDIRECT | No | / |
Frontend URL after successful SSO login |
| OIDC_END_SESSION_URL | No | — | RP-initiated logout URL (optional) |
* Required when OIDC_ENABLED=true. Server refuses to start if missing.
Role Mapping
Roles are resolved from IdP group claims using highest-priority-wins:
- If any group matches
OIDC_ADMIN_GROUPS→ admin - Else if any matches
OIDC_EDITOR_GROUPS→ editor - Else →
OIDC_DEFAULT_ROLE(default: viewer)
User Lifecycle
- First login: User record created automatically (JIT provisioning) with resolved role
- Subsequent logins: Name, email, and role updated from latest token claims
- Deactivation: Set
is_active=falsein users table. User receives 403 on next SSO login
Provider Setup
Select your identity provider below for step-by-step configuration instructions.
Azure AD (Entra ID)
- Register an application in Azure Portal → App registrations
- Set redirect URI to
https://alluredeck.example.com/api/v1/auth/oidc/callback(Web platform) - Create a client secret under Certificates & secrets
- Under Token configuration, add optional
groupsclaim (Security groups, type: Group ID) - Note your tenant ID
OIDC_ENABLED=true OIDC_ISSUER_URL=https://login.microsoftonline.com/<tenant-id>/v2.0 OIDC_CLIENT_ID=<application-client-id> OIDC_CLIENT_SECRET=<client-secret-value> OIDC_REDIRECT_URL=https://alluredeck.example.com/api/v1/auth/oidc/callback OIDC_GROUPS_CLAIM=groups OIDC_ADMIN_GROUPS=<azure-ad-group-object-id-for-admins> OIDC_EDITOR_GROUPS=<azure-ad-group-object-id-for-editors> OIDC_STATE_COOKIE_SECRET=<32-byte-random-string>
_claim_sources reference instead of inline groups. AllureDeck detects this and assigns OIDC_DEFAULT_ROLE.
Keycloak
- Create client in realm (Client type: OpenID Connect, Access type: confidential)
- Set Valid redirect URIs to
https://alluredeck.example.com/api/v1/auth/oidc/callback - Under Client scopes → add mapper of type "Group Membership" with token claim name
groups
OIDC_ENABLED=true OIDC_ISSUER_URL=https://keycloak.example.com/realms/<realm> OIDC_CLIENT_ID=alluredeck OIDC_CLIENT_SECRET=<client-secret> OIDC_REDIRECT_URL=https://alluredeck.example.com/api/v1/auth/oidc/callback OIDC_GROUPS_CLAIM=groups OIDC_ADMIN_GROUPS=alluredeck-admins OIDC_EDITOR_GROUPS=alluredeck-editors OIDC_STATE_COOKIE_SECRET=<32-byte-random-string>
Google Workspace
- Create OAuth 2.0 credentials in Google Cloud Console → APIs & Services → Credentials
- Set authorized redirect URI to
https://alluredeck.example.com/api/v1/auth/oidc/callback - Note: Google does not provide group claims by default
OIDC_DEFAULT_ROLE unless you use Google Workspace directory groups with a custom claim mapper.
OIDC_ENABLED=true OIDC_ISSUER_URL=https://accounts.google.com OIDC_CLIENT_ID=<client-id>.apps.googleusercontent.com OIDC_CLIENT_SECRET=<client-secret> OIDC_REDIRECT_URL=https://alluredeck.example.com/api/v1/auth/oidc/callback OIDC_DEFAULT_ROLE=editor OIDC_STATE_COOKIE_SECRET=<32-byte-random-string>
Okta
- Create an OIDC Web Application in Okta Admin Console
- Set sign-in redirect URI to
https://alluredeck.example.com/api/v1/auth/oidc/callback - Under Sign On → OpenID Connect ID Token, add a Groups claim filter
OIDC_ENABLED=true OIDC_ISSUER_URL=https://<your-okta-domain>/oauth2/default OIDC_CLIENT_ID=<client-id> OIDC_CLIENT_SECRET=<client-secret> OIDC_REDIRECT_URL=https://alluredeck.example.com/api/v1/auth/oidc/callback OIDC_GROUPS_CLAIM=groups OIDC_ADMIN_GROUPS=alluredeck-admins OIDC_EDITOR_GROUPS=alluredeck-editors OIDC_STATE_COOKIE_SECRET=<32-byte-random-string>
Deployment Examples
Docker Compose
services:
allure-api:
environment:
OIDC_ENABLED: "true"
OIDC_ISSUER_URL: "https://login.microsoftonline.com/<tenant>/v2.0"
OIDC_CLIENT_ID: "<client-id>"
OIDC_CLIENT_SECRET: "<client-secret>"
OIDC_REDIRECT_URL: "http://localhost:5050/api/v1/auth/oidc/callback"
OIDC_ADMIN_GROUPS: "<admin-group-id>"
OIDC_EDITOR_GROUPS: "<editor-group-id>"
OIDC_STATE_COOKIE_SECRET: "<32-byte-random-string>"
Helm Chart
api:
oidc:
enabled: true
issuerUrl: "https://login.microsoftonline.com/<tenant>/v2.0"
clientId: "<client-id>"
clientSecret: "<client-secret>"
redirectUrl: "https://alluredeck.example.com/api/v1/auth/oidc/callback"
adminGroups: "<admin-group-id>"
editorGroups: "<editor-group-id>"
stateCookieSecret: "<32-byte-random-string>"
clientSecret and stateCookieSecret in a Kubernetes Secret. If left empty, random values are auto-generated on first install and preserved across upgrades.
Generating Secrets
The OIDC_STATE_COOKIE_SECRET must be exactly 32 bytes. Use any of these methods to generate one:
# OpenSSL openssl rand -base64 32 | head -c 32 # Python python3 -c "import secrets; print(secrets.token_urlsafe(24)[:32])" # /dev/urandom head -c 32 /dev/urandom | base64 | head -c 32
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Server refuses to start with "OIDC_ISSUER_URL is required" | OIDC enabled but required fields missing | Set all required env vars |
| Server refuses to start with secret length error | Key length wrong | Generate key of exactly 32 bytes |
| "OIDC discovery failed" at startup | Cannot reach issuer URL | Verify OIDC_ISSUER_URL is reachable and returns .well-known/openid-configuration |
| SSO login redirects but callback returns 400 | State mismatch or expired | Ensure OIDC_REDIRECT_URL matches IdP; check clock sync |
| User gets viewer role despite admin group | Group ID mismatch | Compare group claim value against OIDC_ADMIN_GROUPS; Azure uses GUIDs, Keycloak uses paths |
| Azure AD user gets viewer despite membership | Group overage (200+ groups) | Reduce group count or use filtered claims |
| User gets 403 after successful SSO | Account deactivated | Check is_active in users table |
| SSO button not visible | Config reports OIDC disabled | Verify OIDC_ENABLED=true and API reachable |