12  Agent action authorization

Action authorization keeps model-generated proposals separate from user, service, and policy decisions that permit consequential changes.

Suppose an employee with a payment limit of 1,000.00 USD asks an organization’s AI application to pay an invoice for 4,200.00 USD. The model generates tool-call arguments, and the application submits the request with scoped credentials to the business service. If that service accepts the request as written, a payment above the employee’s limit can go out. Before execution, the service should resolve the exact invoice and receiving account, check the amount against the employee’s current payment limit, and verify any required approval. Employee confirmation alone cannot raise that limit.

The same problem appears wherever an agent holds real access. Reading a document and changing an account are separate permissions. Sending a message and running a command also need their own authorization. A policy decision outside the model has to link each proposed action to a user or service identity. Model-generated text does not authenticate the requester or establish permission.

An invoice proposal passes typed argument checks, object resolution, business authorization, any required human approval, and bounded execution. Identity, tool discovery, and task-scoped memory connect to the relevant checks. Receipts, denials, and ambiguous outcomes lead to distinct reconciliation paths. The receiving business service's final check of current permissions, resolved request, business state, and required approval is not drawn separately.
Figure 12.1: The ‘Authorizing agent actions’ overview introduces Chapter 12, ‘Agent action authorization’. The model proposes a payment, while identity, tool discovery, memory, and schema checks supply distinct inputs to the application. Business authorization resolves the actual invoice and supplier under current policy. Human approval, when required, binds to the exact operation. Immediately before the effect, the receiving business service enforces current user and agent permissions, the resolved object, destination, arguments, relevant business state, and required approval. Earlier application checks or approval cannot override revoked access or changed state. This final service check is not drawn separately. Budgets and result checks limit repetition and guide recovery. Action permissions and limits on the execution environment remain separate controls.

12.1 Agent identities and delegated access

Google Threat Intelligence Group1 reported that, beginning as early as August 8 and continuing through at least August 18, 2025, an actor it tracks as UNC6395 used compromised OAuth tokens associated with the Salesloft Drift application. With them it exported data from many organizations’ Salesforce tenants. The case is credential theft, not a model failure. It matters here because agents may use these tokens. A stolen bearer token can let its holder use the integration’s access wherever a receiving service still accepts that token.

An agent is an application loop that uses model output and application state to select a tool or another step. The application receives the result and updates its state. It continues until a stopping rule applies. A proposal-only application may specify a tool and its arguments but stops before submitting the operation for execution. A field such as employee: E17 generated by the model is only a claimed identifier. Authentication supplies the evidence needed to associate the call with an account.

One agent request can involve an employee and an application client. It can also involve an agent process and a tool service. The target resource has an owner. A resource owner is the person or organization able to authorize access to a protected resource. A general tool path records the user identity, application or agent identity, tool service, credential, target object, requested operation, and external result. The receiving service checks current policy against trusted records.

A credential provides evidence of a calling identity or access grant. OAuth 2.0 provides one established approach to delegated access. A client application can receive an access token representing an allowed use without receiving the person’s password. The token’s token audience identifies the service or services intended to accept it. Its token scope describes allowed kinds of access. A token permitting invoice reading does not by itself authorize a payment. Along this path, the model generates operation fields. The application turns those fields into a submitted request and attempts the operation. The receiving service is the component that executes or rejects it.

The Model Context Protocol (MCP) standardizes messages between an AI application and services exposing tools, resources, or prompt templates. The MCP host is the application coordinating that use. An MCP client is its connector to an MCP server, the service exposing those capabilities (MCP specification2). In the payment example, the host contains a finance client, the MCP server offers invoice tools, and a downstream business service holds invoice and payment records. The server may call that business service, but the two roles have separate access decisions.

An authorization server issues access tokens under its authorization policy. In MCP’s HTTP authorization flow, it issues a token for the client to present to the protected MCP server. The issuer may share a deployment with that server while performing a distinct role (MCP authorization profile3).

The MCP authorization profile for revision 2026-07-284 covers HTTP transport when a client acts for a resource owner. Authorization is optional for MCP implementations. When this flow is used, the profile requires a token on each HTTP request and server validation of its intended audience. Connections through standard input and output (STDIO), the streams between a local client and server process, should obtain credentials from the environment instead of following the HTTP flow. A specification requirement does not show implementation compliance. The token authorizes access to the MCP server. Business-user identity and permission for a particular invoice still need the application’s trusted identity mapping and business policy. NIST zero trust guidance5 says access decisions use the subject and requested resource for each session. The framework does not specify MCP tokens or an agent identity representation. Tool discovery and server trust explains which interfaces the host makes available.

In the example organization, the employee signs in with an organization account. The application then obtains a limited token, which the action service uses to resolve the employee and requested object again. The agent process never becomes the employee merely because it presents the token. The trace records each identity, credential audience, scope, expiry, and revocation state. Those records provide the inputs for action authorization.

