IAM-05 · Identity & Access

OAuth 2.1 and OIDC for AI Agents: Client Credentials, Token Rotation, and Tight Scopes

How to authenticate AI agents with OAuth 2.1 and OIDC: when to use the client-credentials flow, how token rotation limits blast radius, and how to design scopes that stay tight.

Agent identity flow: an agent authenticates to an issuer, receives a short-lived scoped token, and presents it to a resource that verifies scope before actingagentnon-human idtoken issuerOAuth / mTLSresourceverifies scopeauthenticatescoped tokenleast privilege: the token grants only this task, expires fast, and is bound to the agent's identity

An AI agent calling your API is not a person clicking a button. It has no browser, no consent screen, and no patience for a login form. Yet most teams still bolt agents onto auth stacks built for human users, then wonder why a leaked token hands a runaway script the keys to the entire tenant. OAuth 2.1 and OpenID Connect (OIDC) offer a better answer, but only if you pick the right flow and resist the temptation to over-grant.

This guide walks through the three decisions that matter for agent identity: which flow to use (almost always client credentials), how to rotate and constrain tokens so that a leak is survivable, and how to design scopes tight enough that a compromised agent can do little damage.

How should an AI agent authenticate with OAuth 2.1 and OIDC?

An autonomous AI agent acting on its own behalf — with no end user in the loop — should authenticate using the OAuth 2.1 client-credentials grant, presenting a confidential client credential to the token endpoint and receiving a short-lived, narrowly scoped access token in return. When the agent acts on behalf of a specific human, you use a delegated flow instead — authorization code with PKCE — to obtain a token that carries the user’s identity, and OIDC supplies the ID token that proves who that user is. The core rule: machine-to-machine agents use client credentials; user-delegated agents use the authorization code flow and lean on OIDC for identity.

The distinction is not cosmetic. A client-credentials token says, “this service is allowed to do X.” A delegated token says, “this service is allowed to do X as Alice, and only what Alice herself could do.” Confusing the two is how agents end up with standing access far beyond what any user has — the classic privilege-escalation footgun in agentic systems.

OAuth 2.1, currently an IETF Internet-Draft (draft-ietf-oauth-v2-1 as of 2026), is a consolidation rather than a new protocol. It folds the most important security guidance from RFC 6749 and the OAuth Security Best Current Practice into a single baseline: PKCE is mandatory for the authorization code flow, the implicit grant is gone, and the resource owner password credentials (ROPC) grant is removed entirely. For agents, the headline is simple — there are now far fewer ways to get auth wrong.

What is the client-credentials flow, and why is it the default for agents?

The client-credentials grant is the OAuth flow with no user. The agent (the client) sends its own credentials directly to the authorization server’s token endpoint and gets back an access token scoped to what that agent is permitted to do. There is no redirect, no consent screen, no human approval — because there is no human.

A minimal exchange looks like this:

POST /oauth/token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&scope=invoices:read inventory:read
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJSUzI1Ni1...

Notice that the agent asks for only two scopes, not everything it could theoretically reach. Notice, too, that it authenticates with a signed JWT assertion (private_key_jwt) rather than a shared secret in the body. Both choices matter, and we will come back to them.

This flow is the default for agents because it models the real trust relationship. An order-reconciliation agent is not “Alice using a tool.” It is a standalone identity that the platform has decided may read invoices and inventory. Giving it its own client identity lets you grant it exactly those scopes, rotate its credentials independently, and revoke it without touching anyone else.

When an agent genuinely acts for a user — say, a copilot that drafts emails in someone’s inbox — client credentials are the wrong tool. There you want the authorization code flow with PKCE, so the user consents once and you carry their identity forward, optionally narrowing it further with token exchange (RFC 8693) when the agent calls downstream services.

Where does OIDC fit if the agent has no user?

