Skip to content

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.

  1. Create Client (Keycloak → ClientsCreate):
    • 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
  2. Credentials (Confidential Clients Only):
    • Generate a Client Secret (stored server-side only).
  3. 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)
  4. Client Mappers:
  5. 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)
  1. Redirect the user to the authorization_endpoint with the following parameters:
    • client_id
    • redirect_uri
    • response_type=code
    • scope
    • PKCE parameters:
      • code_challenge
      • code_challenge_method=S256
  2. Exchange the authorization code at the token_endpoint with your code_verifier to receive:
    • id_token
    • access_token
    • refresh_token (optional)
  3. Validate the ID Token:
    • Verify its signature using the realm’s JWKS endpoint from OIDC discovery.
    • Confirm that the aud (audience) and iss (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.

Call the realm’s end_session_endpoint with:

  • id_token_hint — the ID Token issued during login
  • post_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_hint is missing or expired
  • post_logout_redirect_uri is 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.