Most AI agents today are authorised with static OAuth scopes granted once at connection time, which tells a resource what kind of thing the agent may do but nothing about which task it is doing right now. Intent-based authorisation adds that missing piece: each action is checked against a declared task, with its specific resource, parameters and limits, before a narrow credential is issued or a call is allowed. The idea is attractive, but it introduces a new attack surface, because an agent that can be steered by injected content can also be steered into declaring a malicious intent. This guide compares the two models in depth: what each is architecturally, the threat model of each, controls, failure modes, decision criteria and a worked scenario. It is for IAM architects, platform engineers and agent builders. For the wider principles of agent authorisation see the AI Agent Authorisation Guide; this page goes deeper on the scope versus intent choice.
Key takeaways
- Scopes answer "what kind", intent answers "this one". A scope such as files:write covers every file the user can write; an intent-based grant covers one file, one action and one purpose, for one task.
- Intent is only as trustworthy as its source. If the model writes its own intent from content it has read, prompt injection writes it too; anchor intent in something the user or a system of record authenticated.
- Static scopes are not wrong, they are coarse. They suit low-risk, read-only and high-volume work where a task-level decision adds latency and little protection.
- Enforcement must sit outside the model. Both models rely on a resource server, gateway or policy decision point that the agent cannot talk its way past, which OWASP calls complete mediation.
- The practical answer is layered. Narrow static scopes set the ceiling, task-bound tokens and per-action policy decide within it, and human approval covers the irreversible tail.
The short answer
Use static scopes alone for agents whose tools are read-only or low impact, whose actions are easily reversed, and whose resource set is already small. Add intent-based authorisation when an agent writes, pays, deletes, shares or reaches data across many customers or tenants, when a single scope would cover far more than any one task needs, or when auditors need to see why an action was allowed, not just that the token permitted it. In most enterprise deployments the right design keeps scopes as a hard ceiling and makes intent the per-task decision inside that ceiling.
What each model is, in architectural terms
Static scopes
The agent, as an OAuth client, requests scopes such as calendar.read or tickets:write. The user or an administrator consents once, and the authorisation server issues access and refresh tokens carrying those scopes. Each resource server checks that the token's scope covers the endpoint. Nothing in the token says which task the agent is performing, so every call the scope covers is allowed for the token's lifetime. The Model Context Protocol authorization specification (version 2025-11-25) shows the pattern clearly: servers advertise scopes_supported and may name required scopes in a WWW-Authenticate challenge, and when no scope is named, the client's fallback is to request all scopes in scopes_supported. The specification intends that list to be the minimal set, with more requested later through step-up, but in practice the fallback makes the first grant as broad as the server's list.
Intent-based authorisation
There is no single standard called intent-based authorisation; it is a design pattern assembled from standards. The agent, or the orchestrator acting for it, states a task: "refund order 18842 for up to 40 euros on behalf of customer C, for ticket T". That intent is checked by a policy decision point (PDP) and expressed in a narrow credential or a per-call decision:
- Rich Authorization Requests: RFC 9396 notes that
scopesuits coarse requests and definesauthorization_details, a JSON array whose objects carry a requiredtypeand optionallocations,actions,datatypes,identifierandprivileges. Granted details are returned in the token response and can appear as a top-level JWT claim or in introspection, so the resource can enforce them. See the OAuth Rich Authorization Requests (RAR) Guide. - Per-task tokens: RFC 8693 token exchange lets the orchestrator trade a broader token for one with narrower
scope, a specificresourceoraudience, and anactclaim naming the agent, and its security considerations recommend short lifetimes. See the OAuth Token Exchange and Delegation Guide. - Per-action policy decisions: the OpenID AuthZEN Authorization API 1.0, published as Final on 11 January 2026, standardises a request of
subject,action,resourceandcontextto a PDP, with a boolean decision. The task reference, amount limit and delegating user travel incontext. See the OpenID AuthZEN Authorization API Guide.
Side-by-side comparison
| Dimension | Static scopes | Intent-based authorisation |
|---|---|---|
| Unit of permission | A category of operation on a resource type | A specific action on a specific resource for a stated task |
| When decided | Once, at consent or client registration | Per task at token issuance, and often per action |
| Token lifetime | Access token minutes to hours; refresh token often long-lived | Minutes, or a single use, bound to the task |
| What a stolen token allows | Everything the scope covers until revoked | The remaining part of one task |
| Main threat | Over-grant: the agent can do far more than any task needs | Intent spoofing: the agent is steered into declaring a harmful task |
| Standards | OAuth 2.x scopes, RFC 8707 resource indicators | RFC 9396, RFC 8693, AuthZEN 1.0, plus a policy language |
| Audit answer | "The token had tickets:write" | "Task T for customer C permitted refund of order 18842 up to 40 euros" |
| Latency and cost | Lowest: local token check | Higher: token exchange or PDP call per task or action |
| Build effort | Supported by every OAuth stack | Needs a PDP, policy authoring, task identifiers and resource support |
| Fits | Read-only, low-impact, high-volume tools | Writes, payments, deletions, sharing, cross-tenant data |
Threat model: static scopes
- Scope over-grant: OWASP LLM06:2025 Excessive Agency names excessive functionality, permissions and autonomy as root causes. A scope is designed for the broadest legitimate use of an API, so an agent that summarises one document often holds rights to rewrite all of them. See the OWASP LLM Top 10 LLM06 Excessive Agency Guide.
- Prompt injection uses every right the token has: indirect prompt injection (ATT&CK T1698, ATLAS AML.T0051) turns content the agent reads into instructions, and the agent then invokes tools (AML.T0053 AI Agent Tool Invocation) with whatever its token allows. With static scopes the blast radius is the full scope.
- Long-lived refresh tokens: a consent granted months ago keeps working long after the task that justified it. The Salesloft Drift breach shows the pattern for integrations: stolen OAuth tokens with broad, standing grants let an attacker bulk-export CRM data across many organisations.
- Confused deputy: an agent serving several users with one broad token can be tricked into acting on data the requesting user should not reach. See the Confused Deputy in AI Agents Guide.
Controls that make scopes safer: split APIs into fine scopes (read separate from write, per resource family); request the scope named in the server's challenge rather than everything in scopes_supported; use RFC 8707 resource indicators, which the MCP specification makes mandatory for clients, so tokens are audience-bound; validate audience on every server and never pass tokens through; issue short access tokens and rotate refresh tokens; run the agent in the delegating user's context, which OWASP LLM06 recommends, so its rights never exceed the user's.
Threat model: intent-based authorisation
- Intent spoofing via injection: if the model composes the intent from a web page, email or tool output, an attacker who controls that content controls the intent. A policy engine will faithfully approve a perfectly formed, malicious task.
- Intent drift: the declared task says "refund order 18842" but the call parameters say order 18843 or 400 euros. If the resource checks only that a task token exists, not that the call matches it, the binding is decorative.
- Tampered authorisation details: RFC 9396 warns that the parameter passes through the user's browser and can be altered, and recommends signed request objects (RFC 9101) or pushed authorization requests (RFC 9126) where integrity matters. It also requires the authorisation server to validate and sanitise details and reject unknown types with
invalid_authorization_details. - Policy gaps and fail-open: a PDP outage or a policy that defaults to allow when no rule matches recreates static over-grant silently.
- Intent laundering through sub-agents: a parent agent splits a forbidden task into individually allowed sub-tasks, each approved in isolation. See Delegation Chains and Attenuated Authority for AI Agents.
- Approval fatigue: if every intent goes to a human, people approve without reading, which is worse than a well-designed static rule.
Controls that make intent safe: derive intent from an authenticated source (the user's own request in the client, a ticket in the system of record, a signed workflow step), not from model-generated text alone; when the model proposes an intent, show it to the user or check it against the source record before issuing the token; bind the token to exact resource identifiers and limits through authorization_details; make the resource or a gateway compare every call's parameters with the granted details; set the PDP to deny by default and fail closed; carry the delegating user and agent in the token (act claim) so policy can enforce the intersection of their rights.
Where intent comes from
| Intent source | Trust level | Use for |
|---|---|---|
| Ticket, order or case in a system of record, referenced by ID | High: the record was created through an authenticated process | Service desk, customer service and operations agents |
| User's own request, confirmed in the client UI with the real parameters | High, if the confirmation shows exact values | Personal assistants, payments, sharing |
| Signed step in a deterministic workflow | High: the workflow, not the model, chose the action | Plan-then-execute pipelines, scheduled jobs |
| Model-proposed intent checked against policy only | Medium: policy limits the damage but cannot detect a well-formed malicious task | Low-impact actions within tight limits |
| Model-proposed intent derived from untrusted content | Low: treat as attacker-controllable | Never sufficient on its own for writes |
Decision criteria
| Signal | Static scopes are enough | Add intent-based authorisation |
|---|---|---|
| Action impact | Read, search, summarise | Write, pay, delete, share, change permissions |
| Reversibility | Easily undone | Irreversible or costly to undo |
| Resource breadth per scope | Scope already covers a small, known set | Scope covers many records, customers or tenants |
| Exposure to untrusted content | Agent reads only internal, curated data | Agent reads email, web pages, uploaded files or third-party tool output |
| Who the agent acts for | Itself, on its own data | Many users with different rights |
| Audit requirement | Access logging is sufficient | Each action must be justified by a business reason |
| Resource support | APIs accept only scope-based tokens | APIs or a gateway can enforce details or call a PDP |
Small teams rarely have a PDP and policy authors. Start with fine-grained scopes, resource indicators, short tokens and a gateway that enforces simple per-tool limits (allowed record IDs, maximum amounts) taken from the ticket; that captures most of the value. Large organisations with many agents and APIs gain most from a central PDP with AuthZEN-style requests, because policy then lives in one place and every agent action produces a decision record. See Prompt Guardrails vs Policy Engines for AI Agent Actions for why that PDP must be outside the prompt.
Worked scenario: a customer service refund agent
An agent handles customer service tickets for an online retailer. It reads the ticket, the customer's order history and inbound emails, and can issue refunds and update addresses.
Static-scope design: the agent holds orders:read, refunds:write and customers:write for the whole platform, with a refresh token. An email containing hidden instructions persuades it to refund a different order to a different card. Every call is within scope, so every call succeeds, and the logs show only that the token permitted it.
Layered design: scopes are cut to orders:read and a refund scope that only the orchestrator can exchange. When the agent decides a refund is warranted, the orchestrator requests a token through RFC 8693 exchange with authorization_details of type refund, the order identifier from the ticket record, a maximum amount equal to the order line value and an act claim naming the agent. The PDP receives subject (agent acting for the service desk), action (refund.create), resource (the order) and context (ticket ID, amount, customer ID from the ticket) and permits only if the ticket and order belong to the same customer. The refund API compares the call with the token's details and rejects anything else. Refunds above a threshold go to a human with the real parameters shown. The injected email can still make the agent propose a refund, but the proposal fails because the order is not on the ticket and the amount exceeds the limit, and the denial is logged with its reason.
What it cost: one PDP call and one token exchange per refund, policy authoring for three rules, and a change to the refund API. Read-only lookups stayed on static scopes, so most traffic saw no added latency.
How to implement
- Inventory agent tools and scopes. For each tool record the scope it uses, what the scope actually permits, and the narrowest permission the tool's tasks need. The gap is your over-grant.
- Tighten scopes first. Split read and write, add resource indicators, shorten token lifetimes and remove passthrough. This is cheap and lowers the ceiling for everything that follows.
- Classify actions by impact. Mark which tool calls are irreversible, financial, data-sharing or permission-changing; these are the candidates for intent binding.
- Choose an intent source per action. Use the trust table above. Where only model-proposed intent is available, add a user confirmation or a tight policy limit.
- Stand up the decision point in shadow mode. Send PDP requests for every high-impact call and log the decisions without enforcing. Compare decisions with what actually happened for two to four weeks and fix policy gaps.
- Enforce for one agent and one action type. Issue task-bound tokens, make the resource or gateway check parameters against them, and keep the old scope path behind a feature flag for rollback.
- Expand and remove standing grants. Move further actions to intent binding, then revoke the broad write scopes and refresh tokens the agent no longer needs. See revoking delegated agent access for the revocation steps.
Detection and measurement
- Log decisions, not just calls: record each PDP request and decision with task ID, agent, delegating user and reason, alongside the resource's own access log (NIST SP 800-53 AU-12).
- Alert on mismatch: calls whose parameters differ from the granted details, and repeated denials for one agent, are early signs of injection or drift.
- Watch step-up loops: the MCP specification asks clients to limit scope upgrade retries; repeated
insufficient_scopechallenges for one agent may indicate it is trying to widen its rights.
| Metric | What good looks like |
|---|---|
| Share of high-impact actions authorised by a task-bound token or PDP decision | Rising towards 100% |
| Agents holding write scopes with long-lived refresh tokens | Falling to a named, reviewed list |
| Median lifetime of task-bound tokens | Minutes |
| Parameter mismatches between calls and granted details | Near zero, each investigated |
| PDP fail-open events | Zero |
| Human approval rate for intents sent to review | Not near 100%: a rubber-stamp rate suggests fatigue |
Common failure patterns
- Letting the model write its own permission slip: intent generated from untrusted content and approved by policy alone, which turns prompt injection into authorised action.
- Task tokens the resource never checks: details are issued but the API still checks only scope, so the extra precision protects nothing.
- Keeping the broad scope "just in case": intent binding is added for new flows while the old write scope and refresh token remain, so an attacker simply uses the old path.
- Requesting every scope at first connection: following the
scopes_supportedfallback without trimming makes the initial grant as broad as the server allows. - Fail-open policy: PDP timeouts treated as allow to protect user experience.
- Approval for everything: routing every intent to a human, who then approves on reflex. See the Human-in-the-Loop for AI Agents Guide.
Framework mapping
| Framework | Reference | How it applies |
|---|---|---|
| NIST SP 800-53 Rev. 5 | AC-3, AC-6, AC-24, IA-9, AU-12 | Access enforcement, least privilege, access control decisions by a decision point, service identification, decision logging |
| NIST CSF 2.0 | PR.AA | Identity management, authentication and access control |
| CIS Controls v8.1 | 6 Access Control Management | Granting and revoking access by need |
| ISO/IEC 27001:2022 Annex A | A.5.15, A.5.18, A.8.2 | Access control, access rights, privileged access rights |
| OWASP Top 10 for LLM Applications 2025 | LLM01, LLM06 | Prompt injection as the route to intent spoofing; excessive agency as the cost of over-broad scopes |
| MITRE ATT&CK v20 and ATLAS | T1698, T1699, AML.T0051, AML.T0053 | Indirect and direct prompt injection, agent tool invocation |
Practitioner checklist
- List every agent tool with its scope and the narrowest permission its tasks need.
- Split read and write scopes and request only the scopes a server challenges for.
- Send RFC 8707 resource indicators and validate audience on every server; never pass tokens through.
- Classify actions by impact and reversibility and mark which need intent binding.
- Anchor every high-impact intent in a ticket, a confirmed user request or a signed workflow step.
- Express intent in
authorization_detailsor a PDP request, and integrity-protect it. - Make the resource or gateway compare each call's parameters with the granted details.
- Run the PDP deny by default and fail closed, in shadow mode first.
- Revoke broad write scopes and refresh tokens once intent binding covers the action.
- Track mismatch, fail-open and approval-rate metrics monthly.
Standards and references
- IETF: RFC 9396 OAuth 2.0 Rich Authorization Requests
- IETF: RFC 8693 OAuth 2.0 Token Exchange
- OpenID Foundation: Authorization API 1.0 (AuthZEN)
- Model Context Protocol: Authorization specification
- OWASP: LLM06:2025 Excessive Agency
- OWASP: LLM01:2025 Prompt Injection
- NIST: SP 800-53 Rev. 5 Security and Privacy Controls
Related NHI Mgmt Group resources: AI Agent Authorisation Guide, Per-Task vs Standing Consent for AI Agents Acting on a User's Behalf, Pre-Execution Policy Checks vs Post-Execution Monitoring, Prompt Injection Guide.