Agent IAM Is Not Service IAM: Why OAuth Breaks When Intent Is Constructed at Runtime
The bearer token model has one assumption that agents quietly violate: the caller knows what they want when they ask. OAuth scopes, IAM roles, and API keys are all designed around a principal whose intent is fixed before authentication begins. Your CI runner has stable intent. Your microservice has stable intent. An agent does not. An agent's intent is assembled at request time out of a user prompt, a system prompt, retrieved documents, and the outputs of tools that may themselves have been written by an attacker. By the time the agent reaches for a token, the policy decision that the IAM layer has to make has already been made — by inputs the IAM layer never saw.
This is why the same auth pattern that has worked for fifteen years of service-to-service traffic is now producing a class of incidents nobody has good language for. A prompt injection lifts a long-lived bearer token. An agent "remembers" a permission across sessions because the token outlived the user's intent. A multi-step task that legitimately needs three scopes holds all of them for the entire session instead of acquiring and releasing them per step. None of these are OAuth bugs in the strict sense. They are consequences of stretching a model that assumes static intent to cover a caller whose intent is reconstructed every turn.
The argument of this post is narrow: agent IAM is a different problem than service IAM, and treating it as the same problem is what produces the incidents. The shape of the fix is not "OAuth, but careful." It is intent-bound scopes that expire when the task ends rather than when a token TTL fires, delegation chains that record which prompt asked for which tool call, capability tokens that name the user-visible task they were minted for, and a policy layer that distinguishes user-typed instructions from instructions that arrived through a retrieved document. The OAuth model is a reasonable substrate. It is not a complete answer.
The static-intent assumption that everything else inherits
Walk through what an OAuth access token actually represents. A user clicked a consent screen, authorized a client to act on their behalf for a fixed list of scopes, and the authorization server minted a token with a TTL. The client then waves that token at resource servers. The resource server checks the signature, the audience, the expiry, and the scopes. If all four pass, the call goes through. The implicit contract is that whoever obtained the token agreed to use it for the purpose the user consented to, and the resource server trusts that the scopes are a reasonable proxy for that purpose.
For traditional clients this works because the client's intent is static. A backup tool that has drive.readonly will use it to read drive files. An invoice service with payments:create will use it to create payments. The mapping from "scope on the token" to "thing the client will do" is one-to-one and known in advance to the developer who configured the OAuth flow.
For agents, the mapping is one-to-many and decided at runtime. An agent with drive.readonly may use that scope to summarize a doc the user pasted, to enumerate every shared drive looking for a string, or — under prompt injection — to leak the contents of files the user never asked about into a tool call against an attacker-controlled endpoint. The scope is necessary but no longer sufficient. The token says "this principal may read drive content." It does not say "for this task, on this user's behalf, only against the file the user named, and only until this turn ends." All of those constraints are alive in the user's head. None of them are in the token.
The first lesson is that scopes are too coarse to express agent intent. The second is that token TTLs are tied to the wrong clock. A 60-minute access token outlives most agent tasks by an order of magnitude, and the window between "task complete" and "token still valid" is exactly the window in which a hijacked agent can do unintended work with the user's authority.
What goes wrong: three failure modes that recur
The first failure mode is the scope-collapse hijack. A team gives an agent a token with broad scopes — drive.read, gmail.send, calendar.write — because that's the floor at which the agent's planner has enough surface to choose tools. Then a prompt injection arrives, often through a retrieved document or a tool result, and instructs the agent to perform a task that uses all three scopes in a way the user never asked for. From the resource server's view, every call is fully authorized. From the user's view, the agent did the wrong thing. There is no IAM signal that distinguishes the two cases, because the IAM layer doesn't know which prompt produced which tool call. The audit log answers "who called the API" perfectly, and "why did the agent do that" not at all.
The second failure mode is the persistent permission. The agent acquires a token, completes a task, and the token sits in the agent's session memory for the rest of the conversation. A later turn — maybe a different task, maybe a follow-up that goes off the rails — picks up the same token and uses it. The user never re-consented. The token's TTL hasn't expired. The IAM layer has no notion of "the task ended," so the permission outlives the intent that justified it. The fix in service IAM is a shorter TTL, but a shorter TTL just shifts the problem; the right boundary isn't a wall-clock interval, it's the lifetime of the user-named task.
The third failure mode is the session-scope token over a per-step task. The agent's planner sketches a multi-step plan that legitimately needs three scopes — say, read a file, transform it, post results. Instead of acquiring each scope at the moment it's needed and releasing it after, the agent holds all three for the entire session. Step 2's compromise gets to use step 3's scope. The principle of least privilege has a temporal axis that service IAM rarely exercises and that agents make load-bearing.
All three failure modes share a structure. The IAM layer makes a single decision — "is this token valid for this scope?" — and an agent's behavior turns that single decision into an open-ended license to act. The model that assumed static intent is being asked to govern a caller whose intent is being assembled, contested, and rewritten across the call boundary it controls.
Intent-bound scopes: tying authorization to the task, not the clock
The first piece of the fix is intent-bound scopes. The idea is to mint authorization that names the user-visible task it was issued for, and to make that authorization expire when the task ends rather than when an arbitrary TTL fires. Several emerging standards push in this direction — the OpenID Foundation's agentic identity work, the IETF's draft intent-token primitive, and a wave of vendor capability-token schemes — but the engineering pattern is recognizable independent of the spec.
Concretely: when the user types "summarize this PDF and email a one-paragraph summary to my team," the agent's authorization request to the IAM layer should not be "give me drive.read and gmail.send for the next hour." It should be "give me a capability that lets me read the document at this specific URL, and a capability that lets me send a single email with this subject line to this specific recipient list, both expiring when the task either completes or fails." The capability token is bound to the task's intent, not to the agent's session.
That changes the audit story too. The token itself records the user-named purpose, which means the audit log can finally answer "why" — not just "an agent with token X called endpoint Y" but "an agent acting on the user-stated task 'summarize this PDF and email it to the team' called endpoint Y." A prompt injection that diverts the agent into a different action shows up as a tool call without an intent-binding that covers it, instead of a tool call that looks like every other authorized call.
The harder design question is who is allowed to mint these capabilities and how the agent obtains them. The cleanest pattern is a token-exchange step where the agent presents its session token plus the user-stated task description and receives a narrower capability token. The minting service is a policy enforcement point that sits outside the LLM, which means the LLM cannot prompt-inject its way past it; the model can ask for a capability, but it cannot forge one.
Delegation chains that record which prompt asked
The second piece is making the delegation chain explicit. In service IAM, the chain is usually shallow: a user authorizes a client, the client calls the service. With agents, every tool call is a hop in a chain that begins with the user's prompt, passes through the model's interpretation, and may chain through several agents and MCP servers before reaching the final resource. The audit log needs to reconstruct the chain. The policy layer needs to evaluate the chain.
The pattern that's converging is structured delegation, where each hop in the chain produces a token that names its parent, the action it authorizes, and the context it was issued for. Each child token must be a strict attenuation of its parent — narrower scope, sooner expiry, smaller budget — and the resource server validates the entire chain on every call, not just the leaf token. A token that attempts to widen a scope, increase a budget, or extend an expiry fails cryptographic verification.
The audit value is enormous. When an investigator asks "why did this email get sent," the chain answers in concrete terms: the user said this, the planner decomposed it into these subtasks, this subtask was delegated to this sub-agent, which acquired this capability, which authorized this tool call. The chain also makes it tractable to ask harder questions, like "did any tool call in this trace originate from a retrieved document rather than a user prompt?" — which is exactly the question a confused-deputy-style prompt injection forces you to answer, and which a flat audit log cannot answer at all.
Distinguishing user-typed intent from document-supplied intent
The third piece is the policy distinction that has no analog in service IAM: the difference between "the user typed a sentence that expanded into this tool call" and "a retrieved document instructed the agent to call this tool." Service IAM has nothing to say about the provenance of an instruction because services don't have instructions in the IAM-relevant sense; their behavior is fixed in code. Agents do, and the source of an instruction is one of the most security-relevant pieces of metadata that exists about a tool call.
Building this in practice requires the agent runtime to label every input by its trust tier — user prompts at the top, system prompts second, retrieved documents and tool outputs at the bottom — and to propagate those labels into the policy decision when authorization is requested. A capability that requires user-tier intent cannot be acquired by an agent whose currently active instruction came from a document-tier source. This is the same idea behind classic taint tracking in language runtimes, applied to the new substrate of natural-language instructions, and it is the only known structural defense against the indirect prompt injection that today's MCP integrations make trivial.
The realistic version of this is not perfect. Agents that re-summarize their own context can launder taint, and a sufficiently determined attacker can socially engineer a user into re-uttering the malicious instruction so it crosses the boundary. The point of the boundary isn't to be unbreakable; it's to make the IAM layer aware that there's a distinction worth defending, in the same way that user-input vs. trusted-input is a distinction the web platform learned to defend after years of XSS pain.
The architectural realization
The summary is short. OAuth, IAM roles, and API keys were designed around a caller who decides their intent before they ask for a token. An agent constructs its intent mid-request, from inputs the IAM layer never sees, and the layer that grants permissions has been quietly making decisions on the basis of a model of intent that no longer matches reality. The fix isn't to throw OAuth out — the cryptographic substrate, the discovery mechanisms, and the resource-server pattern are all still useful. The fix is to add the layer above it that the agent era requires: intent-bound scopes that expire with the task, delegation chains that record provenance, capability tokens that name the user-visible purpose, and a policy layer that knows which inputs are allowed to ask for what.
Teams that get this wrong will write incident reports that all sound the same. A token did exactly what it was authorized to do, and the work it did was not what the user asked for. The IAM layer will report green. The behavior will be wrong. That gap — between "authorized" and "intended" — is the new perimeter, and it is where the next decade of agent security work is going to live.
- https://aembit.io/blog/iam-agentic-ai/
- https://www.resilientcyber.io/p/identity-is-the-agentic-ai-problem
- https://openid.net/wp-content/uploads/2025/10/Identity-Management-for-Agentic-AI.pdf
- https://levine.tech/blog/oauth-is-broken
- https://zylos.ai/research/2026-04-11-agent-authentication-delegated-access-oauth-scoped-tokens
- https://supertokens.com/blog/auth-for-ai-agents
- https://datatracker.ietf.org/doc/rfc9700/
- https://www.scalekit.com/blog/delegated-agent-access
- https://www.thefai.org/posts/human-anchored-intent-bound-delegation-for-ai-agents
- https://datatracker.ietf.org/doc/draft-williams-intent-token/
- https://www.okta.com/blog/ai/agent-security-delegation-chain/
- https://arxiv.org/html/2509.13597v1
- https://unit42.paloaltonetworks.com/model-context-protocol-attack-vectors/
- https://simonwillison.net/2025/Apr/9/mcp-prompt-injection/
- https://www.practical-devsecops.com/mcp-security-vulnerabilities/
- https://blog.gitguardian.com/ai-agents-authentication-how-autonomous-systems-prove-identity/
