docs(security): document client credentials for machine-to-machine callers - #191
Open
adityamparikh wants to merge 1 commit into
Open
docs(security): document client credentials for machine-to-machine callers#191adityamparikh wants to merge 1 commit into
adityamparikh wants to merge 1 commit into
Conversation
…llers Every token example in keycloak.md uses the password grant with a test user, so a service calling this server on its own behalf -- an agent, a scheduled job, another application -- has no documented path. The confidential client it needs is already described under Creating Clients; what was missing is the grant that uses it. The gap that actually bites is the audience mapper. The Quick Start attaches it to the public client used by MCP Inspector, so a service client created by following Creating Clients has none of its own, and its tokens are issued normally and then rejected with 401 by validateAudienceClaim(true). The new section says where the mapper belongs, shows how to add it to the service client, and shows how to confirm the claim landed. Also fixes the audience check under Troubleshooting. A JWT payload is base64url without padding, so `base64 -d` truncates it and jq reports "Unfinished string at EOF" instead of the claim -- the failure looks like a malformed token when the token is fine. Replaced with a jq-only decode that tolerates the missing padding. Every command in the new section was run verbatim against Keycloak 26 and a running server, and produces the output shown. Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011nUD34DFfoJeyQRTquPy7a
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's missing today
Every token example in
docs/security/keycloak.mduses the password grant withtestuser. Aservice that calls this MCP server on its own behalf — an agent, a scheduled job, another
application — has no user to authenticate as, and no documented path. The confidential client it
needs is already described under Creating Clients; what was missing is the grant that uses it.
The part that actually bites
The audience mapper. The Quick Start attaches it to the public client used by MCP Inspector, so
a service client created by following Creating Clients has none of its own:
validateAudienceClaim(true)finds no matchingaudand rejects it. The new Machine-to-MachineTokens section states where the mapper belongs, shows adding it to the service client, and shows
confirming that the claim landed before an application is pointed at it.
Also fixed: the audience check under Troubleshooting
A JWT payload is base64url without padding, so
base64 -dtruncates it and jq reportsparse error: Unfinished string at EOF— which reads like a malformed token when the token isperfectly fine. That is a bad failure mode for a troubleshooting step whose whole job is telling you
whether the token is good. Replaced with a jq-only decode that tolerates the missing padding:
Verification
Every command in the new section was run verbatim against Keycloak 26 and a running Solr MCP server,
and produces the output shown in the doc:
client_credentialsgrant against the confidential clientaudcheck["http://localhost:8080/mcp", "account"]/.well-known/oauth-protected-resourcehttp://localhost:8080/mcpparse error: Unfinished string at EOFDocs only — no code or test changes.
🤖 Generated with Claude Code
https://claude.ai/code/session_011nUD34DFfoJeyQRTquPy7a