Repository navigation
Conversation
An A2A agent with auth_type="oauth" stored oauth_config but never used
it. The gateway now gets an agent-level client_credentials token before
it calls the agent.
- Send the RFC 8707 resource on the token request. Use the configured
value, else the origin of the agent endpoint.
- Validate token audience, scopes, and issuer with
validate_oauth_token_claims() before the gateway forwards the token.
Apply the gateway precedence and OAUTH_REQUIRE_CONFIGURED_RESOURCE.
- Cache the token per agent in the service-token cache. The key covers
the resource and the client credentials.
- Add send_resource to get_client_credentials_token_response(). It is
off by default, so existing callers keep their request shape.
- Wire the token into A2AAgentService.invoke_agent and both A2A paths
in ToolService.
Other grant types fail with an error. The per-user authorization_code
flow and the Resource field on the A2A forms stay open under #5815.
Signed-off-by: Marek Dano <mk.dano@gmail.com>
An A2A agent with auth_type="oauth" stored oauth_config but never used
it. The gateway now gets an agent-level client_credentials token before
it calls the agent.
- Send the RFC 8707 resource on the token request. Use the configured
value, else the origin of the agent endpoint.
- Validate token audience, scopes, and issuer with
validate_oauth_token_claims() before the gateway forwards the token.
Apply the gateway precedence and OAUTH_REQUIRE_CONFIGURED_RESOURCE.
- Cache the token per agent in the service-token cache. The key covers
the resource and the client credentials.
- Add send_resource to get_client_credentials_token_response(). It is
off by default, so existing callers keep their request shape.
- Wire the token into A2AAgentService.invoke_agent and both A2A paths
in ToolService.
- Add Resource (Audience) to the A2A agent create and edit forms. Stop
passing include_resource=False in the A2A admin handlers.
- Document the A2A token lifecycle.
Other grant types fail with an error. The per-user authorization_code
flow is not part of this change.
Closes #5815
Signed-off-by: Marek Dano <mk.dano@gmail.com>
marekdano
requested review from
Lang-Akshay,
brian-hussey,
ja8zyjits and
msureshkumar88
as code owners
November 10, 2026 17:46
The diff-coverage gate reported 89% against the 90% minimum. Add tests
for the changed lines that no test reached.
- Cover the cache hit that happens while a request waits for the token
lock, and the fallback TTL for an invalid expires_in.
- Cover A2AAgentService.invoke_agent for an OAuth agent: the token
becomes the Authorization header, and a token failure becomes an
A2AAgentError.
- Cover the OAuth token lookup in ToolService.invoke_tool and
_call_a2a_agent.
Signed-off-by: Marek Dano <mk.dano@gmail.com>
This branch has not been deployed
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.
Summary
Closes #5815.
An A2A agent with
auth_type="oauth"storedoauth_config, but no code path used it. The gateway now gets an agent-levelclient_credentialstoken before it calls the agent. It validates the token before it forwards it.Changes
mcpgateway/services/a2a_oauth.py.resolve_a2a_oauth_headers()requests the token, validates it, caches it, and returns theAuthorizationheader.resourceon the token request. The value isoauth_config["resource"], else the origin of the agent endpoint (derive_resource_origin()).validate_oauth_token_claims(). A mismatch of a configured audience, scopes, or issuer blocks the call. A mismatch of a derived audience is advisory unlessOAUTH_REQUIRE_CONFIGURED_RESOURCE=true.send_resourcetoOAuthManager.get_client_credentials_token_response(). The default isFalse, so gateway and discovery callers send the same request as before.oauth_headerstoprepare_a2a_invocation(). The gateway applies it only whenauth_type="oauth".A2AAgentService.invoke_agentand both A2A paths inToolService.include_resource=Falsein the two A2A admin handlers.oauth-resource-configuration.md.Behavior
client_credentialsis supported. Any othergrant_typefails with anA2AAgentErrorthat names the grant type.Decisions
authorization_codeflow with token storage and refresh is deferred by design. It needs an Alembic migration and goes in a separate issue.client_credentials.