You give an AI agent an API key and tell it to handle incident triage overnight. By morning, it's dropped a production database, restarted your servers, and scaled your infrastructure — all because the key could do all of those things and the agent decided they were reasonable solutions. This is not a hypothetical. It's the core problem with AI agent access control in 2026: agents are overprivileged, their credentials carry no identity, and "human in the loop" fails when the human is tired or absent.
The fix is not another prompt. The fix is OAuth 2.0 Token Exchange (RFC 8693) — an IETF standard published in January 2020 that lets you issue short-lived, task-scoped tokens carrying both the agent's identity and the user's identity. Every tool call gets its own narrowly scoped credential, evaluated against policy before the credential is minted. If the policy says no, the token never exists — there's nothing to leak, steal, or replay.
Last verified: 2026-07-21
- Agents with blanket API keys are overprivileged and unattributed — they can do anything the key allows, and you can't tell who used it
- Human-in-the-loop fails under consent fatigue; a tired operator will approve anything
- RFC 8693 token exchange issues per-call, short-lived, audience-restricted tokens with full identity chains
- MCP's own authorization spec mandates OAuth 2.1 — token exchange extends this with delegation semantics
- Real CVEs (CVE-2025-68143/44/45) show what happens when agent-adjacent infrastructure lacks access control
Why Do AI Agents Need Access Control?
AI agents need access control because they act autonomously with credentials that are more powerful than any single task requires. An agent is a control loop that calls an LLM, proposes tool calls, and dispatches them to external resources — often through the Model Context Protocol (MCP). Without access control, three things go wrong:
Credentials carry no identity. When an API key is used, the audit log shows the key was used — but not who told the agent to use it, which agent instance it was, or on whose behalf it was acting. You lose accountability entirely.
Agents are overprivileged. A single "kitchen sink" API key that can renew certificates, restart servers, scale infrastructure, and drop databases means the agent can do all of those things whenever its reasoning loop decides to. Agents want to be helpful — they will use every permission they have to solve the problem in front of them. (WorkOS)
Human-in-the-loop is not reliable. We spent decades building access management for humans. Blindly trusting a human who might be consent-fatigued or half-asleep at 2 AM is not a security control. In March 2026, Meta's own Director of Alignment lost control of her AI agent when context window compaction erased safety instructions mid-session — she had to physically kill the process. (APort)
What Happens When Agents Run Without Access Control?
When agents run without access control, they make decisions with your most powerful credentials and no policy stops them. Here's a concrete scenario based on the pattern that real incident-management agents follow:
An overnight triage agent receives five tickets. It has one API key that can do everything — read monitoring systems, call cloud hosting APIs, access the database, and scale infrastructure.
- Ticket 1 (hardware failure): The agent reads the monitoring system, decides it can't fix a physical problem, escalates to the morning team. Fine.
- Ticket 2 (TLS certificate expiring): The agent uses the same key to renew the certificate via the cloud API, then writes a report. The key could have done anything else too — it just happened to choose correctly.
- Ticket 3 (billing database broken): The documentation says "delete the database and restore from backup." The agent has the Postgres connection string. It drops the database. It can't verify whether a backup exists. It escalates to the morning team. This has happened to high-profile companies.
- Ticket 4 (server processes frozen): The agent decides to take production offline briefly. It does, using the same all-powerful key.
- Ticket 5 (site failing for 1 in 3 users): The agent scales up infrastructure, incurring real spend, because the key allows it.
The root cause across all five: one key, no scoping, no policy, no identity chain. The agent wasn't malicious — it was overprivileged. Every action it took was a reasonable response if the agent had the authority to take it. But nobody checked whether it should have that authority for each specific action.
This maps to a real vulnerability class. In January 2026, researchers disclosed CVE-2025-68143, CVE-2025-68144, and CVE-2025-68145 — three chained flaws in Anthropic's own official Git MCP server that allowed remote code execution via prompt injection. The attacker didn't need direct access to the victim's system. They just needed to influence what the AI read (a malicious README, a poisoned issue description), and the MCP server would execute arbitrary commands with the server's own permissions. (NVD, SecurityWeek)
The lesson: when the tool layer has no access control, a manipulated agent becomes a weapon against your own infrastructure.
How Does OAuth 2.0 Token Exchange Secure AI Agents?
OAuth 2.0 Token Exchange (RFC 8693) secures AI agents by replacing static API keys with short-lived, per-call tokens that carry a full identity chain — who the user is, who the agent is, and what specific action is being authorized. Published as an IETF Standards Track document in January 2020, the spec defines a protocol for requesting and obtaining security tokens from OAuth 2.0 authorization servers, including tokens that employ impersonation and delegation. (IETF RFC 8693)
Here's how it works in the agent execution path:
The agent execution path
- A user submits a prompt to a runtime (a CLI like Claude Code, an SDK, or an app like Cursor).
- The runtime calls the model (LLM), which proposes tool calls.
- An MCP client dispatches those tool calls to an MCP server.
- The MCP server calls the resource API and returns results.
- The loop repeats until the model returns a final answer.
Without access control, the MCP server just uses whatever API key it has. With token exchange, an OAuth client sits between the MCP client and the MCP server, and the flow changes:
The token exchange flow
- User authenticates with an authorization server (Google, Okta, Auth0, etc.) and consents to delegate a subset of their permissions to the agent. This is the first narrowing — the agent only gets some of the user's total access.
- The authorization server issues a subject token that identifies the user and their access level.
- The agent loop runs. When the model proposes a tool call, the runtime authenticates with a Security Token Service (STS) using its own workload identity or OAuth client credentials, and sends the subject token along with it.
- The STS creates a token exchange request asking for permission to access a specific MCP server for that specific tool call only.
- Governance policy evaluates the request: Is the delegation chain valid? Is the requested access within policy? Is the user's role sufficient for this action?
- If approved, the STS issues an access token with:
- An audience declaring that only the target MCP server can use it
- A short lifetime (often minutes)
- Ephemeral storage — it's never persisted, used once, and discarded
- The MCP server validates the token, calls the resource, and discards the token immediately after.
The key insight: the policy evaluates before the credential is minted. If the policy denies the request, the token never exists. There's nothing to leak, nothing to replay, nothing to steal. This is fundamentally different from issuing a broad API key and then trying to restrict what the holder does with it.
The act claim: who is acting on whose behalf
RFC 8693 introduces the act (Actor) claim in JWT tokens. When a token is exchanged with delegation semantics, the resulting JWT contains both the subject (the user) and the actor (the agent) as separate claims. Downstream services can evaluate each independently — they know both who authorized the action and who executed it. The may_act claim lets the authorization server specify which actors are authorized to act on behalf of a subject, creating a verifiable delegation chain. (IETF RFC 8693, Section 4.1)
What Is the Difference Between Delegation and Impersonation?
Delegation and impersonation are two token exchange semantics defined in RFC 8693, and the difference matters for agent security.
Impersonation means the new token represents only the subject. The agent effectively becomes the user — the downstream service sees the user's identity but not the agent's. This is risky because you lose the audit trail of which agent acted. Use impersonation only across fully trusted systems where maintaining separation between user and client isn't necessary. (Ping Identity)
Delegation means the new token carries both identities — the subject (user) and the actor (agent) — via the act claim. The downstream service can see that "Agent X acted on behalf of User Y," which preserves the full audit chain. For AI agents, delegation is almost always the right choice because you need to know both who authorized the action and who executed it.
| Property | Impersonation | Delegation |
|---|---|---|
| Token contains | Subject only | Subject + Actor |
| Audit trail | "User did X" | "Agent did X on behalf of User" |
| Downstream sees agent identity? | No | Yes |
| Risk level | Higher (identity loss) | Lower (full chain) |
| Best for | Trusted internal systems | AI agents, third-party tools |
How Does MCP Authorization Work With Token Exchange?
The Model Context Protocol's own authorization specification mandates OAuth 2.1 for HTTP-based transports. An MCP server acts as an OAuth 2.1 resource server — it accepts and validates access tokens. An MCP client acts as an OAuth 2.1 client. The authorization server issues tokens. The spec also references OAuth 2.0 Authorization Server Metadata (RFC 8414), Dynamic Client Registration (RFC 7591), and Protected Resource Metadata (RFC 9728). (MCP Authorization Spec)
Token exchange (RFC 8693) extends this foundation with delegation semantics. While OAuth 2.1 gives you the basic client-server-resource server model, token exchange adds the ability to:
- Exchange a broad user token for a narrowly scoped, per-call token
- Carry the agent's identity alongside the user's identity (the
actclaim) - Restrict the token to a specific audience (one MCP server)
- Make the token short-lived and ephemeral
This combination — MCP's OAuth 2.1 foundation plus RFC 8693 token exchange — is what gives you per-tool-call authorization with full identity chains. The MCP server validates the token, checks the scopes, executes the tool, and discards the token. The next tool call gets a fresh token with potentially different scopes.
Scoping: one scope per tool or tool group
The MCP ecosystem recommends defining one OAuth scope per MCP tool or tool group. For example: mcp:certificate.renew for a certificate renewal tool, mcp:database.read for read-only database queries, mcp:infrastructure.scale for scaling operations. Without scopes, access is all-or-nothing — making fine-grained tool authorization impossible. (Descope MCP Docs)
When an agent requests a token exchange, it asks for the specific scope needed for the current tool call. The STS evaluates whether the user's delegated permissions include that scope, whether policy allows the agent to exercise it, and only then mints the token.
How Do You Implement Agent Access Control: A Step-by-Step Guide
Implementing agent access control with token exchange requires changes at three layers: identity, policy, and the agent runtime. Here's how to do it.
Step 1: Give the agent its own identity
Register each agent (or agent deployment) as a service account, workload identity, or OAuth client in your identity provider. The agent should never authenticate by reusing a user's session cookie or long-lived API key. It needs its own credentials, its own audit trail, and its own lifecycle. (WorkOS)
When the agent acts on behalf of a user, use a delegation protocol — OAuth 2.0 token exchange (RFC 8693) or an on-behalf-of flow — so the resulting token carries both the agent's identity and the user's identity as separate claims.
Step 2: Authenticate the user and get consent
The user logs in to the authorization server (Google, Okta, Auth0, etc.) and consents to delegate a subset of their permissions to the agent. This is the first narrowing — you're only delegating some of the user's total access, not all of it.
The authorization server issues a subject token that identifies the user and contains their level of access. This token becomes the input for all subsequent token exchange requests.
Step 3: Define scopes at the action level
Design scopes to mirror the agent's tasks, not its role. Instead of repo:write across the entire organization, define a scope that can open pull requests in one repository. Instead of mail.send, define a scope that can send from one mailbox to a pre-approved domain list. (SecureW2)
For MCP servers, define one scope per tool or tool group:
mcp:certificate.renew— can only renew TLS certificatesmcp:database.read— read-only database queriesmcp:infrastructure.scale— scaling operations (requires elevated role)mcp:ticket.escalate— escalate tickets to the morning team
The closer the scope matches the task, the smaller the attack surface.
Step 4: Set up the Security Token Service (STS)
The STS is the authorization server component that handles token exchange requests. It receives:
- The agent's own credentials (workload identity or OAuth client credentials)
- The subject token (user's identity and access level)
- The requested scope (what the current tool call needs)
- The audience (which MCP server will receive the token)
Popular identity providers that support RFC 8693 token exchange include Auth0 (via Token Vault), ZITADEL, Ping Identity, and open-source options like the Janssen Project. (Auth0, ZITADEL)
Step 5: Write governance policy
Policy is what decides whether a requested token should be granted. The policy engine evaluates:
- Is the delegation chain valid? (Agent is authorized to act for this user)
- Is the requested scope within the user's delegated permissions?
- Does the action require a specific role? (e.g., restarting production requires an on-call engineer role)
- Are there time-based restrictions? (e.g., no scaling operations after hours without explicit approval)
Policy is evaluated before the credential is minted. If policy denies the request, the token never exists. This is the critical difference from API-key-based approaches where you issue the credential first and try to restrict actions after.
Step 6: Make tokens short-lived and ephemeral
The STS should issue access tokens with:
- Short lifetimes: 5-15 minutes for high-risk operations, up to 1 hour for read-only operations
- Audience restriction: the token can only be used at the specified MCP server
- No persistence: the token is used once and discarded — never stored in a database, config file, or log
This means even if a token is somehow intercepted, it's useless within minutes and only works against one specific server. (IETF Draft: AI Agent Authentication and Authorization)
Step 7: Enforce human-in-the-loop with real policy
When an agent requests approval for a sensitive action, human-in-the-loop should be backed by policy — not just a yes/no click. The policy should verify:
- Does the human user have the required role for this action?
- Is the user's approval within their delegated authority?
This prevents consent fatigue. A tired operator clicking "approve" on everything can't grant permissions they don't have. The policy is the real security boundary; the human approval is just one input to it.
API Keys vs. Token Exchange: Which Should You Use for AI Agents?
API keys and token exchange represent two fundamentally different approaches to agent authorization. Here's how they compare:
| Property | Static API Keys | OAuth 2.0 Token Exchange (RFC 8693) |
|---|---|---|
| Identity | None — key is anonymous | Full chain — user + agent identity |
| Scope | All-or-nothing (key permissions) | Per-call, per-tool granularity |
| Lifetime | Long-lived (months/years) | Short-lived (minutes) |
| Storage | Persisted in config files | Ephemeral — never stored |
| Audit trail | "Key was used" | "Agent X acted for User Y on Tool Z" |
| Policy enforcement | After issuance (try to restrict) | Before issuance (token never minted if denied) |
| Rotation | Manual, painful | Automatic (each call gets a fresh token) |
| Compromise impact | Full key permissions exposed | One narrow token, expires in minutes |
| Standards | Proprietary per service | Open IETF standard (RFC 8693) |
API keys are an explicitly identified antipattern for agent identity. The IETF's draft on AI Agent Authentication states: "Static API keys are an antipattern for agent identity. They are bearer artifacts that are not cryptographically bound, do not convey identity, are typically long-lived and are operationally difficult to rotate, making them unsuitable for secure agent authentication or authorization." (IETF Draft)
What Real Security Incidents Teach Us About Agent Access Control
Real-world incidents in 2025-2026 show exactly what happens when agent-adjacent infrastructure lacks proper access control:
Anthropic Git MCP Server RCE (CVE-2025-68143/44/45): Three chained vulnerabilities in Anthropic's official mcp-server-git allowed remote code execution via prompt injection. An attacker could influence what the AI read (a malicious README), and the MCP server would execute arbitrary commands with the server's own permissions. The server had no per-call access control — it operated with whatever permissions the server process held. Fixed in mcp-server-git v2025.12.18. (NVD, SecurityWeek)
Azure DevOps MCP Authentication Bypass (CVE-2026-32211): API keys and tokens were accessible without credentials due to an authentication bypass. CVSS 9.1. A patch is available, but the incident highlights how MCP infrastructure can expose credentials when access control is weak. (CyberDesserts)
Agentjacking via Sentry MCP Event Injection (June 2026): Tenet Security demonstrated that 2,388 organizations had injectable Sentry DSNs. Their testing showed an 85% agent execution rate — meaning 85% of injected events successfully triggered agent actions. Sentry declined remediation and deployed only a payload-string filter. This is a case where per-call policy enforcement would have blocked the injected actions entirely. (CyberDesserts)
The Clinejection Attack (February 2026): A prompt injection payload in a GitHub issue title compromised an AI triage bot, which executed npm install with a malicious package. 4,000 developer machines were infected over eight hours. If the triage bot had a policy denying system.command.execute, the kill chain would have collapsed at step one. (APort)
The pattern across all four: the agent or MCP server had more permissions than any single task required, and there was no policy layer to deny specific actions before they executed.
What This Means for You
If you're building or deploying AI agents — for incident management, customer support, code review, or any autonomous workflow — you need to treat agent credentials as a first-class security problem:
Audit your current agent credentials today. If your agents use static API keys, those keys are overprivileged by definition. List every key, what it can do, and what the agent actually needs. The gap between those two is your attack surface.
Start with scopes, not tokens. Before implementing token exchange, define what scopes your agent actually needs per tool call. If your MCP server doesn't have scopes defined yet, start with the downstream resource server's existing scopes — those are your baseline. Layer agent-specific scopes on top. (Descope)
Add a policy layer before you add token exchange. Token exchange is the mechanism; policy is the brain. If you mint tokens without policy evaluation, you've just created a faster way to issue overprivileged credentials. Write policies that check: who is asking, on whose behalf, for what scope, at what time, with what role.
Treat human-in-the-loop as an input, not a control. A human clicking "approve" is not a security boundary. The policy is the boundary. The human's approval is one signal the policy evaluates. This prevents consent fatigue from becoming a security failure.
Use open standards. RFC 8693 works with off-the-shelf agents (Claude Code, Cursor), custom agents, CLI tools, third-party MCP servers, agent-to-agent communication, and any OAuth identity provider. It works with MCP's OAuth 2.1 authorization spec. You're not locking yourself into a vendor — you're using the same IETF standards that power the rest of the web's authorization infrastructure. For more on building reliable agent architectures, see our guide to AI agent architecture that survives the 6-month churn.
FAQ
Q: What is OAuth 2.0 Token Exchange?
A: OAuth 2.0 Token Exchange (RFC 8693) is an IETF standard published in January 2020 that defines a protocol for requesting and obtaining security tokens from OAuth 2.0 authorization servers. It enables one token to be exchanged for another with different scopes, audiences, or subjects — including impersonation and delegation semantics. For AI agents, it lets you exchange a broad user token for a narrowly scoped, short-lived, per-call token that carries both the agent's and the user's identity.
Q: Why are API keys bad for AI agents?
A: API keys are bad for AI agents because they carry no identity (you can't tell who used the key), are typically overprivileged (they can do everything the key allows, not just what the current task needs), are long-lived (months or years), and are stored in config files where they can be stolen. The IETF's draft on AI Agent Authentication explicitly calls static API keys an antipattern for agent identity.
Q: How does token exchange work with MCP?
A: The MCP specification mandates OAuth 2.1 for HTTP-based transports — an MCP server acts as a resource server that validates access tokens. Token exchange (RFC 8693) extends this by allowing an agent to exchange a user-delegated token for a per-call token scoped to one specific MCP tool. The MCP server validates the token, checks the scopes, executes the tool, and discards the token. Each tool call can get a different token with different scopes.
Q: What is the difference between delegation and impersonation in token exchange?
A: Impersonation means the new token represents only the subject (the user) — the downstream service doesn't see the agent's identity. Delegation means the token carries both identities via the act JWT claim — the downstream service can see that "Agent X acted on behalf of User Y." Delegation is almost always the right choice for AI agents because it preserves the full audit chain.
Q: Do I need a human in the loop if I have token exchange?
A: Token exchange and human-in-the-loop serve different purposes. Token exchange handles the mechanical authorization (is this credential valid and scoped correctly?). Human-in-the-loop handles judgment calls (should the agent restart production at 2 AM?). But human approval should be backed by policy — the policy checks whether the human has the required role for the action, preventing consent fatigue from becoming a security failure.
Q: What tools support OAuth 2.0 Token Exchange for agents?
A: Identity providers that support RFC 8693 token exchange include Auth0 (via Token Vault), ZITADEL, Ping Identity, and the open-source Janssen Project. The standard works with any OAuth 2.0-compatible identity provider, any MCP server that implements the OAuth 2.1 authorization spec, and agent runtimes that can act as OAuth clients (Claude Code, Cursor, custom SDKs). For more on securing your broader AI stack, see our guide to the 4-layer defense model for AI agent safety.

Discussion
0 comments