Flows / No human

Client credentials

The agent authenticates as itself. No user, no consent screen, no one to ask.

Based onRFC 6749published October 2012Guide reviewedNovember 2026

Sources and review details
This page
Implementation guideAn explanation, not a specification
Primary specification
OAuth 2.0 Authorization FrameworkRFC · October 2012
All 5 specifications
5 published
Flow maturity
Stable standardsWhat the rating means
Human involvement
No human
Review
Checked against sources in November 2026How it was checked

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.

Step by step

7 steps between 3 parties. Each step shows the message and who holds which credential afterward. Use ←→ or select any arrow.

Sequence diagram3 participants, 7 steps
  • Direct call
  • Response
  • Local action

Drag to see every party and step. Tap a step to jump to its explanation.

1Sign a client assertion2Token requestwith assertion3Verify assertion, apply policy4Access token (sub = agent)5API call with Bearer token6Validate; authorize the client7200 OK

  1. 1AgentLocal action

    The agent creates a signed proof of its identity

    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

    Agent
    newprivate key

    Parties not listed hold none of this flow’s credentials at this point.

  2. 2Agent to Authorization serverDirect call

    The agent requests a token

    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

    Agent
    private key

    Parties not listed hold none of this flow’s credentials at this point.

  3. 3Authorization serverLocal action

    The authorization server authenticates the client

    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

    Agent
    private key

    Parties not listed hold none of this flow’s credentials at this point.

  4. 4Authorization server to AgentResponse

    The server issues an access token

    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

    Agent
    private keynewaccess token

    Parties not listed hold none of this flow’s credentials at this point.

  5. 5Agent to APIDirect call

    The agent calls the API

    An ordinary bearer request.

    Who holds what after this step

    Agent
    private keyaccess token

    Parties not listed hold none of this flow’s credentials at this point.

  6. 6APILocal action

    The API authorizes a service, not a person

    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

    Agent
    private keyaccess token

    Parties not listed hold none of this flow’s credentials at this point.

  7. 7API to AgentResponse

    The API responds

    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

    Agent
    private keyaccess token

    Parties not listed hold none of this flow’s credentials at this point.

Watch out for

  • An agent that serves many users with one service identity is a confused deputy waiting to happen. If user A can talk the agent into fetching user B’s data, the API cannot stop it: the token says “agent,” not “user A.”
  • Client secrets are the most common credential found in agent prompts, traces and repositories. Prefer private_key_jwt or workload identity federation.
  • There is no consent step, so scopes are whatever an admin configured. Review them as you would a service account’s IAM role.
  • No refresh token is issued; the agent just asks again. Keep access tokens short-lived so revoking the client takes effect quickly.

Standards in play

See the full tracker for status and links.

RFCRFC 8707

Resource Indicators

Required by MCP. An agent talks to many servers; this is what stops a token for one being replayed at another.