Validated claims identify the account and grant represented by the credential. They do not prove that the current bearer is the original employee, client, or workload (RFC 67506). A separate check must authenticate the application or prove possession of a bound key where sender constraint is used. The issuer defines the grant and its lifetime. Expiry limits a token’s validity in time. For credentials, revocation withdraws a grant or credential before it would otherwise expire.

The receiving service validates the audience, scope, expiry, and current status under its own rules. Status may be checked online, checked locally, or cached. A cached result can be stale. The deployment states its validation method, revocation support, cache window, and failure behavior. Short-lived delegated credentials add exchanges and can interrupt a task when identity services fail. A service that validates without checking current revocation information may continue accepting the token until expiry. Revocation requests can propagate with delay (RFC 70097). After misuse, recovery revokes the grant, ends affected sessions, and rotates related secrets. Allowed and denied calls then run again. A passing run covers only the services and users it actually tested.

12.2 Action policy and enforcement

A well-formed payment request can still exceed the employee’s authority. When the model generates operation fields, those fields form an action proposal. Once the application submits them, the service has an actual request to evaluate. Neither step grants permission by itself. The action service has to check the current user, operation, destination, target object, and relevant business conditions. Resolving identifiers means finding the corresponding objects in trusted business records. For a payment the service can compare the proposed amount with the invoice, check the supplier’s current payment status, and apply the employee’s limit. Reading the invoice and transferring money are separate permissions. A policy enforcement point is the component that allows or blocks that operation after receiving a policy decision. A policy decision point evaluates the request against rules and returns a result. These roles may sit in the same service or in cooperating components.

A model proposal enters application object resolution and policy checks using user identity, agent identity, and trusted state. Policy branches to denial, bounded tool execution, or required human approval. Rejected approval stops execution. A decision trace records checks and external results. The receiving business service's final authorization check is not shown separately and remains required before the effect.
Figure 12.2: The figure’s ‘12.2 Action authorization’ heading refers to ‘Action policy and enforcement’. The model proposes an operation and arguments but does not authorize the action. Application checks resolve objects and prepare the request, including human approval when required. The receiving business service must enforce current user and agent permissions, the resolved object, destination, arguments, relevant business state, and required approval immediately before the effect. An earlier application decision or approval cannot override revoked access or changed state. The diagram does not draw this final service check separately.

Saltzer and Schroeder’s8 least-privilege principle limits a program or user to the rights needed for the task, while complete mediation calls for checking each access to each object. RFC 97009 applies least privilege to tokens by restricting audience, resource, and action to the minimum needed. NIST zero trust guidance10 also states that permission for one resource does not imply permission for another. These principles guide placement of checks but do not prove that a selected service enforces object-level policy. The check belongs on a path that every payment operation has to pass through. An application-level check would offer limited protection if another route could write payments directly. Reusing an earlier decision also needs care when permissions, account status, or the requested amount have changed.

In the payment example, the model generates payment arguments for supplier B, and the application submits them to the service. The service checks whether the employee may initiate this payment type and whether supplier B is allowed. It then checks the amount against the current limit and looks for any required approval. It evaluates those facts with trusted records outside the model context. The resulting allow or deny decision determines what fields the tool interface needs to carry.

Open Policy Agent (OPA) is an example of a separate policy engine. An application supplies structured input, OPA evaluates rules written in Rego, its policy language, and the application receives a decision (OPA documentation11). OPA does not perform the payment or make the calling application obey its result. The service controlling the business effect has to enforce the decision. The following abbreviated rule uses Rego v1 syntax and illustrates four local conditions. It is not a complete payment policy. It assumes that the surrounding service has already done four things. It has authenticated the caller and the application, and validated a positive integer payment amount and a nonnegative integer remaining limit, both expressed in the invoice’s currency and its smallest unit, such as cents for USD. It has also resolved the invoice and destination and checked a trusted approval record.

package payments.authz
default allow = false
allow if {
  input.caller.payment_initiator == true
  input.supplier.payments_enabled == true
  input.amount_minor <= input.caller.remaining_limit_minor
  input.approval.present == true
}

The input object contains the caller’s payment role, the supplier’s status, an amount in minor currency units, and an approval status. In this design these values come from authenticated context and trusted records. The amount is a validated positive integer in the invoice’s currency, and the approval status is read from a trusted approval record, not from model text. A model-generated statement that approval.present is true would not be evidence of approval. The default decision is false, and the rule produces true only when all four conditions hold. The service then allows or blocks the payment call based on its policy.

A Boolean result does not explain which condition failed, so a useful denial record would need additional information about the evaluated checks. Field names and the rule requiring approval for every payment are choices made for this example, not built-in features of OPA. A remaining payment allowance that concurrent or sequential calls consume needs protected accounting of its own. A Boolean check alone does not make concurrent use atomic. Chapter 13 (Limits on agent execution) treats sequences and transactions.

Example

Concrete authorization trace. Suppose employee E17 asks the agent to pay invoice INV-204. The model generates operation pay_invoice, target INV-204, amount 4,200.00 USD, and supplier B-204. The application converts the amount to 420,000 cents and submits the request with the authenticated employee context. The service resolves INV-204 as open for 4,200.00 USD but finds payments to B-204 disabled, the amount above the employee’s 1,000.00 USD limit, and no recorded approval. The enforcement point returns decision-771, with the payment-record field empty. This result shows that the service denied the resolved object under current business state. A different invoice, supplier, employee, or later state requires a new decision. The identifiers and values in this and the later traces are invented for the example.

