Configure your authorization server

Configure your authorization server

Trust AIGW from Keycloak or any OAuth server with RFC 7523 or RFC 8693.

Checked against the Evaluation environment, Console 0.10.1 / 0.14.1, on October 19, 2026. Release status

This guide is for the team that runs the merchant's authorization server (AS). AIGW does not ask your API to trust the agent's AIGW token. Instead, AIGW gets a token from your existing AS, and only your MCP or UCP service sees that merchant token. Your job is to make your AS trust AIGW and to decide how AIGW users map to your users.

How AIGW reaches your server

Each Token exchange Resource in the AIGW Console has its own issuer and its own ES256 signing key. With the default method, your AS needs two trust relationships with that Resource:

  • Trust the Resource as an assertion issuer. AIGW sends a user assertion signed with ES256 by the per-resource issuer, verifiable at the per-resource JWKS.
  • Trust AIGW as a client. AIGW authenticates as the client you registered for it, using a JWT client assertion signed by the same Resource key.

Your AS also has to:

  • accept your own issuer URL, as configured on the Resource, as the JWT aud;
  • define every scope name AIGW will request;
  • map the assertion sub to a merchant user, or link or provision that user under your policy;
  • issue an access token your backend accepts.

Choose a method

The method is set in the Resource's Client authentication field. It decides what AIGW sends to your token endpoint.

Console valueWhat AIGW sendsStatus
private_key_jwtRFC 7523 JWT bearer user assertion plus JWT client authentication. The default, and the method the Keycloak walkthrough uses.Supported with the Playground's preconfigured Keycloak Resource. Unverified on a newly configured Resource.
token_exchangeRFC 8693 token exchange with an external, AIGW-signed subject token and JWT client authentication.Unverified
client_secret_basicClient ID and secret over HTTP Basic. The Console collects a secret for it.Unsupported Use private_key_jwt instead.

Values you receive

Whoever operates the AIGW Resource (you, or your MCP or UCP provider) hands you these values. They are on the Resource's Reference step and at the bottom of its Configuration tab.

ValueWhat you use it for
Per-resource issuerTrusted assertion issuer, for example https://api.aigw.eval.loginid.ai/<RESOURCE_ID>
Per-resource JWKS URLVerifying the ES256 assertions, for example https://api.aigw.eval.loginid.ai/<RESOURCE_ID>/.well-known/jwks.json
Client IDIdentifies AIGW at your AS. You create this client; AIGW stores the same value.
Requested scopesThe permissions AIGW may request. Each must exist in your AS.
Merchant issuer URLYour AS issuer. It must match the Resource configuration and is the assertion audience.
Merchant token endpointWhere AIGW sends the grant.

Keycloak 26

This walkthrough uses Keycloak 26.x and the private_key_jwt method: an RFC 7523 JWT bearer grant for the user plus Signed JWT client authentication for AIGW. Do not swap in Keycloak's Standard Token Exchange. In its standard mode it does not accept the external AIGW-signed subject token, so the RFC 7523 path is the one to use.

Before you start, have the Resource issuer, the Resource JWKS URL, the Client ID set on the Resource, the requested scopes, and your realm issuer and token endpoint ready.

Add a JWT Authorization Grant identity provider

Who: Merchant IAM admin

In Keycloak, open Identity providers, choose Add provider, then JWT Authorization Grant.

FieldValue
AliasA unique alias for this AIGW Resource, for example aigw-demo-search-api
IssuerThe AIGW per-resource issuer
Use JWKS URLOn
JWKS URLThe AIGW per-resource JWKS URL
Max allowed assertion expiration1 hour
Assertion signature algorithmES256
Allow assertion reuseOff
Allowed clock skew60 seconds

After saving, reopen the provider and confirm it still points at the intended issuer and JWKS URL.

One identity provider per Resource

The AIGW issuer is per Resource. Do not reuse the provider you made for Resource A on Resource B. The add form may prefill the alias jwt-authorization-grant; replace it so aliases never collide.

