Configuring A2A OAuth User Delegation
In this blog post, we’ll walk through an OAuth 2.0 token exchange and delegation to an A2A Agent. We will focus on configuring the A2A Agent Card, implementing the agent in Python, and validating the OAuth credentials. At the end of this walk through, we’ll have an A2A enabled agent that has a user’s delegated/downscoped intended for specific skills of the agent. This token can be further exchanged to operate as the user including calling out to MCP tools. Source code for this demo is on my GitHub. Digging into MCP Authorization is the next blog. Let’s dig in.
This is part of a much larger showcase of MCP / Agent2Agent identity, delegation, and authorization I’m working on. Please follow (@christianposta or /in/ceposta) along if interested.
Setting up the A2A Agent
For this example, we are using FastAPI and the FastAPI support in A2A’s python SDK.
Here we see a basic request_hanlder for the HTTP side of things (see source code) and we pass in an . Let’s dig into what that is.
What is the AgentCard?
The AgentCard is how the agent advertises its capabilities, identity, and requirements to the outside world. Think of it as a self-describing contract. It includes metadata like the agent’s name, version, capabilities, and expected input/output modes—but more importantly, it describes the security expectations.
For clients to call this agent securely, they need to know what kind of token to send and what scopes it must contain. The AgentCard defines that precisely, so downstream tools like delegation frameworks and identity brokers can dynamically determine what kind of delegation or token exchange is needed.
Configuring Security in the AgentCard
Here’s what that looks like in code:
The section defines how the client can authenticate. In this case, the agent expects an HTTP Bearer token in JWT format. You could imagine this being issued by a system like Keycloak, Auth0, or a custom OIDC broker.
Then the field outlines what that token must authorize. In our case, the agent requires a scope of . This gives us a nice clean contract: the agent declares what it needs, and the identity broker ensures the delegated token includes only that.
This mechanism also makes it possible to generate agent-specific tokens that follow the principle of least privilege—crucial in agentic systems where you don’t want an agent with excessive access rights.
Adding Middleware to Enforce Authentication
With FastAPI, one way to add JWT bearer token checking is through Middleware. We can add rules to exclude auth checking for the AgentCard and properly handle scenarios when the correct Bearer token is not present. If a token is found, then we need to validate it.
This middleware intercepts every HTTP request and applies authentication logic to the A2A endpoints.
Bypasses Auth for Safe Routes: The first check allows unauthenticated access to /docs, /openapi.json, and /favicon.ico. These are common public endpoints that don’t need protection.
Handles A2A Paths: We only enforce authentication for requests targeting /a2a/*, which is the context path for A2A agent interactions.
AgentCard is Public: The agent’s discovery endpoint (/a2a/.well-known/agent.json) is intentionally left unauthenticated—this allows clients to fetch the AgentCard before obtaining or exchanging a token.
Bearer Token Required: All other A2A requests must include a valid Authorization header. If it’s missing or incorrectly formatted, the middleware returns a 401 Unauthorized.
Token Validation: If a properly formatted token is found, the middleware verifies it (via verify_token) and attaches the decoded result to . This makes the user’s identity and scopes available downstream to the route handler.
This pattern ensures your agent safely accepts only scoped, valid JWTs—paving the way for delegated, auditable agent behavior.
But What Kind of OAuth Token Should This Be?
When sending OAuth access tokens to Agents, we need to be very careful. When a user logs in and authorizes a set of permissions to an OAuth client and then proceeds to instruct agents to work on behalf of the user, you will want to limit and be selective of what permissions go to which agents, based on skills.
Why? Because agents that act on behalf of a user can invoke tools, perform actions, and chain calls to other agents or services as the user. If you hand upstream agents a token with broad scopes, that’s a recipe for agentic misalignment.
Instead, we follow a delegation flow using OAuth 2.0 Token Exchange. You take a user’s broad-scope access token and exchange it for a narrow, fine-grained, downscoped token for a specific agent (audience) and use case.
For example, here’s what a downscoped token might look like:
This token is only valid for a specific agent () and only includes the permission. If the agent tries to do anything else on behalf of the user, ie, call another API, escalate access, etc it shouldn’t work.
This is how we align security posture with agent capability. By narrowing the delegation at the token level, we can safely compose powerful agentic workflows without introducing risk.
Putting It All Together
Once the agent receives this token, it can proceed to call MCP servers or APIs using the delegated authority. If it needs to further act on behalf of the user, it can perform another token exchange or pass that identity downstream, within the bounds of the original delegation.
This opens the door to safe, auditable chained agent execution, critical for enterprise use cases where human oversight, traceability, and tight auth boundaries are essential.
See the full demo here.
IAM Specialist | | Passionate About Advancing IAM Through AI
2wOne of the best read for me in terms of A2A protocol .. Would like to explore myself .. Thansk
AI Platform Engineer | Open-Source Innovator | GitOps | LLMOps | RAGOps | Driving Reliable, Cost-Effective Solutions with Domain-Driven Design
2wGreat article. I like the fact that you are using OIDC as a standard security protocol, allowing more IdP’s to be integrated. Inference Gateway is leveraging the same techniques, building using open standards is a smart approach.
IT Engineer | CISSP | CCSP | CEH (Master): research | learn | do | MENTOR
2wChristian Posta the Agentic systems are envisioned as dynamic. They shall optimize costs efficiency, security... Users, but also Agents (this is A2A protocol) dynamically discover agent cards, replace agents in time. So, the user doesn't know in advance what scopes the downstream agents need now or in the future. For example, in the CURRENT agent chain call A1 - > A2 -> A3, the user will know about A1 only. The user is unaware about the rest of the downstream agents. Agent scopes, from security perspective shall be namespaced, so downscoping the token and passing the same scope downstream, while technically possible, is not the best possible choice. The main problem is the user consent. The user consented the A1 agent, not A2. Someone can say consenting A1 also includes unconditional delegation of the same scope to downstream agents. But it is not right approach. That's why Microsoft's "On User Behalf" flow (token exchange) relies on user pre-approved consents for anything POSSIBLE included in the request flow. And this right approach is not suitable for dynamic Agentic topology. Solution? CIBA and stateful async flows. Problems: User consenting fatigue.