Table 12.1: Inputs to an action authorization decision.
Decision input Resolved record
caller E17, finance initiator, current limit 1,000.00 USD
invoice INV-204, open, amount 4,200.00 USD (420,000 cents)
supplier B-204, payments disabled
approval none recorded
policy result deny; supplier disabled, amount above employee limit, and approval missing

A deny record proves no effect only when the external result is also checked. The business service enforces the decision from trusted caller, operation, object, destination, approval, and current-state records. Report unauthorized actions blocked over all eligible unauthorized attempts separately from authorized actions completed over all valid authorized cases. Per-object checks add service calls and can delay high-volume workflows. Stale state, an alternate write path, or a privileged intermediary can bypass them. If an unauthorized action occurs, suspend the affected route and revoke its credential under the incident recovery process. Seek transaction reversal only where supported, then rerun both case groups.

12.3 Tool contracts and validation

The service needs fields it can interpret consistently before it can check the requested operation. A tool contract specifies an operation’s structured inputs and outputs so that model text can become a request that ordinary software can validate. The contract can constrain field types and formats. It cannot decide whether the current caller may change a specific account, file, message, or business record. Structure and authorization answer different questions about the same request.

MCP revision 2026-07-2812 lets a tool declare JSON Schema input and output schemas, using the 2020-12 dialect by default. Servers must validate inputs and apply access controls. For declared output schemas, server conformance is required while client validation is recommended (MCP specification13). Structural acceptance still does not establish permission. MCP14 also tells clients to treat tool annotations as untrusted unless they come from a trusted server. That warning does not establish server trust or validate a tool result. The NIST Secure Software Development Framework15 includes input validation and output encoding as secure software practices.

The organization validates generated arguments against the schema and rejects unknown operations and extra fields. It normalizes destinations before server-side authorization on the resolved object. Tool results return typed status and identifiers rather than instructions that silently change the plan in this design. Whether a trusted destination resolution or a changed annotation can be accepted depends on discovery and protocol configuration in the next section. Schema validation can reject malformed requests, but it does not establish user intent or server trust. A harmful value that remains schema-valid or a server that interprets fields differently can bypass structural checks.

Example

Concrete contract trace. The operating mode is conversion of a model proposal into a validated request. The allowed contract requires operation, invoice_id, and integer amount_minor. Its additional-properties rule rejects fields outside that set.

  1. The model returns {"operation":"pay_invoice","invoice_id":"INV-204","amount_minor":420000}. Parsing succeeds and the schema accepts the request.
  2. The service resolves INV-204 and sends the object plus caller E17 to authorization. The decision is deny because the supplier is disabled.
  3. A second model output adds "shell_command":"pay now". Schema validation rejects the unknown field, so no authorization request is made.

The first path shows that a well-formed request can still be unauthorized. In the second path, the contract stops an unexpected representation before it reaches the service. These results leave tool-server trust and the safety of valid amounts untested.

Enforcement here is split between two components. The parser admits or rejects the structure, and the business service then allows or denies the resolved action. Measurements therefore keep malformed requests, valid unauthorized requests, and completed authorized requests in separate denominators. Strict contracts need version management and can reject compatible changes. If a changed contract breaks a required operation, disable that version. An approved version can replace it only if available and under the team’s control; otherwise keep the affected route disabled. Reconcile external state and rerun the case groups under the incident recovery process.

12.4 Tool discovery and server trust

Invariant Labs16 showed on May 26, 2025, that a public GitHub issue could steer an agent using the GitHub MCP server into leaking private repository data. Invariant called this a toxic agent flow. It was a demonstration, and no CVE was assigned. A different failure followed in September 2025. Version 1.0.16 of postmark-mcp, an unofficial package on the npm JavaScript registry named after the Postmark email service, added a hidden blind carbon copy (BCC). It sent a copy of every email sent through the malicious package to an outside address (Postmark and The Hacker News17).

In the first case hostile content arrived as ordinary tool data. In the second the server code itself was hostile. Both raise the question of which servers and tools an application should present to the model.

Tool discovery decides which interfaces the MCP host presents to the model for the current request. Its client obtains the server’s advertised tools using the roles introduced above. A server’s ability to speak the protocol does not decide whether the organization accepts its code or endpoint as trusted.

In MCP revision 2026-07-2818, clients request a tool list with tools/list, and the returned set may vary with the authorization on the request. The same MCP revision19 describes stateless, self-contained requests and per-request capability negotiation. These are version-specific protocol facts. Older revisions and application-managed state can behave differently. Discovery responses carry a self-reported server description, and the specification warns against trusting it. The approved configuration should therefore bind to an authenticated endpoint or a locally controlled executable, not to a display name or a bare schema digest. An unchanged definition says little about whether the server’s implementation has changed.

