Create a Keycloak realm with a confidential OIDC client, configure client scopes and a custom claim mapper, and exchange tokens with token introspection
Using the Keycloak Admin REST API, create a realm: POST /admin/realms with body {"realm": "myrealm", "enabled": true}
Create a confidential client: POST /admin/realms/myrealm/clients with {"clientId": "myapp", "protocol": "openid-connect", "publicClient": false, "serviceAccountsEnabled": true, "standardFlowEnabled": true, "redirectUris": ["https://myapp.example.com/callback"]}
Create a custom client scope: POST /admin/realms/myrealm/client-scopes with {"name": "employee-id", "protocol": "openid-connect"}, then add a user attribute protocol mapper to it that maps user attribute 'employee_id' to claim 'employee_id' in both ID and access tokens
Assign the scope to the client as a default scope: PUT /admin/realms/myrealm/clients/<CLIENT_ID>/default-client-scopes/<SCOPE_ID>
Perform the authorization code + PKCE flow: generate code_verifier and code_challenge, redirect to /realms/myrealm/protocol/openid-connect/auth with response_type=code, code_challenge, and code_challenge_method=S256, then exchange the code at /realms/myrealm/protocol/openid-connect/token with code_verifier
Introspect the access token to verify claims: POST /realms/myrealm/protocol/openid-connect/token/introspect with client credentials and token parameter
Known gotchas
Client scopes added as 'optional' scopes require the client to explicitly request them in the 'scope' parameter; missing this causes the claim to be absent from the token with no error
The Keycloak service account user for a client (created when serviceAccountsEnabled=true) must have the user attribute set separately from regular users — the attribute is on the service account user entity, not the client
Token introspection returns 'active: false' for expired tokens without an error HTTP status; callers that only check HTTP 200 without inspecting the 'active' field will incorrectly treat expired tokens as valid
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp