Agent security · 9 min
OAuth, Scopes, and Confirmed Agent Writes
Design agent authorization so identity, audience, scope, preview, human confirmation, version checks, and idempotency reinforce one another.
A safe agent write needs more than an OAuth token. OAuth establishes who authorized a client, which resource the token targets, and which scopes it carries. A confirmed-write protocol binds a specific human decision to a specific proposed change at a specific version of product state.
Four different questions
Do not compress these checks into “the user is logged in.”
- Identity: Which user and client are acting?
- Audience: Was the token issued for this resource server?
- Scope: May this identity read cases, write cases, or both?
- Intent: Did the user confirm this exact state change?
An access token with cases:write establishes available authority. It does not prove that the user approved changing OPS-1042 from open to investigating.
Publish the authorization boundary
An MCP resource should expose protected-resource metadata. That metadata points a client to the relevant authorization server and supported scopes. The authorization server publishes its endpoints, supported grant, client registration method, and PKCE requirement.
The synthetic lab uses:
Resource: https://permadyn.ai/mcp/ops-demo
Scopes: cases:read cases:write
Grant: authorization_code + PKCE S256
Client: dynamically registered public client
At the MCP endpoint, the server validates the bearer token signature, expiration, resource audience, sandbox session, and required read scope. The domain service independently checks write scope for preview and apply.
Never pass the MCP token through
An incoming token is intended for the MCP server audience. Passing it to another API confuses trust boundaries and may expose credentials to a service that should not receive them.
If the MCP adapter calls another protected API, use a separately designed service credential, token exchange, or on-behalf-of flow appropriate to that API. Keep the audiences and logs distinct.
The Permadyn lab avoids the ambiguity entirely: the MCP adapter calls its in-process domain service and never forwards the incoming bearer credential.
Preview before confirmation
The preview operation reads current state and stores an immutable proposal:
{
"proposalId": "proposal_…",
"caseId": "OPS-1042",
"caseVersion": 1,
"changes": {
"status": { "from": "open", "to": "investigating" },
"assignedTo": { "from": "Untriaged", "to": "Billing review" }
},
"expiresAt": "…",
"reversible": true
}
The server also hashes the proposed change and generates a hidden challenge. No case mutation occurs.
Bind confirmation to the proposal
The user interface displays the exact diff. A deliberate click exchanges the hidden challenge for a short-lived confirmation token. That token is bound to:
- the authorizing sandbox user,
- the proposal identifier,
- the case version,
- the proposed change hash,
- and the expiration.
It can be used once. The apply operation also requires an idempotency key.
current state ── preview ── exact diff ── human click
│ │
└──────── version + change hash ───────┘
↓
one-use confirmation capability
↓
apply + idempotency + version compare
Fail closed when reality changes
If another actor updates the case after preview, the stored version is stale. Apply must reject the request and require a new preview. If the proposal content changes, its hash no longer matches. If the token is replayed with a different idempotency key, it fails. If the same completed request is retried with the same key, the original result is returned without a duplicate mutation.
The important property is not that failures are impossible. It is that ambiguity does not silently become authority.
Keep consequential boundaries contextual
A reversible assignment change can use a compact confirmation UI. Sending money, deleting customer data, prescribing treatment, or making an employment decision requires a different risk model and specialist review. “Human in the loop” is not a universal control if the person lacks information, time, or meaningful choice.
Claim boundary
This pattern demonstrates defense in depth for a synthetic reversible workflow. It is not a general security certification or a claim that the same controls are sufficient for regulated, irreversible, or high-consequence actions.