The application records the protocol revision, server identity, transport, authentication method, negotiated capabilities, tool-list response, and schema hash. A changed schema or newly visible tool triggers review before use. Tool visibility still does not grant object-level permission, so execution repeats the policy checks from the previous section. This version and trust record also separates protocol state from the application’s own agent memory.

Example

Concrete discovery trace. The operating mode is tool setup before the agent can propose an action. The MCP host connects to server finance-tools.internal using protocol revision 2026-07-28 and an application credential limited to employee E17. The capability response records tools. The tools/list result contains read_invoice and pay_invoice, with schema digests a81c and d092. The approved configuration expected only read_invoice, so the host marks pay_invoice as newly visible and withholds both tools from the model pending review. After review, read_invoice is released while pay_invoice remains disabled. The discovery result detects a change but does not prove that the server binary or transport endpoint is trustworthy.

At each connection the host compares server identity, protocol revision, capability response, tool list, and schema digests with the approved record. It counts unexpected or changed tools over all returned tools, and expected tools missing over the approved set. Review adds startup delay and maintenance whenever schemas change. The comparison also has a limit: a trusted server can still change behavior after discovery or misdescribe an operation. Recovery disconnects the server, revokes its credential, and restores an approved configuration before discovery and action tests run again.

12.5 Agent memory controls

An agent that keeps information between steps can carry one user’s data into another user’s task, or carry planted content into later decisions. Agent memory is application-managed information retained across steps or sessions, such as prior user preferences, summaries, tool results, or task state. The security questions begin with who may write it and which user or task may read it. They also cover how corrections replace old entries and when expiry or deletion removes it. Protocol state, conversation history, retrieved records, and model parameter updates are different mechanisms.

The MCP core for revision 2026-07-2820 describes stateless requests, so it does not define a long-term memory policy for an application. OWASP21 describes memory and context poisoning as a distinct area in its 2025 agentic risk list. The OWASP entry is a community risk description without a prevalence rate or validated retention design.

In the example organization, every memory entry stores a user or tenant identifier, writer, source, creation time, expiry, and correction link. Reads apply the same identity and resource checks as retrieval. A test writes synthetic state for employee A and verifies that employee B cannot retrieve or alter it. That test covers only the selected users and entries. It does not establish correct isolation or deletion across every retained copy. The approval interface should reveal which retained state affected a proposed action. A remembered statement that a payment was approved cannot replace the actual approval record.

The memory service applies the current user, tenant, task, and entry labels to every write, read, correction, expiry, and deletion. Its test matrix counts unauthorized reads or writes over every cross-user pair, and expired entries returned over all expiry cases. Isolation and retained history increase storage and correction work. The rule fails when a summary carries the wrong label, or when a shared cache or copied state sits outside the memory service. Recovery quarantines affected memory and blocks dependent actions. Reachable copies are deleted or corrected before the matrix runs again. Copies in untracked stores or in model parameters stay outside what this test can show.

12.6 Binding approval to exact actions

Human approval can add an independent decision before a consequential action, but only if the person sees the operation that will execute. An approval object contains the operation, resolved destination, important arguments, expected effect, current state, expiry time, and a digest that binds approval to those details. For a payment, a supplier identifier alone may be insufficient if its associated receiving account can change. Binding a supplier label without the resolved account would miss exactly that change. The interface keeps retrieved text from untrusted sources visually separate from the trusted summary.

MCP22 recommends that a person retain the ability to deny tool invocations and that clients present confirmation for operations. MCP’s trust and safety principles23 also call for explicit consent and clear explanation before data exposure or tool use. The specification states that the protocol cannot enforce every consent requirement, and it does not show that a confirmation interface produces informed decisions. A digest alone supplies none of these checks. Approval needs a protected binding with the approver, resolved operation, object and version, actual recipient, amount, expiry, and relevant conditions. It also needs a comparison of executed fields and a recheck of current permission.

The application freezes the reviewed arguments, records the approval, then compares the digest and relevant external state immediately before execution. Any change in recipient, amount, object, or policy invalidates the approval. A short lifetime limits reuse. Both the approval record and the comparison need protection from unauthorized changes. An attacker who can replace the approved record could otherwise replace its digest too. The record does not block an operation by itself. The service has to perform the comparison and reject an unacceptable mismatch. The example below tests whether the service rejects changed fields. It does not measure how well a person understands the approval screen or notices a misleading description.

Example

Concrete approval trace. Suppose the employee, invoice, supplier, and amount checks pass, and the payment now awaits the required human approval. The review screen shows invoice INV-311, supplier B-311, resolved receiving account acct-311, amount 900.00 USD, current supplier status, and expiry time 14:10. It binds those fields to approval record approval-55 with digest 7f31.

At 14:08, the action service resolves the request again. The amount is now 9,000.00 USD, so the current digest is c244 and does not match the approved object. The service records approval_mismatch and blocks execution. It then requests a new review. The payment-identifier field remains empty. The tested binding stopped a changed request. These values and shortened digests are illustrative, and the trace does not measure whether a person understood the original review screen. Where even the receiving account can change between the check and the final effect, execution needs a supported destination precondition or transaction. Otherwise the race stays explicitly unresolved.

