# How do I scope OAuth tokens per task for an AI agent instead of giving it one broad token?

**Short answer:** Give the agent a fresh, short-lived token for each task, limited to the scopes and the one resource that task needs, and record who delegated it. Keep the user's broad grant (or refresh token) on your server, never in the agent's context. When a task starts, mint a token for it: request only the task's scopes, name the target API with the resource parameter (RFC 8707) so the token works nowhere else, and keep its lifetime to minutes. Where your identity provider supports OAuth 2.0 Token Exchange (RFC 8693), exchange the user's token for a narrower one in which the act claim names the agent acting on the user's behalf, so every downstream log shows both the person and the agent. When the agent hits something its token can't do, it should get a 403 insufficient_scope and ask for a step-up with the user's approval, not fall back to a bigger token. Write a delegation log entry for every token: user, agent, task, scopes, audience, expiry and token ID.

## Checklist
1. Split the grant: the user's long-lived consent and refresh token stay in your backend or token vault. The agent only ever holds the short-lived access token for the task in hand.
2. One task, one token: request only the scopes the task needs (for example calendar.events.read for a scheduling lookup, not full calendar access) and name a single audience with the resource parameter (RFC 8707). MCP clients must already send resource for MCP servers.
3. Keep lifetimes short: minutes for an access token, ending when the task does, and no refresh token in the agent's hands. A leaked or misused token then expires on its own.
4. Use token exchange for delegation: RFC 8693 lets a service swap the user's token (subject_token) plus the agent's own credential (actor_token) for a narrower token whose act claim records the agent. In Microsoft Entra ID the equivalent is the on-behalf-of flow.
5. Narrow further where the server supports it: Rich Authorization Requests (RFC 9396) express a grant as structured authorization_details, such as one payment amount or one folder, instead of a broad scope string.
6. Bind the token to the agent where you can: DPoP (RFC 9449) sender-constrains a token to a key the agent holds, so a copied token is useless elsewhere.
7. Handle missing permissions with a step-up, not a wider default: the MCP authorization spec has servers answer 403 with error="insufficient_scope" and the scopes needed; the client asks the user to approve those, with a retry limit.
8. Log every delegation and every call: user, agent, task ID, scopes, audience, issued and expiry times, token ID (jti), and the tool calls made with it, with token values kept out of the logs. Revoke the task's tokens when the task ends or is cancelled.

## Why one broad token is the wrong unit
- An agent's permissions should match its current task, not everything the user could ever allow. A single token with every scope means a prompt-injected or confused agent can do anything the user can, for as long as the token lives.
- Long-lived tokens in an agent's context end up in logs, transcripts and tool results. Short-lived, single-audience tokens limit both how long and where a leak matters.
- A shared token also erases attribution: the API sees the user, not which agent or task acted, so you can't tell an intended action from a hijacked one afterwards.

## What a delegated token should say
- sub: the user whose authority is being used. act (RFC 8693): the agent acting for them, nested if one agent delegates to another. aud: the one API it is for. scope or authorization_details: the task's permissions. exp: minutes away. jti: an ID you can find in the delegation log.
- The resource server should check all of them, including the audience, and reject a token that names a different API, rather than accepting any token signed by the right issuer.
- Token exchange can only narrow: the issued token should never carry more scopes or a later expiry than the token it was exchanged from.

## Ask Rightshold (free, no key)
Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code (one-click setup: https://www.rightshold.com/start?ref=seo), then ask: "An agent presented this RS-Intent token. Is it still in force, signed by that agent, and does it cover the operation and domain I'm about to allow?"

```json
{
  "tool": "verify_intent",
  "arguments": {
    "token": "<the RS-Intent value the agent presented>",
    "operation": "<the operation, for example read>",
    "domain": "<your-domain.com>"
  }
}
```
- Free. verify_intent checks the token's signature, window and live state (revoked intents fail at once) and whether the operation, domain, counterparty and amount are inside what the agent declared.
- On Rightshold, intent_key issues an API key bound to one declared intent: it can only do the operations, targets and budget that intent names and stops working when the intent ends or is revoked, which is per-task scoping for Rightshold's own API.
- Delegation can only narrow: a sub-agent's intent must fit inside its parent's, and revoking a parent intent ends every intent delegated under it.

_Rightshold does not issue OAuth tokens for your APIs or run your authorization server. Per-task OAuth scoping is configured in your identity provider, token service and resource servers; Rightshold's intents and intent keys scope agents' use of Rightshold itself and give sites a token they can verify._

## Sources
- [RFC 8693: OAuth 2.0 Token Exchange (act and may_act claims)](https://www.rfc-editor.org/rfc/rfc8693)
- [RFC 8707: Resource Indicators for OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8707)
- [RFC 9396: OAuth 2.0 Rich Authorization Requests](https://www.rfc-editor.org/rfc/rfc9396)
- [RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP)](https://www.rfc-editor.org/rfc/rfc9449)
- [MCP specification: Authorization (scope challenge and step-up, 2025-11-25)](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization)
- [RFC 9700: Best Current Practice for OAuth 2.0 Security](https://www.rfc-editor.org/rfc/rfc9700)
- [Microsoft identity platform: OAuth 2.0 On-Behalf-Of flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-on-behalf-of-flow)

## Related
- [How to share one MCP server across a company with per-user auth](https://www.rightshold.com/answers/how-to-share-one-mcp-server-across-a-company-with-per-user-auth)
- [MCP OAuth wrong-audience tokens](https://www.rightshold.com/answers/mcp-oauth-wrong-audience-tokens)
- [How to give an MCP server least-privilege access to GitHub](https://www.rightshold.com/answers/how-to-give-an-mcp-server-least-privilege-access-to-github)
- [How to keep .env secrets and API keys away from AI coding agents](https://www.rightshold.com/answers/how-to-keep-env-secrets-and-api-keys-away-from-ai-coding-agents)

_Not legal advice. Updated 2026-10-29. JSON: https://www.rightshold.com/answers/how-to-scope-oauth-tokens-per-task-for-ai-agents.json_