Create the client AIGW uses

Who: Merchant IAM admin

Open Clients, choose Create client, and pick OpenID Connect. The Client ID must match the Client ID on the AIGW Resource exactly.

Capability configValue
Client authenticationOn
Standard flowOff. This is a back-channel client.
JWT Authorization GrantOn
Allowed identity providers for JWT Authorization GrantThe alias from the previous step

Configure Signed JWT client authentication

Who: Merchant IAM admin

On the client's Credentials tab:

SettingValue
Client AuthenticatorSigned JWT
Signature algorithmES256
Max expiration1 minute

When Keycloak asks Change to client-jwt?, confirm. If you skip the prompt, the new authenticator is not saved.

Then, on the Keys tab, turn Use JWKS URL on and enter the same AIGW Resource JWKS URL. With a URL instead of a pasted key, Keycloak fetches the new key when AIGW rotates to a new kid.

Map the custom audience

Who: Merchant IAM admin

AIGW sets the assertion aud to the Issuer URL configured on the Resource, which is your realm issuer. Open the client's Advanced tab, then OpenID Connect Compatibility Modes, then Custom audience mapping, and map the identity provider alias to the realm issuer.

Custom audience mapping
# <IdP alias> -> <realm issuer>aigw-demo-search-api -> https://id.example.com/realms/shop

Without this mapping Keycloak rejects the JWT for its audience.

Create and attach merchant scopes

Who: Merchant IAM admin

For every scope requested on the AIGW Resource, create a Keycloak client scope with the same protocol value. For search:read:

Client scope fieldValue
Namesearch:read
TypeNone
ProtocolOpenID Connect
Include in token scopeOn

Then open the AIGW client and attach the scope as Optional. Type None keeps the scope from becoming a realm-wide default for unrelated clients. Include in token scope defaults to Off, so check it.

Point the AIGW Resource at Keycloak

Who: Resource operator

In the AIGW Console, open the Token exchange Resource's Configuration tab and set:

Resource configuration
Issuer URL      https://id.example.com/realms/<realm>Token endpoint  https://id.example.com/realms/<realm>/protocol/openid-connect/tokenClient ID       <the exact Client ID of the Keycloak client>Method          private_key_jwt

Save, reload the page and confirm every value persisted.

Decide how users are matched

Who: Merchant IAM admin

This is the step most likely to block your first real exchange. A new JWT Authorization Grant provider starts with no linked users, so AIGW's assertion sub has to resolve to someone. Pick one approach:

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

The reference setup linked its test user to the provider with a federated identity link whose external user ID matched the AIGW subject. Auto-provisioning on a newly created provider is Unverified, so test it before you depend on it. The resolution order is under How users are resolved.

Common Keycloak problems

ProblemWhy it happensFix
Identity provider alias collisionThe add form prefills jwt-authorization-grantUse a unique alias per Resource.
A new scope never appears in tokensInclude in token scope defaults to OffTurn it on.
A scope is assigned to every clientClient scope Type was set to Default or Optional at creationSet Type to None, then attach it explicitly.
invalid_clientSigned JWT, JWKS, algorithm or lifetime mismatchRecheck the client's Credentials and Keys tabs.
invalid_grant with user not foundNo mapping or link for the assertion subConfigure user mapping or provisioning.
JWT rejected for its audienceCustom audience mapping is missingMap the alias to the realm issuer.
Key rotation breaks verificationKeycloak holds a static key instead of the JWKS URLConfigure the Resource JWKS URL.

Any other OAuth server

If you don't run Keycloak, implement one of these two contracts. Equivalent verified console walkthroughs for Auth0 and Okta are not available for this release, so this section describes the protocol only.

Option A: RFC 7523 JWT bearer (private_key_jwt)

AIGW sends two JWTs to your token endpoint, both signed ES256 with the Resource signing key: a user assertion used with the JWT bearer grant, and a client assertion for JWT client authentication.

