When a person lets an AI agent act for them, the single consent screen they click once can quietly become months of open-ended authority that nobody re-reads. Standing consent grants an agent a durable set of permissions, usually an OAuth grant backed by a refresh token, that it can use whenever it decides to act. Per-task consent asks the person, or a policy acting for them, to approve a specific action or bounded piece of work and issues authority that expires with it. This guide compares the two for identity architects and platform engineers: threat models, mechanisms (scopes, Rich Authorization Requests, short-lived tokens, CIBA), revocation, audit and a decision method based on action risk.
Key takeaways
- Neither model wins outright. Standing consent is the right tool for low-risk, repetitive, read-heavy work; per-task consent is the right tool for actions that move money, delete data, send messages externally or change access.
- Standing consent fails by accumulation. Its typical failures are scope creep, forgotten grants, stolen refresh tokens and consent phishing, all of which give an attacker durable access without a new prompt.
- Per-task consent fails by fatigue. Too many prompts teach people to approve without reading, which turns a strong control into a rubber stamp and pushes teams to quietly widen standing grants.
- The mechanism matters more than the label. A per-task approval that still mints a broad, long-lived token is standing consent in disguise; bind the approval to the action with authorization_details, audience and a short lifetime.
- Most production agents need a hybrid. A narrow standing baseline plus incremental, per-action elevation keeps prompts rare and blast radius small, provided revocation and audit cover both layers.
The short answer
Use standing consent for a small, read-mostly baseline that the agent needs on every run, keep it audience-restricted, and expire it when the agent goes unused. Use per-task consent for any action whose effect is external, irreversible, financial or access-changing, and make the approval produce a token that can only perform that action. Decide per action, not per agent.
For how an agent carries a user's authority across hops, see the AI Agent Service Accounts vs On-Behalf-Of Access and the Delegation Chains and Attenuated Authority for AI Agents.
What each model is, in architectural terms
Standing consent
Architecture in words: the user completes an OAuth authorisation code flow once, the authorisation server records a grant for the agent's client against a set of scopes, and the agent receives an access token plus a refresh token. From then on the agent refreshes silently and acts whenever its planner decides, with no further human interaction until the grant is revoked or the refresh token expires. Google's OAuth documentation for web server applications states that refresh tokens remain valid until the user revokes access or the token expires, and that losing the refresh token means repeating the consent flow.
Threat model: the asset at risk is the grant itself. Anyone who obtains the refresh token, compromises the agent's token store, or tricks the user into granting a malicious client gets the whole scope set for the life of the grant.
Per-task consent
Architecture in words: the agent reaches an action it is not already authorised for, describes that action to an approval channel, and only receives authority after an explicit yes. The authority is bound to that action, through fine-grained authorization_details, a single audience and a short lifetime, and is discarded afterwards.
Threat model: the asset at risk is the approval decision. An attacker who can influence what the agent asks for (through prompt injection), how the request is displayed, or whether the user reads it, can still obtain an approval; but the result is one bounded action, not durable access.
Side-by-side comparison
| Dimension | Standing consent | Per-task consent |
|---|---|---|
| Unit of approval | A client and a set of scopes, once | A specific action or bounded task, each time |
| Typical credential | Access token plus long-lived refresh token | Short-lived, audience-bound access token with authorization_details; no refresh token |
| User friction | Very low after the first screen | Proportional to action volume unless tiered |
| Blast radius if the credential leaks | Every granted scope until revocation or expiry | One action, for minutes |
| Main threats | Consent phishing, scope creep, refresh token theft, forgotten grants | Approval fatigue, misleading prompts, injected requests, disguised broad tokens |
| Prompt injection impact | Agent can use any granted scope without asking | Agent must ask; the user sees the concrete action |
| Evidence of user intent | One historical grant; individual actions show only the agent's choice | An approval record per action, with the parameters approved |
| Revocation target | The grant and every refresh token issued from it | Usually nothing; tokens expire on their own |
| Works when the user is offline | Yes | Only with decoupled approval or pre-approved policy |
Threats that separate the two models
Consent phishing
Consent phishing persuades a user to approve a malicious OAuth client through a genuine consent screen. No password is stolen and MFA is never triggered, because the attacker receives a token rather than a login. The Cyberhaven Chrome extension breach followed this pattern: an employee approved a fake "Privacy Policy Extension" app on a real Google consent screen, which gave the attacker publishing rights. Standing consent makes the payoff durable; per-task consent shrinks it only if the organisation also controls which clients may request consent. In Microsoft Entra ID, the built-in permission grant policy microsoft-user-default-low limits user consent to apps from verified publishers or apps registered in the tenant, and only for permissions the administrator has classified as low impact, with everything else routed to the admin consent workflow. See the Consent Phishing and Illicit OAuth Grants Guide and How to restrict user consent to apps in Entra ID.
Scope creep
Standing grants grow. Developers request every scope up front, incremental authorisation adds scopes that are never removed, and nobody re-approves the total. The Model Context Protocol security best practices (specification version 2025-11-25) list the common mistakes directly: publishing every possible scope in scopes_supported, using wildcard or omnibus scopes such as "*" or "full-access", bundling unrelated privileges to pre-empt future prompts, and treating scopes in a token as sufficient without server-side authorisation logic.
Confused deputy
A confused deputy uses its own legitimate authority on behalf of the wrong party. For agents this appears in two forms. First, a prompt-injected instruction in a document or email causes the agent to use its standing grant for an action the user never wanted; OWASP LLM06:2025 Excessive Agency recommends complete mediation, meaning authorisation is enforced in downstream systems rather than by the model. Second, at the protocol layer, the MCP specification describes an attack on MCP proxy servers that use a static client ID with a third-party authorisation server: if the third party has set a consent cookie, an attacker who dynamically registers a malicious client can obtain an authorisation code without the user seeing a consent screen. The MCP mitigation is per-client consent: the proxy keeps a registry of approved client_id values per user and shows its own consent page naming the client, scopes and redirect_uri. See the Confused Deputy in AI Agents Guide.
Refresh token theft and supply chain exposure
When an integration stores refresh tokens for many customers, compromising that store yields standing consent at scale. In the Salesloft Drift breach, OAuth access and refresh tokens for the Drift Salesforce integration, held in Drift's AWS environment, were used to export data from many customers' Salesforce instances without any user logging in. Per-task tokens held for minutes offer far less to steal. RFC 9700, the OAuth 2.0 Security Best Current Practice, requires refresh tokens for public clients to be sender-constrained or rotated, says refresh tokens should expire after client inactivity, allows automatic revocation after security events such as a password change or logout, and requires refresh tokens to be bound to the scope and resource servers the resource owner consented to.
UX fatigue versus blast radius
Every prompt costs human attention; every standing scope costs blast radius. Four techniques keep both low.
- Tier by action risk: only prompt for actions in the top tiers (see the decision table below). The Human-in-the-Loop for AI Agents Guide covers approval tiering and automation bias in depth.
- Elevate incrementally: start with a minimal baseline and request more only when a privileged operation is first attempted. The MCP security best practices recommend a minimal initial scope set (their example is mcp:tools-basic) and incremental elevation through targeted WWW-Authenticate scope challenges, and Google's include_granted_scopes parameter supports the same in-context pattern.
- Batch into bounded tasks: approve "file these 12 receipts totalling 480 GBP" once, not 12 times, with the token limited to that task.
- Show the concrete effect: an approval screen that says "Send email to [email protected] with attachment invoice-0412.pdf" is readable; "Allow agent to use Mail.Send" is not. Rich Authorization Requests make this possible because the authorisation server renders structured details rather than scope strings.
If approval rates approach 100 per cent while time to approve falls to a second or two, the prompt has stopped being a control.
Mechanisms that implement each model
| Mechanism | What it does | Supports | Notes |
|---|---|---|---|
| OAuth scopes with refresh tokens | Durable grant to a client for a set of scopes | Standing | Bind to consented scope and resources; rotate or sender-constrain refresh tokens (RFC 9700 s4.14) |
| Incremental authorisation and scope challenges | Adds scopes in context when first needed | Hybrid | Reduces up-front breadth but grants still accumulate unless pruned |
| Rich Authorization Requests (RFC 9396) | authorization_details JSON array with type, locations, actions, datatypes, identifier, privileges | Per-task | The authorisation server must return the details actually granted; the user may grant a subset |
| Resource indicators (RFC 8707) and audience restriction | Limits a token to a named resource server | Both | RFC 9700 s2.3: resource servers must refuse tokens not meant for them |
| Short-lived access token, no refresh token | Authority expires with the task | Per-task | RFC 9700 s4.14.2 allows servers to issue no refresh tokens at all |
| OpenID Connect CIBA Core 1.0 (Final) | Decoupled approval on the user's authentication device via a backchannel | Per-task for background agents | binding_message shows a short code on both devices; auth_req_id is single-use and expires |
| Sender constraint (DPoP RFC 9449, mTLS RFC 8705) | Binds a token to a key the agent holds | Both | Limits replay of a leaked token; weakened if the key leaks too |
Rich Authorization Requests in practice: RFC 9396 (Standards Track, May 2023) lets a client request, for example, a payment of a stated amount to a named creditor rather than a generic "payments" scope. For JWT access tokens the RFC recommends adding the granted details, filtered to the audience, as a top-level claim, so the resource server can check that the call matches what the user approved. See the OAuth Rich Authorization Requests (RAR) Guide.
CIBA for agents that run while the user is away: CIBA lets a client start authentication with the OpenID Provider directly, with the user approving on a separate authentication device such as a phone. The binding_message parameter carries a short human-readable code shown on both devices so the user can tell which request they are approving; an optional user_code lets the user block unsolicited requests to their device. CIBA still needs authorization_details or equivalent to bind the token to the action. See the OIDC CIBA Guide.
Revocation and audit
Standing consent: revocation has to reach the grant, not just the current access token. Revoke the refresh token at the authorisation server (RFC 7009 defines the generic revocation endpoint; Google exposes https://oauth2.googleapis.com/revoke), delete the delegated permission grant where the platform models one, and confirm the agent's next refresh fails with invalid_grant. Issued access tokens stay usable until expiry unless the resource server introspects, so keep them short-lived. See Revoking Delegated Access During an Active Agent Incident.
Per-task consent: there is usually little to revoke, which is the point. The audit burden moves to the approval record: who approved, on which device, what the screen displayed, the exact authorization_details granted, the token identifier, and the action the agent then performed. Correlate them with a transaction identifier such as the txn claim shown in RFC 9396.
Decision criteria by action risk
| Action tier | Examples | Consent model | Token properties |
|---|---|---|---|
| 1. Read own data, internal | Read calendar, search own documents, summarise inbox | Standing, narrow, read-only | Audience-bound; refresh token rotated; expire after inactivity |
| 2. Write own data, reversible | Draft an email, create a calendar hold, label messages | Standing with incremental elevation | Separate write scope requested in context; reviewed at recertification |
| 3. External or shared effect | Send email outside the organisation, share a file, post publicly | Per-task, or pre-approved by policy for named recipients | authorization_details naming recipient or resource; minutes-long lifetime |
| 4. Financial or irreversible | Payments, purchases, deletion, contract acceptance | Per-task, every time | authorization_details with amount, payee or object; single use; no refresh token |
| 5. Access-changing | Grant permissions, add an app, change MFA or recovery details | Per-task with step-up authentication, or prohibited for agents | Step-up at the authorisation server; consider dual control |
Adjust for context. A small organisation with a handful of agents can enforce tiers inside the agent platform's approval feature; a large one should enforce them at the authorisation server and resource servers so that no single agent runtime is trusted to apply its own rules, in line with the complete mediation principle in OWASP LLM06. For spend thresholds and approval limits, see the AI Agent Action Approvals and Spending Limits Guide.
Worked scenario: a travel and expenses agent
An employee uses an agent that books travel and files expenses. The first design gave it one standing grant covering calendar read and write, mail send, the travel booking API and the expenses API, with a refresh token valid until revoked. Threat review found that a prompt-injected hotel email could make it book or cancel travel unasked, a token store leak would expose every employee's mail-send capability, and no record showed any booking was the employee's choice.
The redesign kept a standing, read-only baseline (calendar read, travel policy read, the employee's own expense history), set to expire after 30 days without use. Booking a trip now triggers a per-task request whose authorization_details name the route, dates, fare ceiling and cost centre; the employee approves on their phone through CIBA, with a binding_message such as "Trip 7F2" shown in both the chat and the phone prompt. The resulting token is valid for 10 minutes, audience-restricted to the booking API, and carries no refresh token. Expenses are batched into one approval per claim, and external email was removed from the agent. The result was about two prompts per trip and a token store holding only read-only authority.
Implementing and migrating
- Inventory existing grants. List every agent client, the users who granted it, the scopes, whether a refresh token exists, and the last-used date. Treat any grant unused for 90 days as a candidate for removal.
- Classify actions, not agents. Map each tool or API operation the agent can call to a tier in the table above.
- Shrink the standing baseline. Re-register the client with only tier 1 and tier 2 scopes, remove wildcard scopes, and restrict user consent to verified or tenant-registered clients.
- Add per-task paths for tiers 3 to 5. Define authorization_details types for each high-risk operation, configure the authorisation server to render them on the consent screen, and require resource servers to check the granted details.
- Pilot with audit-only enforcement. For two to four weeks, log what would have required approval without blocking, measure the projected prompt rate per user per day, and tune tiers before switching to enforcement.
- Enforce and keep a rollback. Turn on blocking for one agent and one user group first. If prompt volume or failure rates spike, roll back by re-enabling the previous client registration rather than widening scopes on the new one.
- Retire the old grants. Revoke legacy grants and refresh tokens once stable, and verify a refresh attempt fails.
Detection and measurement
- Log: consent grants and changes per client and user, scope elevation events (requested versus granted subset, with a correlation ID, as the MCP guidance recommends), CIBA requests and outcomes, token issuance with authorization_details, and resource calls tagged with the transaction ID.
- Alert: new consent to unverified or newly registered clients; scope additions to an agent client outside a change window; refresh token reuse detected by rotation; per-task approvals arriving in rapid succession from one user; agent calls whose parameters differ from the approved authorization_details.
Metrics that show the design is working:
- Share of high-risk (tier 3 to 5) actions executed under per-task authority: target 100 per cent.
- Median scopes per standing agent grant, tracked monthly: should fall, then hold.
- Standing grants unused for 90 days or more: target zero.
- Approval prompts per user per day and median time to approve: rising volume with falling decision time signals fatigue.
- Time from revocation decision to the last successful agent call: measures whether revocation actually reaches issued tokens.
Common failure patterns
- Per-task in name only: the approval screen is per action, but the token issued afterwards carries the agent's full scope set and a refresh token, so one approval unlocks everything.
- Approving what the model wrote: the consent text is generated by the agent rather than rendered by the authorisation server from structured details, so prompt injection can make a harmful action read as harmless.
- Consent cookie shortcuts: a proxy or gateway skips its own consent screen because a third-party authorisation server remembers an earlier approval, the confused deputy pattern the MCP specification describes.
- Grants that never die: refresh tokens with no inactivity expiry, held by an integration vendor or a token store that becomes a single high-value target, as the Salesloft Drift tokens did.
- Open user consent: any user may grant any client any delegated permission, so a convincing consent phishing page converts directly into standing access.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST SP 800-53 Rev 5 | AC-6 Least Privilege; AC-3 Access Enforcement; AC-2 Account Management; IA-9 Service Identification and Authentication; AU-2 Event Logging; AU-10 Non-repudiation | Minimal standing scopes, enforcement at resource servers, grant lifecycle, agent client authentication, approval evidence |
| NIST CSF 2.0 | PR.AA-01; PR.AA-05; DE.CM | Managing agent credentials, least-privilege authorisations, monitoring grant and approval activity |
| OWASP Top 10 for LLM Applications 2025 | LLM06:2025 Excessive Agency | Minimise permissions, act in the user's context, require user approval for high-impact actions, complete mediation |
| MITRE ATT&CK v20 | T1528 Steal Application Access Token; T1550.001 Application Access Token | Consent phishing and theft or reuse of standing OAuth tokens |
Practitioner checklist
- Classify every agent tool or API operation into an action risk tier before deciding its consent model.
- Limit standing grants to read-mostly, audience-restricted scopes, with no wildcard or omnibus scopes.
- Expire standing grants after inactivity and rotate or sender-constrain their refresh tokens.
- Issue per-task tokens with authorization_details, a single audience, a lifetime of minutes and no refresh token.
- Render approval text at the authorisation server from structured details, never from model output.
- Use CIBA or an equivalent decoupled channel, with a binding message, for agents that act while the user is away.
- Restrict user consent to verified or tenant-registered clients and route everything else to admin review.
- Test revocation end to end: revoke, attempt a refresh, and confirm the agent's next call fails.
Standards and references
- IETF: RFC 9396 OAuth 2.0 Rich Authorization Requests
- IETF: RFC 9700 Best Current Practice for OAuth 2.0 Security
- OpenID Foundation: Client-Initiated Backchannel Authentication Core 1.0
- Model Context Protocol: Security Best Practices
- OWASP: LLM06:2025 Excessive Agency
- Microsoft Learn: Configure how users consent to applications
- Google for Developers: Using OAuth 2.0 for Web Server Applications
Related NHI Mgmt Group resources: Delegation Chains and Attenuated Authority for AI Agents · Revoking Delegated Access During an Active Agent Incident · AI Agent Service Accounts vs On-Behalf-Of Access · AI Agent Authorisation Guide · CIBA vs OAuth Device Flow