OAuth 2.0 Authorization Framework
The foundation under MCP authorization and nearly every agent delegation scheme.
Flows / No human
The agent authenticates as itself. No user, no consent screen, no one to ask.
When an agent runs on a schedule, reacts to an event, or does work that belongs to an organization rather than a person, there is no user to redirect. The agent is the principal. It proves its own identity to the authorization server and receives a token whose subject is the agent.
The grant is trivial. The hard part is the credential the agent uses to authenticate. A static client secret in an environment variable is a long-lived password that never gets rotated and leaks into logs, images and model context. A signed assertion from a key the agent holds is better. A platform-issued workload identity the agent never has to store is better still.
7 steps between 3 parties. Each step shows the message and who holds which credential afterward. Use ←→ or select any arrow.
Drag to see every party and step. Tap a step to jump to its explanation.
Instead of sending a shared secret, the agent signs a short-lived JWT with its private key. Issuer and subject are both the client ID; the audience is the authorization server; jti makes it single-use. The private key never leaves the agent.
{
"iss": "invoice-agent",
"sub": "invoice-agent",
"aud": "https://auth.example",
"jti": "b1f7c2a0-5d1e-4c8e-9f3a-0d6b8e1a2c44",
"iat": 1794268800,
"exp": 1794268860
}Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
One direct call. The resource parameter asks for a token that is valid for one API only.
POST /token HTTP/1.1
Host: auth.example
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&scope=invoices.read invoices.reconcile
&resource=https://erp.example/api
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJFUzI1NiJ9…Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
It verifies the signature against the public key registered for this client, checks audience, expiry and replay, then decides which of the requested scopes this client is allowed. There is no user to ask, so policy is the only gate.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
The subject of the token is the client itself. Nothing in it refers to a human.
{
"iss": "https://auth.example",
"sub": "invoice-agent",
"client_id": "invoice-agent",
"aud": "https://erp.example/api",
"scope": "invoices.read invoices.reconcile",
"exp": 1794269400
}Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
An ordinary bearer request.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
The API must treat this as a machine caller. Row-level rules that depend on “the current user” have nothing to bind to. If the agent is doing something for a particular user, that fact has to arrive some other way, and a request parameter the agent filled in is not evidence.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
The audit log records the agent’s client ID. If several replicas, runs or sub-agents share that ID, the log cannot tell them apart. Workload identity systems such as SPIFFE address this by giving each workload its own identity.
Who holds what after this step
Parties not listed hold none of this flow’s credentials at this point.
private_key_jwt or workload identity federation.See the full tracker for status and links.
The foundation under MCP authorization and nearly every agent delegation scheme.
Secretless client authentication, and the second leg of ID-JAG and identity chaining.
Required by MCP. An agent talks to many servers; this is what stops a token for one being replayed at another.
The usual carrier for act and other agent-related claims.
The sanctioned path for agents with no human present.
Your agent uses an identity established by its runtime to obtain short-lived access from a system that trusts that identity.
Every agent process gets a cryptographic identity from the infrastructure it runs on, and uses it to authenticate both ends of every connection.
Bind a token to a key so that stealing the token is not enough to use it.
Trade the token you were given for a new one that names both the user and the service now acting for them.