OpenID Connect is the identity layer on top of OAuth 2.0, and it works the same way on top of OAuth 2.1. OAuth answers “is this caller authorized to do X”; OIDC answers “who is this caller.” For a pure machine-to-machine agent, the client-credentials flow does not give you an OIDC ID token — ID tokens describe authenticated users, and there isn’t one.

So why does OIDC matter for agents at all? Three reasons. First, the OIDC discovery endpoint (/.well-known/openid-configuration) tells your agent where the token endpoint, JWKS, and supported features live, so you avoid hard-coding URLs. Second, when an agent does act for a user, the ID token is how you prove and propagate that user’s identity through the call chain. Third, the JWKS published as part of OIDC metadata is what your resource servers use to validate the signatures on JWT access tokens without phoning home on every request.

In short: OIDC is essential for user-delegated agents and useful infrastructure even for machine-only ones. It is not a flow you invoke instead of client credentials; it is the identity scaffolding around it.

Why does token rotation matter more for agents than for humans?

Agents run unattended, often in environments where a leaked token can be replayed thousands of times before anyone notices. A human notices when their session breaks; an agent’s token sitting in a misconfigured log file does not announce itself. Token rotation and short lifetimes are how you make a leak survivable rather than catastrophic.

There are two complementary mechanisms, and mature agent deployments use both.

Short-lived access tokens. Keep access-token lifetimes small — minutes, not days. The agent re-runs the client-credentials exchange when its token expires. Because there is no user interaction, re-authentication is cheap and invisible. A short lifetime means a stolen access token is useless almost immediately.

Refresh token rotation. When you do use refresh tokens — more common in delegated flows than in pure client credentials, where re-fetching is trivial — OAuth 2.1 expects rotation: every time a refresh token is used, the authorization server issues a new one and invalidates the old. If an attacker steals a refresh token and uses it, the legitimate client’s next refresh fails — the server sees the old token replayed, recognizes the breach, and can revoke the entire token family. Rotation turns a silent theft into a detectable, containable event.

Layer on sender-constrained tokens for defense in depth. DPoP (RFC 9449) binds a token to a key the client holds, so a stolen bearer token cannot be replayed from another machine. The client proves possession of its private key on every request via a signed DPoP JWT in the header. For agents — which can safely hold a key in a KMS or secrets manager — DPoP or mutual-TLS binding means token theft alone is no longer enough to impersonate the agent.

How do you design tight scopes for an AI agent?

Scope design is where most agent security is won or lost. The default failure mode is the “god agent” — one client with admin or * access because that was easier than enumerating what it actually needs. A compromised god agent is a compromised platform.

Tight scope design rests on a few concrete principles:

  • One identity per capability, not one per agent fleet. Give the invoice agent its own client and the support agent its own client. Shared identities make least privilege impossible and turn revocation into a blunt instrument.
  • Scopes name resources and verbs, not roles. Prefer invoices:read and inventory:write over finance-admin. Resource-and-verb scopes are auditable; role scopes hide what is actually permitted.
  • Read and write are different scopes. An agent that summarizes invoices needs invoices:read, never invoices:write. Splitting verbs stops a hijacked read-only agent from mutating data.
  • Constrain by audience. Use the resource parameter (RFC 8707) or an audience claim so that a token minted for Service A cannot be presented to Service B. This stops token reuse across your own internal APIs.
  • No standing access to data the agent rarely touches. If an agent needs a sensitive scope occasionally, mint a separate short-lived token for that task rather than baking it into the agent’s permanent grant.

The table below contrasts a permissive grant with a tight one for the same hypothetical reconciliation agent.

Aspect Loose grant (avoid) Tight grant (target)
Client identity One shared “agents” client Dedicated client per capability
Scopes read write admin invoices:read inventory:read
Audience Any internal API https://api.example.com/billing only
Token lifetime Hours or days A few minutes
Client auth Shared secret in body private_key_jwt or mTLS
Token binding Bearer DPoP or mTLS-bound

The asymmetry is the point. The tight column costs a little more setup; the loose column costs you the tenant the day a token leaks.

