Integrate OIDC Clients with Keycloak on Game Warden¶
This guide walks you through integrating directly with our Identity Provider (IdP), Keycloak, deployed via Platform One’s Big Bang. It covers how to request credentials, configure your application, map claims/roles, and implement login, refresh, and logout flows using OpenID Connect (OIDC).
Who should use this guide?
Customers building their own OIDC client (instead of using Authservice)
Terminology & environment¶
Terminology¶
| Term | Meaning |
|---|---|
| IdP (Keycloak) | The identity provider that issues authentication tokens. |
| Realm | An authentication namespace in Keycloak (e.g., gamewarden). |
| Client | An application registered in Keycloak that consumes OIDC. |
| Confidential Client | Used by backends/services that can safely store a client secret. |
| Public Client | Used by SPAs/browser-based apps; does not store a secret and must use PKCE. |
Base URLs¶
When configuring OIDC, your application needs to know where to retrieve Keycloak’s public configuration and which issuer to trust when validating tokens.
Keycloak exposes two important URLs:
1. OIDC Discovery (Well-Known) URL:¶
This is the endpoint your application calls to automatically retrieve token endpoints, signing keys, and supported claims. Your OIDC library will typically use this URL directly or indirectly.
https://<idp-host>/auth/realms/<YOUR_REALM>/.well-known/openid-configuration
Example Commercial environment:
https://login.secondfront.com/auth/realms/gamewarden/.well-known/openid-configuration
2. Issuer URL (must match exactly):¶
The issuer is the value embedded inside the tokens issued by Keycloak. Your application must trust this value exactly, or token validation will fail.
https://<idp-host>/auth/realms/<YOUR_REALM>
Important
Keycloak always includes /auth in the issuer path.
If your OIDC library expects an issuer without /auth, tokens will be rejected with errors such as:
- Issuer mismatch
- JWKS not found
- Token signature validation failed
Integration steps¶
Requesting access
Submit a request to Second Front with the following details:
- Client name (as you want it to appear in Keycloak)
- Redirect URIs for authentication (e.g., Production and Staging)
- Application type (Web server, SPA, Native, or Machine-to-Machine)
- Whether the client should be Public (no secret, uses PKCE) or Confidential (requires client secret)
- Any required claims (e.g.,
email,groups, custom attributes) - If needed, token lifetime adjustments (access, refresh, offline tokens)
Second Front will provision a Keycloak Client in the appropriate shared realm and provide you with:
- Client ID (and Client Secret, if applicable)
- OIDC Discovery URL (well-known configuration endpoint)
- Any scopes, mappers, or group-based access controls that were configured for the client
Note: Access can be restricted to your organization’s group space (e.g., /Customers/). See Claims, scopes, and group/role mapping for more details.
Choosing your Client Type
| App type | Client type | Auth flow | Notes |
|---|---|---|---|
| Server-rendered Web | Confidential | Authorization Code (+ PKCE recommended) | Store secret server-side only |
| SPA (React/Vue/etc.) | Public | Authorization Code + PKCE (required) | Never embed a client secret |
Configure your Client (Keycloak Admin steps)
Note: These steps are performed by Second Front during client provisioning. They are included here for visibility and review.
-
Create Client (Keycloak → Clients → Create):
- Client Type: OpenID Connect
- Client ID:
us_<UUID>_<CUSTOMER_NAME> - Client Protocol:
openid-connect - Access Type: Confidential (or Public for SPA / native)
- Valid Redirect URIs: Provide exact callback URLs (use wildcards sparingly)
- Post-Logout Redirect URIs: Provide exact return URLs after logout
-
Credentials (Confidential Clients Only):
- Generate a Client Secret (stored server-side only).
-
Login Settings:
- Standard Flow (Authorization Code): ON
- Implicit Flow: OFF (deprecated)
- Direct Access Grants (Password Grant): OFF
- Service Accounts: ON (only if client-credentials flow required)
- PKCE: Required for Public clients (SPA, mobile, desktop)
-
Client Mappers:
- Add claim mappers to include attributes such as
email,roles, or organizational groups. - See Claims, scopes, and group/role mapping for mapping guidance.
- Add claim mappers to include attributes such as
-
Advanced Settings:
- Token lifetimes may be adjusted if needed; otherwise realm defaults apply.
- Note: In certain government environments, token lifetimes may be fixed and cannot be altered.
Application-side configuration
Use the Discovery URL to auto-configure endpoints.
{
"issuer": "https://<idp-host>/auth/realms/gamewarden",
"client_id": "us_<UUID>_<CUSTOMER_NAME>",
"client_secret": "<SECRET-IF-CONFIDENTIAL>",
"redirect_uri": "https://<your-app>/oidc/callback",
"post_logout_redirect_uri": "https://<your-app>/",
"response_type": "code",
"scope": "openid profile email",
"use_pkce": true
}
Auth Code Flow (with PKCE)
-
Redirect the user to the
authorization_endpointwith the following parameters:client_idredirect_uriresponse_type=codescope- PKCE parameters:
code_challengecode_challenge_method=S256
-
Exchange the authorization
codeat thetoken_endpointwith yourcode_verifierto receive:id_tokenaccess_tokenrefresh_token(optional)
-
Validate the ID Token:
- Verify its signature using the realm’s JWKS endpoint from OIDC discovery.
- Confirm that the
aud(audience) andiss(issuer) claims match your client configuration.
Client Credentials Flow (no user)
POST token_endpoint
grant_type=client_credentials
client_id=...&client_secret=...
Claims, scopes, and group/role mapping¶
- Standard OIDC:
sub,iss,aud,exp,iat - Profile/Email:
email,email_verified,given_name,family_name,preferred_username - Groups:
groups(e.g.,/Customers/<CUSTOMER_NAME>/developer) - Custom attributes: e.g.,
customer_id,employee_number(may be added at request of customer)
Example ID Token (truncated)
{
"exp": 1762360748,
"iat": 1762360448,
"jti": "12345678-1234-1234-1234-123456789123",
"iss": "https://login.secondfront.com/auth/realms/gamewarden",
"aud": "us_98fhdje8-kld4-8d23-aa11-mgja92jfh456_example-customer",
"sub": "87654321-4321-4321-4321-321987654321",
"typ": "ID",
"azp": "us_98fhdje8-kld4-8d23-aa11-mgja92jfh456_example-customer",
"sid": "dc23c6a8-280c-4168-aa92-452c235b27a3",
"acr": "1",
"email_verified": false,
"name": "Example User",
"groups": [
"/Gamewarden/Users",
"/Customers/example-customer/developers",
],
"preferred_username": "example.user",
"given_name": "Example",
"family_name": "User",
"email": "example.user@example.com"
}
Restricting group visibility to a customer
We can restrict the groups included in issued tokens so that users only receive groups under: /Customers/<CUSTOMER_NAME>/....
This ensures your application only sees roles and permissions relevant to your organization.
Note
If your application requires additional custom claims (e.g., user role, tenant ID, or feature flags), please provide the claim names and expected data types and our team will configure the appropriate mappers.
Token lifetimes & refresh strategy¶
Game Warden environments follow security-first token lifetimes aligned with DoW and industry best practices:
- Access Token: Short-lived (≈ 5 minutes) — limits the impact of token leakage.
- Refresh Token: Longer-lived (≈ 30 minutes) and rotates on each use — reduces replay risk.
- SSO Session Duration: Typically up to 10 hours before requiring re-authentication.
These defaults balance strong security controls with a smooth user experience. If your application requires different lifetimes, discuss with our team—adjustments may be possible depending on your deployment environment and compliance level.
Best practice
Use short-lived access tokens paired with rotating refresh tokens to minimize risk if a token is compromised.
Logout & session management¶
When users sign out, the application should trigger RP-Initiated Logout, which logs the user out of both your application and the Keycloak SSO session.
RP-initiated logout (recommended)¶
Call the realm’s end_session_endpoint with:
id_token_hint— the ID Token issued during loginpost_logout_redirect_uri— a pre-registered URL where the user should be redirected after logout
Example call
GET https://<idp-host>/auth/realms/<YOUR_REALM>/protocol/openid-connect/logout
?id_token_hint=eyJ...
&post_logout_redirect_uri=https%3A%2F%2F<your-app>%2F
Important
The value of post_logout_redirect_uri must exactly match one of the URIs listed in the client configuration.
Front-channel vs back-channel logout¶
Keycloak supports multiple logout notification mechanisms:
| Mode | How it Works | Use When |
|---|---|---|
| Front-channel logout | Keycloak loads each client’s logout URL in the browser. | Your app can handle logout via browser redirect. |
| Back-channel logout | Keycloak sends a server-to-server logout request. | Your app has a backend endpoint for logout processing. |
If your application expects to be notified when the user logs out from another session, provide:
- A logout endpoint URL
- Expected authentication/validation behavior for the logout request
Troubleshooting
If you see a Keycloak confirmation page during logout, check:
id_token_hintis missing or expiredpost_logout_redirect_uriis not in the allowed list
Adding both parameters correctly will produce a silent, seamless logout experience.
Security guidance¶
-
Do not store client secrets in browser-based or mobile applications. Use Public clients with PKCE for SPAs and native apps.
-
Always validate Issuer and JWKS:
- Issuer must match realm URL including
/auth - Validate token signatures against the realm’s JWKS
-
Verify
aud,iss,nonce, and token expiration -
Use state + nonce with Authorization Code Flow and verify both during the callback to prevent CSRF and replay attacks.
-
Apply least-privilege access:
- Request only the scopes and claims your application actually needs.
-
Avoid broad group claims unless necessary.
-
Consider refresh token rotation and server-side session enforcement for added protection.
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
could_not_discover_issuer / “Not found” |
Wrong issuer URL (missing /auth) |
Use https://<idp-host>/auth/realms/<YOUR_REALM> |
invalid_grant / code exchange fails |
Missing/wrong code_verifier |
Ensure PKCE end-to-end |
redirect_uri_mismatch |
Callback not whitelisted | Add exact redirect URI in client |
invalid_audience |
Token aud doesn’t include your client |
Add audience mapper / check resource_access |
| Logout shows confirmation page | No id_token_hint |
Pass id_token_hint and whitelist post_logout_redirect_uri |
Samples¶
# 1) Discover endpoints
curl -s https://<idp-host>/auth/realms/<YOUR_REALM>/.well-known/openid-configuration | jq .
# 2) Browser to authorization endpoint (build URL)
# https://<idp-host>/auth/realms/<YOUR_REALM>/protocol/openid-connect/auth?response_type=code&client_id=...
# 3) Exchange code for tokens
curl -s -X POST \
-d grant_type=authorization_code \
-d code=<CODE_FROM_CALLBACK> \
-d client_id=cust-<CUSTOMER_NAME>-<APP> \
-d client_secret=<SECRET> \
-d redirect_uri=https://<your-app>/oidc/callback \
https://<idp-host>/auth/realms/<YOUR_REALM>/protocol/openid-connect/token
curl -s -X POST \
-d grant_type=client_credentials \
-d client_id=cust-<CUSTOMER_NAME>-svc \
-d client_secret=<SECRET> \
https://<idp-host>/auth/realms/<YOUR_REALM>/protocol/openid-connect/token
Support & changes¶
If you need to update your OIDC client configuration (e.g., add redirect URIs, rotate secrets, adjust claims), please open a support request with the following information:
- Client ID
- Environment (e.g., Staging, Production)
- Requested change
- Reason / justification
For urgent items such as incident response, credential compromise, or access revocation, contact Support and mark the request as High Priority so our team can respond immediately.