Immediately before execution, the service checks the bound operation, resolved object, destination, arguments, state, digest, approver, and expiry. A test of this binding counts changed requests blocked over all mutation cases and valid approvals completed over all unchanged cases. Good results still leave gaps. A digest can still match after an employee’s payment permission is revoked, which is why the service rechecks current permission as well. An expiry time limits how long an approval can be reused but does not detect an altered amount before expiry. Approval adds latency and can create reviewer fatigue. Misleading presentation, approver compromise, or an omitted field can bypass the intended decision. Recovery cancels the request, freezes affected actions, and applies any supported reversal before a fresh review. A valid binding does not prove informed human judgment.

12.7 Action budgets and delegated credentials

A loop can repeat a permitted payment until the task exceeds its allowed count or cost. Checking each payment’s permission does not bound the whole task. The executor also needs a budget and a stopping condition. A detector gate between the agent and its actions serves a different role. For example, in September 2026, Capsule Security announced an “AI circuit breaker” built on detectors trained with NVIDIA’s Nemotron models. SecurityWeek24 reported Capsule’s claims of a 71-millisecond decision time and a 96.9% detection score in Capsule’s own testing. These are the vendor’s figures on a benchmark it chose. They do not show how the product performs against real agents or new attacks, or establish enforcement of a task budget.

Budgets control how much work a task may perform. Token controls determine who can reuse or pass on its access. The two controls answer different questions even when the same action service enforces both.

12.7.1 Action budgets and retries

An authorized action can still cause excessive harm through repetition or an expanded target set. Continued execution after partial failure creates another path. An action budget sets a maximum count, cost, time, data volume, or number of affected objects for one task. A transaction limit bounds each operation. A stopping condition ends the sequence when state, credentials, policy, or observed results differ from the approved assumptions.

The NIST Generative AI Profile25 recommends monitoring pre-trained models and using organizational risk tolerance to evaluate acceptable performance, including decommissioning or retraining models that operate outside defined limits. OWASP’s 2025 prompt-injection entry26 links impact to business context and application agency and recommends least privilege and human approval for high-risk actions. These sources support bounded authority as a risk response. They leave transaction semantics and retry safety to the system design, along with rollback behavior.

The executor decrements the budget before each operation. An idempotency key lets a supporting service recognize retries of the same intended operation. The executor checks the returned state and stops on an ambiguous result. It records partial completion and hands recovery to a person or a separate service with the needed authority. This design pattern requires system-specific failure tests. The budget record must say whether it counts attempts, completed effects, or both, so retries cannot silently reset the allowance.

The executor’s decisions rest on task identity, current count or cost, external result, credential state, and idempotency key. Its tests count over-budget steps blocked and duplicate effects over all retry cases, and they measure ordinary completion separately. Tight budgets reduce possible harm but can stop legitimate long tasks. Unmetered side effects, reused identities, or a service that ignores the idempotency key can bypass the design. Recovery stops the loop and reconciles each external object. Reversible effects receive the supported compensation, and an authorized person handles ambiguous cases. A clean test run does not show that every external action can be reversed.

Example

Reconciling an uncertain payment. Suppose a service supports idempotency for the same key and payment fields and retains its result for 24 hours. The executor submits one authorized payment with key pay-417. The service creates payment P-417, but its response is lost. The executor records an unknown result and pauses further payments rather than assuming failure.

An authorized recovery process queries the service using that key and obtains the receipt for P-417. In a separate retry test within the retention period, the service receives the same key and fields and returns the existing receipt without creating a second payment. A new key, changed fields, or a retry after the retention period would need the service’s specified handling and a fresh decision. The example assumes these service features and outcomes. It does not establish them for other payment APIs.

Conclusion. The lost reply left the caller uncertain even though the payment completed. Reconciliation established the actual effect. The retry test exercised the service’s duplicate handling under the same key and payload.

12.7.2 Token replay controls

Reuse of credentials adds a distinct path. The identity and scope checks in Agent identities and delegated access remain necessary. With a bearer token, possession of the token is enough to present the represented access (RFC 675027). Restrictions on audience and scope reduce what a copied token can be used for when receiving services enforce them (RFC 970028). A sender-constrained token adds evidence that the caller holds a particular key. A copied token alone is then not enough, but only where the receiving service verifies that evidence and the attacker lacks key or signing access (RFC 944929). Demonstrating Proof of Possession (DPoP) provides one such mechanism. The MCP HTTP token path in this revision specifies Bearer authorization. DPoP is therefore a separate OAuth mechanism that needs explicit support and matching validation, not an automatic feature (RFC 944930). Proof replay handling is still necessary.

Example

Checking a DPoP request. Suppose an OAuth service supports DPoP and issues access token T bound to client public key K. For a permitted invoice read, the client signs a new proof with the matching private key. It sends T and that proof over TLS. The proof includes a unique identifier, creation time, HTTP method, target URI excluding query and fragment, and a hash of T (RFC 944931).