What does a hardened agent OAuth setup look like end to end?

Putting the pieces together, a production-grade machine agent flow runs like this:

  1. The agent authenticates to the token endpoint with private_key_jwt or mutual TLS — never a long-lived shared secret pasted into config.
  2. It requests the client-credentials grant with the minimum scopes for the task at hand, plus a resource parameter naming the exact API it intends to call.
  3. The authorization server returns a short-lived, DPoP-bound access token (and a rotating refresh token, if you use one).
  4. The agent calls the resource server, which validates the token’s signature against the OIDC JWKS and checks the aud, the scopes, the expiry, and the DPoP proof.
  5. When the token expires, the agent silently re-runs the exchange. Credentials rotate on a schedule, and any replay of an old refresh token triggers revocation of the whole family.

Every layer here narrows the blast radius. Short lifetimes shrink the window. Tight scopes shrink the surface. Sender-constraining shrinks who can use a stolen token. Rotation makes theft detectable. None of these is sufficient alone; together they turn a leaked agent credential into an incident you contain rather than a breach you have to explain.

Where to go next

If you are designing agent identity now, start by reading the OAuth 2.1 draft and the OAuth 2.0 Security Best Current Practice (RFC 9700) — they encode the reasoning behind every choice above. Then audit your existing agent clients against the tight-scope table: count how many share an identity, how many hold admin, and how many rely on a static secret. Each of those is a finding. Fixing them is rarely glamorous, but it is the difference between an agent that can be compromised and a platform that can be.

Frequently asked

Should AI agents use the client-credentials flow or the authorization code flow?

Use client credentials when the agent acts autonomously on its own behalf with no human in the loop — it is a machine-to-machine grant with no consent screen. Use the authorization code flow with PKCE when the agent acts on behalf of a specific user, so the token carries that user's identity and is limited to what the user themselves could do.

Does OIDC apply to machine-to-machine agents with no user?

Partly. You do not get an OIDC ID token from the client-credentials flow because ID tokens describe authenticated users, and there is none. But OIDC still provides the discovery endpoint and JWKS your agent and resource servers rely on to locate endpoints and validate token signatures. ID tokens become essential only when the agent acts for a real user.

Why is token rotation more important for AI agents than for human users?

Agents run unattended, so a leaked token can be replayed many times before anyone notices — a human would notice a broken session, an agent will not. Refresh token rotation issues a new token on every use and invalidates the old one, so a replayed stolen token fails and signals a breach, letting the server revoke the whole token family.

What is DPoP and should AI agents use it?

DPoP (RFC 9449) is sender-constraining: it binds an access or refresh token to a key the client holds, so a stolen bearer token cannot be replayed from another machine. Agents can safely keep a key in a KMS or secrets manager and prove possession on each request, making DPoP a strong defense-in-depth layer for agent tokens alongside short lifetimes and rotation.

How do I keep an AI agent's OAuth scopes tight?

Give each capability its own client identity, name scopes as resource-and-verb pairs like invoices:read rather than broad roles, split read from write, constrain tokens to a specific audience with the resource parameter, and avoid baking rarely-used sensitive scopes into the permanent grant — mint a separate short-lived token for those tasks instead.

What changed in OAuth 2.1 that affects agent authentication?

OAuth 2.1 consolidates the OAuth 2.0 security best practices into one baseline: PKCE is mandatory for the authorization code flow, the implicit grant is removed, and the ROPC (password) grant is removed entirely. For agents this means fewer insecure options and a clear push toward the client-credentials flow with strong client authentication.

Should an AI agent authenticate with a client secret?

Avoid a long-lived shared secret pasted into config. Prefer private_key_jwt (a signed JWT client assertion) or mutual TLS, where the agent proves possession of [a private key it never transmits](/blog/cryptographic-identity-ai-agents-mtls-jwt-spiffe-spire). These methods let you rotate credentials independently and are far harder to leak than a static secret sitting in environment variables or logs.