Token request shapehttp
POST <merchant token endpoint>Content-Type: application/x-www-form-urlencodedgrant_type=urn:ietf:params:oauth:grant-type:jwt-bearer# plus the ES256 user assertion and a JWT client assertion (RFC 7523)

Only the grant type is documented for this release. The other form parameter names are expected to follow RFC 7523 but are Unverified.

User assertion claims
iss = https://api.aigw.eval.loginid.ai/<RESOURCE_ID>sub = external user reference (email candidates, then the AIGW subject)aud = <merchant issuer URL configured on the Resource>iat = nowexp = now + assertion lifetimejti = unique UUID
Client assertion claims
iss = <merchant AS client ID>sub = <merchant AS client ID>aud = <merchant issuer URL configured on the Resource>iat = nowexp = now + assertion lifetimejti = unique UUID

Option B: RFC 8693 token exchange (token_exchange)

Unverified AIGW can instead send a token exchange request with JWT client authentication:

Token request shapehttp
POST <merchant token endpoint>Content-Type: application/x-www-form-urlencodedgrant_type=urn:ietf:params:oauth:grant-type:token-exchangesubject_token=<AIGW-signed subject token>subject_token_type=urn:ietf:params:oauth:token-type:jwtrequested_token_type=urn:ietf:params:oauth:token-type:access_tokenresource=<resource indicator>scope=<requested scopes># plus JWT client authentication

Your AS must accept an external subject token

The subject token is signed by AIGW, not by your AS. Do not assume a product's standard token exchange feature accepts external subject tokens. Keycloak's standard mode does not for this pattern.

Scope and response contract

  • Every scope AIGW requests should exist in your AS and map to the permission your API expects. AIGW sends the requested scope string, intersected with what is allowed, to your token endpoint.
  • On success, return a standard OAuth access token response.
  • In RFC 8693 mode, also return issued_token_type set to the access token type and a meaningful token_type.

Trust the Resource JWKS

AIGW signs merchant-facing assertions with a per-Resource EC P-256 key (ES256). A first key is generated when the Resource is created, so the JWKS URL works immediately. Check that your AS can reach it:

Fetch the Resource JWKSbash
curl -s "https://api.aigw.eval.loginid.ai/<RESOURCE_ID>/.well-known/jwks.json"
  • Configure the JWKS URL, not a pinned public key. When the operator creates a new signing key, it becomes active and older keys stay in the JWKS during rotation.
  • Select keys by kid and refetch the JWKS when you see an unknown kid.
  • Don't confuse this key set with the core JWKS at https://core.api.aigw.eval.loginid.ai/.well-known/jwks.json. The core set signs agent-facing AIGW access tokens. Your AS trusts the per-resource set only.

How users are resolved

AIGW tries sub candidates in this order:

  1. each email available from the user's login evidence, in order;
  2. the AIGW pairwise subject.

It moves to the next candidate only when your AS returns invalid_grant with an error description containing user not found. Any other error stops the sequence. So decide what your user identifier is: if you match on email, make sure your grant implementation really resolves users by email; if you require federated links, create them or provision them.

Test your setup

Check each layer on its own before you run a full flow:

  1. Your AS can fetch the Resource JWKS.
  2. The AIGW client authenticates with Signed JWT and ES256.
  3. The audience mapping points the alias, or your audience check, at your issuer.
  4. Every requested scope exists and is attached to the client.
  5. The target user resolves from the assertion sub.
  6. The Resource issuer, token endpoint and Client ID match your AS exactly.
  7. Your maximum expiration rules accept the assertion lifetime.

Then run a real end-to-end flow: an agent authorizes, and the MCP or UCP service redeems the merchant token. The Playground runs that flow in your browser.

The Console Test exchange button produces no result

Unsupported The Test exchange button on the Resource's Reference step and Configuration tab shows no result in this release. Test with a real flow or the Playground instead.

Redemption is Supported with the Playground's preconfigured private_key_jwt Keycloak Resource. A full exchange against a Resource you configure yourself is Unverified, so test yours end to end before production.

Next steps