The service checks proof structure and signature, token validity and key binding, the token hash, method, URI, and freshness. In this deployment it also rejects proof identifiers already seen for that key within the acceptance window. Assume the first request passes these checks and the employee’s invoice permission check. A copied T without signing access fails proof validation. Replaying the accepted proof fails the stored-identifier check.

Limit. These checks do not grant invoice permission or authenticate the full request body, general headers, or query parameters. TLS and application checks remain necessary. Compromised signing access defeats the copied-token distinction. This is an explicitly supported DPoP deployment, not the earlier MCP Bearer path.

A refresh token lets a client obtain new access tokens without asking the user to sign in for every request. If an authorization server issues refresh tokens to public clients, applications that cannot reliably protect a client secret, RFC 970032 requires sender-constrained refresh tokens or rotation to detect replay. With rotation, the authorization server issues a replacement refresh token and invalidates the previous one. Reuse of the old token can reveal that more than one party has a copy. The server cannot reliably determine which party is legitimate from that reuse alone. Revoking the active refresh token interrupts further access-token issuance through it. It does not by itself establish that every previously issued access token is already unusable (RFC 700933).

12.7.3 Delegation and token exchange

When an agent passes work to another agent or service, the receiving component may require a token issued for its own interface. Token exchange is an issuer-mediated protocol in which a client presents an existing token to an authorization server and requests a new token for a specified use. The issuer validates the inputs and applies policy before issuing or denying it. The client then presents the new token to the target service (RFC 869334). This adds an issuer decision and an availability dependency to the handoff. Forwarding the old token performs neither step.

The protocol distinguishes impersonation from delegation. With impersonation, the receiving context treats the actor as the subject. With delegation, it recognizes the actor as a separate party acting for the subject. Neither case grants unlimited rights. The receiving service’s policy still determines which operations the exchanged token permits (RFC 869335).

Example

Exchanging a token for an invoice read. Suppose employee E17 authorized invoice reading through finance-tools, an MCP server. Its inbound token T1 has audience finance-tools and scope invoice.read. The server now needs to call invoice-api. This deployment has configured that API’s authorization server to accept the earlier issuer and this delegation path.

  1. Acting as an OAuth client, finance-tools authenticates to the authorization server’s token endpoint. Its exchange request includes T1 as subject_token, the token’s type, target audience invoice-api, and requested scope invoice.read. It also supplies an actor_token identifying finance-tools and the corresponding type. This actor token is optional in the general protocol but is part of this selected delegation example. It does not replace client authentication.
  2. The issuer validates both tokens and checks that finance-tools may act for E17 at that target with that scope. Assume this read is permitted and payment is prohibited under the policy. The response contains new access token T2, issued for invoice-api, with subject E17, current actor finance-tools, scope invoice.read, and its own expiry. A request outside this grant is denied.
  3. finance-tools sends T2 to invoice-api. The API validates the issuer, audience, lifetime, and scope, then checks E17’s permission for the requested invoice. T1 alone would fail the target-audience check. The identifiers and policy are illustrative choices using the RFC’s exchange roles, not an MCP feature that appears automatically.

A JSON Web Token (JWT) is a format for carrying claims as a JSON object, with support for cryptographic integrity protection or encryption (RFC 751936). For a JWT version of T2, an abbreviated claim fragment is {"sub":"E17","aud":"invoice-api","scope":"invoice.read","act":{"sub":"finance-tools"}}. This fragment is not a usable credential: issuer, expiry, cryptographic protection, and validation are omitted. If an earlier actor were retained, "act":{"sub":"finance-tools","act":{"sub":"assistant-A"}} would put the current actor outside and history inside. RFC 869337 limits access-control decisions to top-level claims and the current actor. Historical actors do not add rights.

Input tokens normally stay valid and gain no automatic lifetime or revocation linkage to the tokens issued from them. Passing a received client token onward to a further API is forbidden in the MCP authorization profile38. A separate token issued for that API is required. Token exchange is one possible way to obtain it when both the issuer and deployment policy support the flow.

Note

Chapter checkpoint. An agent in the example organization sees pay_invoice during tool discovery and proposes a payment after reading an invoice. List the records needed to decide whether the action may execute and to explain the final result.

Answer. Record the employee, agent process, credential audience and scope, MCP revision, server identity, negotiated capabilities, tool list, and exact schema. Parse the proposal into typed fields, resolve the invoice and supplier in trusted business records, and make an object-level authorization decision. For a consequential payment, bind approval to the resolved operation, amount, receiving account, destination, expiry, and current state. Recheck both policy and approval immediately before execution, then retain the external payment identifier or the blocking reason. Tool visibility and schema validity alone do not grant authority.

