Skip to main content

Keycloak

The supplied environment uses Keycloak 26.x. The working reference pattern uses AIGW private_key_jwt, which the supplied backend implements as an RFC 7523 JWT bearer authorization grant for the user assertion plus JWT client authentication for the AIGW client.

This is not the same thing as simply enabling Keycloak Standard Token Exchange. In the supplied notes, Keycloak Standard Token Exchange does not accept the external AIGW-signed subject token in the tested standard mode, so the RFC 7523 path is recommended for this setup.

Before you start​

Collect these values from the AIGW ResourceResourceThe downstream system registered in a Project. Its kind (Token exchange or OAuth client) decides the role AIGW plays.:

  • AIGW Resource authorization-server/issuer URL, for example https://api.aigw.eval.loginid.ai/<RESOURCE_ID>;
  • Resource JWKSJWKSJSON Web Key Set: a published set of public keys used to verify JWT signatures. URL https://api.aigw.eval.loginid.ai/<RESOURCE_ID>/.well-known/jwks.json;
  • client ID configured in the AIGW Resource;
  • requested scopes;
  • your Keycloak realm issuer and token endpoint.

The AIGW Resource Reference page exposes the merchant-facing values.

AIGW reference

Step 1 — Create a JWT Authorization Grant Identity Provider​

In Keycloak go to Identity providers → Add provider → JWT Authorization Grant.

Add provider

Configure:

FieldValue
AliasUnique alias for this AIGW Resource, e.g. aigw-demo-search-api
IssuerAIGW per-resource issuer
Use JWKS URLOn
JWKS URLAIGW per-resource JWKS URL
Max allowed assertion expiration1 hour in the supplied setup
Assertion signature algorithmES256
Allow assertion reuseOff in the reference setup
Allowed clock skew60 seconds in the reference setup

JWT grant IdP form

After saving, verify that the provider exists and still points to the intended Resource issuer/JWKS.

IdP created

One IdP per AIGW Resource in this pattern

The AIGW issuer is per Resource. A Keycloak JWT Authorization Grant IdP configured for Resource A should not be reused for Resource B with a different issuer.

Step 2 — Create the Keycloak client used by AIGW​

Go to Clients → Create client and choose OpenID Connect.

Exact match required

The Client ID must exactly match the Client ID configured on the AIGW Resource.

In Capability config:

  • Client authentication: On
  • Standard flow: Off for the newly created back-channel client in the supplied walkthrough
  • JWT Authorization Grant: On
  • Allowed Identity Providers for JWT Authorization Grant: the IdP alias from step 1
  • Standard Token Exchange was also enabled in the tested console, but the AIGW Keycloak recommendation still uses the JWT Authorization Grant path

Client capability

Step 3 — Configure Signed JWT client authentication​

Open the client Credentials tab:

  • Client Authenticator: Signed JWT
  • Signature algorithm: ES256
  • Max expiration: 1 minute in the reference setup

Signed JWT credentials

When Keycloak asks Change to client-jwt?, confirm the change. Otherwise the new authenticator is not saved.

Next open Keys:

  • Use JWKS URL: On
  • JWKS URL: the same AIGW Resource JWKS URL

JWKS

Using a JWKS URL lets Keycloak fetch an updated key when AIGW rotates to a new kid.

Step 4 — Configure the custom audience mapping​

The supplied AIGW user/client assertions use the AIGW Resource's configured Issuer URL (the merchant AS issuer) as aud.

In Keycloak open the client Advanced → OpenID Connect Compatibility Modes → Custom audience mapping and map:

<JWT Authorization Grant IdP alias> -> <Keycloak realm issuer>

Example:

aigw-demo-search-api -> https://id.example.com/realms/shop

Audience mapping

This mapping is essential in the supplied working reference.

Step 5 — Create and attach merchant scopes​

For every AIGW Requested scope, create a Keycloak client scope with the same protocol value.

Example for search:read:

  • Name: search:read
  • Type: None
  • Protocol: OpenID Connect
  • Include in token scope: On

Create scope

Then open the AIGW client and attach the scope as Optional.

Attach scope

Using Type None avoids assigning the scope as a realm-wide default to unrelated clients.

Step 6 — Point the AIGW Resource to Keycloak​

Back in AIGW, open the Token exchange ResourceToken exchange ResourceA Resource for agent access: AIGW authorizes the user and obtains a token from the merchant's own authorization server. Configuration and set:

Issuer URL = https://<keycloak>/realms/<realm>
Token endpoint = https://<keycloak>/realms/<realm>/protocol/openid-connect/token
Client ID = <the Keycloak client created above>
Method = private_key_jwt

AIGW Resource configuration

Reload after saving and verify the values persisted.

Step 7 — Define user matching/provisioning​

This is the part most likely to block the first real exchange.

AIGW tries user assertion sub values using login-evidence emails first and the AIGW pairwise subject last. The supplied Keycloak reference user was linked to the JWT Authorization Grant IdP using a federated identity link whose external user ID matched the AIGW subject.

A new JWT Authorization Grant IdP starts with no linked users. Decide whether you will:

  • pre-link known users;
  • map email to an existing Keycloak user;
  • auto-create/link a Keycloak user through a custom flow/extension;
  • reject unknown users.

The supplied material does not verify auto-provisioning for the newly created IdP, so do not assume it works without testing.

Step 8 — Validate the setup​

Check each layer separately:

  1. Keycloak can fetch the AIGW Resource JWKS.
  2. The Keycloak client uses Signed JWT/ES256.
  3. Audience mapping points the IdP alias to the realm issuer.
  4. Every requested AIGW scope exists and is attached.
  5. The target user can be resolved from the assertion sub.
  6. AIGW Resource issuer/token endpoint/client ID exactly match Keycloak.
  7. Assertion lifetime is accepted by Keycloak's configured maximum-expiration rules.

Common Keycloak pitfalls​

ProblemWhy it happensFix
IdP alias collisionAdd-provider form may prefill jwt-authorization-grantUse a unique alias per AIGW Resource
New scope never appearsInclude in token scope defaults OffTurn it On
Scope accidentally assigned widelyClient scope Type set to Default/Optional during creationUse Type=None, then attach explicitly
invalid_clientSigned JWT/JWKS/algorithm/lifetime mismatchRecheck client credentials + keys
invalid_grant / user not foundNo user mapping/link for assertion subConfigure mapping/provisioning
JWT rejected for audienceCustom audience mapping missingMap IdP alias to realm issuer
Key rotation failsKeycloak has static key instead of JWKS URLConfigure the Resource JWKS URL
Verification status

All objects shown above were created and saved in the supplied Keycloak environment, and the AIGW Resource was pointed at that configuration. The full AIGW → Keycloak → merchant-token exchange for the new Resource was not completed end to end in the supplied run.