Open questions remain about memory isolation, approval quality, and recovery from partial execution. Chapter 13 (Limits on agent execution) applies the same limits on authority inside browser, code, network, and multimodal environments.


  1. Austin Larsen, Matt Lin, Tyler McLellan, and Omar ElAhdan (2025), “Widespread Data Theft Targets Salesforce Instances via Salesloft Drift,” Google Cloud Blog, Google Threat Intelligence Group, August 26, 2025, source. An investigator’s account of stolen OAuth credentials. No model or agent behavior was involved.↩︎

  2. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Overview,” “Key Details,” “Base Protocol,” source.↩︎

  3. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Authorization,” “Purpose and Scope,” “Protocol Requirements,” “Roles,” and “Token Requirements,” source.↩︎

  4. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Authorization,” “Purpose and Scope,” “Protocol Requirements,” “Roles,” and “Token Requirements,” source.↩︎

  5. Scott Rose, Oliver Borchert, Stu Mitchell, and Sean Connelly (2020), Zero Trust Architecture, NIST SP 800-207, section 2.1, tenets 3-4, printed pp. 6-7, source.↩︎

  6. Michael B. Jones and Dick Hardt. The OAuth 2.0 Authorization Framework: Bearer Token Usage. RFC 6750, Internet Engineering Task Force (IETF), October 2012. Official specification. Bearer use requires no proof of a separate cryptographic key. Applies to OAuth bearer deployments.↩︎

  7. OAuth 2.0 Token Revocation. RFC 7009, Internet Engineering Task Force (IETF), August 2013. Official specification. Revocation requests can propagate with delay, and revoking only the refresh token does not promise immediate invalidation of issued access tokens. Introspection responses carry an active state with identity fields, checked under the issuer’s applicable rules with caching trade-offs (RFC 7662, October 2015).↩︎

  8. Jerome H. Saltzer and Michael D. Schroeder (1975), “The Protection of Information in Computer Systems,” Proceedings of the IEEE 63(9), 1278-1308, section I.A.3, “Design Principles,” items c, “Complete mediation,” and f, “Least privilege,” source.↩︎

  9. Torsten Lodderstedt, John Bradley, Andrey Labunets, and Daniel Fett. Best Current Practice for OAuth 2.0 Security. RFC 9700 / BCP 240, Internet Engineering Task Force (IETF), January 2025. Official specification. Minimal privileges with audience, action, and resource restrictions (Section 2.3). Refresh-token rotation or sender constraint for public clients (Sections 2.2.2 and 4.14.2).↩︎

  10. Scott Rose, Oliver Borchert, Stu Mitchell, and Sean Connelly (2020), Zero Trust Architecture, NIST SP 800-207, section 2.1, tenet 3, printed p. 6, source.↩︎

  11. Open Policy Agent contributors. Open Policy Agent (OPA), documentation overview (undated), introduction and “Writing Policies with Rego.” Official documentation. Snapshot accessed 2026-09-16. OPA evaluates structured input against declarative Rego policies and returns decisions. The surrounding application must enforce them at the operation boundary. The chapter’s payment fields and approval rule are constructed examples, not built-in OPA behavior or evidence that a payment integration has been tested.↩︎

  12. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Tools,” “Data Types,” “Tool,” and “Output Schema,” source.↩︎

  13. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Tools,” “Data Types,” “Tool,” and “Output Schema,” source.↩︎

  14. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Tools,” “Data Types,” “Tool,” annotations requirement, source.↩︎

  15. Murugiah Souppaya, Karen Scarfone, and Donna Dodson (2022), Secure Software Development Framework (SSDF) Version 1.1: Recommendations for Mitigating the Risk of Software Vulnerabilities, NIST SP 800-218, practice PW.5.1, example 1, printed p. 13, source.↩︎

  16. Marco Milanta and Luca Beurer-Kellner (2025), “GitHub MCP Exploited: Accessing private repositories via MCP,” Invariant Labs Blog, May 26, 2025, source. A demonstration with no CVE. It shows a possible path, not an observed attack.↩︎

  17. Postmark (2025), “Information Regarding Malicious ‘postmark-mcp’ Package,” Postmark Blog, September 25, 2025, source. Ravie Lakshmanan (2025), “First Malicious MCP Server Found Stealing Emails in Rogue Postmark-MCP Package,” The Hacker News, September 29, 2025, reporting Koi Security’s findings, source. Postmark speaks for the service the package imitated, and Koi Security’s findings are cited through a news report rather than Koi’s own publication.↩︎

  18. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Tools,” “Capabilities” and “Listing Tools,” source.↩︎

  19. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Overview,” “Key Details,” “Base Protocol,” source.↩︎

  20. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Overview,” “Key Details,” “Base Protocol,” source.↩︎

  21. OWASP GenAI Security Project (2025, December 9), “OWASP Top 10 for Agentic Applications: The Benchmark for Agentic Security in the Age of Autonomous AI,” release announcement, “The OWASP Agentic Top 10,” ASI06, “Memory & Context Poisoning,” source.↩︎

  22. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Tools,” “User Interaction Model,” source.↩︎

  23. Model Context Protocol contributors (2026), Model Context Protocol Specification, revision 2026-07-28, “Security and Trust & Safety,” “Key Principles” and “Implementation Guidelines,” source.↩︎

  24. Kevin Townsend (2026), “Capsule Security Launches ‘AI Circuit Breaker’ to Stop Rogue Agents,” SecurityWeek, September 3, 2026, source. A news report of vendor claims. The figures come from Capsule’s own evaluation and are not independently replicated.↩︎

  25. National Institute of Standards and Technology (2024), Artificial Intelligence Risk Management Framework: Generative Artificial Intelligence Profile, NIST AI 600-1, MANAGE 3.2 and action MG-3.2-009, printed pp. 43-44, source.↩︎

  26. OWASP GenAI Security Project (2025), Top 10 for LLM Applications 2025, LLM01:2025, “Prompt Injection,” impact discussion under “Types of Prompt Injection Vulnerabilities” and mitigation items 4-5, source.↩︎

  27. Michael B. Jones and Dick Hardt. The OAuth 2.0 Authorization Framework: Bearer Token Usage. RFC 6750, Internet Engineering Task Force (IETF), October 2012. Official specification. Bearer use requires no proof of a separate cryptographic key. Applies to OAuth bearer deployments.↩︎

  28. Torsten Lodderstedt, John Bradley, Andrey Labunets, and Daniel Fett. Best Current Practice for OAuth 2.0 Security. RFC 9700 / BCP 240, Internet Engineering Task Force (IETF), January 2025. Official specification. Minimal privileges with audience, action, and resource restrictions (Section 2.3). Refresh-token rotation or sender constraint for public clients (Sections 2.2.2 and 4.14.2).↩︎

  29. OAuth 2.0 Demonstrating Proof of Possession (DPoP). RFC 9449, Internet Engineering Task Force (IETF), September 2023, sections 4.2–4.3, 7, 11.1, and 11.7. Official specification. Access-token protection requires an issued DPoP token with matching proof validation. A Bearer response does not acquire that protection.↩︎

  30. OAuth 2.0 Demonstrating Proof of Possession (DPoP). RFC 9449, Internet Engineering Task Force (IETF), September 2023, sections 4.2–4.3, 7, 11.1, and 11.7. Official specification. Access-token protection requires an issued DPoP token with matching proof validation. A Bearer response does not acquire that protection.↩︎

  31. OAuth 2.0 Demonstrating Proof of Possession (DPoP). RFC 9449, Internet Engineering Task Force (IETF), September 2023, sections 4.2–4.3, 7, 11.1, and 11.7. Official specification. Access-token protection requires an issued DPoP token with matching proof validation. A Bearer response does not acquire that protection.↩︎

  32. Torsten Lodderstedt, John Bradley, Andrey Labunets, and Daniel Fett. Best Current Practice for OAuth 2.0 Security. RFC 9700 / BCP 240, Internet Engineering Task Force (IETF), January 2025. Official specification. Minimal privileges with audience, action, and resource restrictions (Section 2.3). Refresh-token rotation or sender constraint for public clients (Sections 2.2.2 and 4.14.2).↩︎

  33. OAuth 2.0 Token Revocation. RFC 7009, Internet Engineering Task Force (IETF), August 2013. Official specification. Revocation requests can propagate with delay, and revoking only the refresh token does not promise immediate invalidation of issued access tokens. Introspection responses carry an active state with identity fields, checked under the issuer’s applicable rules with caching trade-offs (RFC 7662, October 2015).↩︎

  34. Michael B. Jones, Anthony Nadalin, Brian Campbell (editor), John Bradley, and Chuck Mortimore. OAuth 2.0 Token Exchange. RFC 8693, Internet Engineering Task Force (IETF), January 2020, Sections 1.1, 2.1-2.3, 4.1, and Appendix A.2, official specification. Subject and actor inputs, issuer policy, target token, independent lifetimes, and current-actor claims are distinct parts of the exchange.↩︎

  35. Michael B. Jones, Anthony Nadalin, Brian Campbell (editor), John Bradley, and Chuck Mortimore. OAuth 2.0 Token Exchange. RFC 8693, Internet Engineering Task Force (IETF), January 2020, Sections 1.1, 2.1-2.3, 4.1, and Appendix A.2, official specification. Subject and actor inputs, issuer policy, target token, independent lifetimes, and current-actor claims are distinct parts of the exchange.↩︎

  36. Michael B. Jones, John Bradley, and Nat Sakimura (2015), JSON Web Token (JWT), RFC 7519, IETF, May 2015, Sections 2-3 and 7.2, source. A representation and validation specification, not a grant of application permission.↩︎

  37. Michael B. Jones, Anthony Nadalin, Brian Campbell (editor), John Bradley, and Chuck Mortimore. OAuth 2.0 Token Exchange. RFC 8693, Internet Engineering Task Force (IETF), January 2020, Sections 1.1, 2.1-2.3, 4.1, and Appendix A.2, official specification. Subject and actor inputs, issuer policy, target token, independent lifetimes, and current-actor claims are distinct parts of the exchange.↩︎

  38. Model Context Protocol contributors (2026), Authorization Security Considerations, revision 2026-07-28, “Token Audience Binding and Validation” and “Access Token Privilege Restriction,” source. Token passthrough is forbidden. A separate token issued by the downstream API’s authorization server is required. This does not require every deployment to implement RFC 8693.↩︎