OAuth Client Credentials Flow

Not every API call comes from a user. Background jobs, backend services, cron tasks, data pipelines, and partner integrations call APIs as themselves. The client credentials grant is OAuth 2.0's answer: a client authenticates directly to the authorization server with its own credentials and receives an access token representing the application, scoped to what that service is allowed to do.

It's simple (one HTTP request, no browser, no user), but security depends on how the client authenticates, how narrowly tokens are scoped, and how credentials are stored and rotated. Modern practice is moving from static client secrets toward asymmetric keys, mTLS, and workload identity federation, which avoids long-lived secrets entirely.

TL;DR

Quick Example

A caching client using private_key_jwt (Python):

Core Concepts

The Grant

  1. The client authenticates to the token endpoint and requests scopes (and often an audience or resource indicator).
  2. The authorization server verifies the client, checks which scopes it's allowed, and issues an access token.
  3. The client calls APIs with Authorization: Bearer <token>.
  4. APIs validate the token (signature, issuer, audience, expiry) and authorize by scopes or client identity.

There's no refresh token: when the access token expires, the client simply requests a new one.

Client Authentication Methods

Scopes, Audiences, and Least Privilege

Give each service its own client ID and the minimum scopes it needs (invoices:read, not admin). Request tokens for a specific audience or resource (RFC 8707), so a token for the billing API can't be replayed against the user API. Resource servers must check both audience and scopes. See API security.

Token Caching and Expiry

Access tokens are typically valid for minutes to an hour. Cache them per scope and audience set, refresh shortly before expiry, and handle 401 responses by fetching a new token once. Requesting a token for every API call adds latency, and can trigger rate limits at the authorization server.

Workload Identity Federation

Instead of storing client secrets in configuration, a workload proves its identity with a credential its platform already issues:

The authorization server (or cloud IAM) trusts the platform's issuer and exchanges these tokens for access tokens, using the JWT bearer grant or token exchange. There are no secrets to leak or rotate. See secrets management.

On-Behalf-Of and Token Exchange

When service A handles a user request and must call service B as that user, client credentials would lose the user's identity and permissions. Use OAuth 2.0 Token Exchange (RFC 8693), Entra ID's on-behalf-of flow, or forward a properly scoped user token. Reserve client credentials for actions that genuinely belong to the service itself.

Best Practices

One Client per Service

Separate client IDs per service and environment make revocation, auditing, and least-privilege scoping possible. Shared "backend" credentials used by ten services are a single point of compromise.

Prefer Asymmetric Client Authentication

private_key_jwt or mTLS keeps private keys in a KMS or HSM, supports key rotation via published JWKS, and avoids transmitting shared secrets. Many identity providers support them.

Store Remaining Secrets Properly

If you must use client secrets, keep them in a secrets manager, inject them at runtime, rotate them regularly, and alert on use from unexpected networks.

Validate Tokens Fully at Resource Servers

Check signature, issuer, audience, expiry, and scopes. Distinguish machine tokens from user tokens if your authorization logic depends on user context (for example via the sub claim, or a client_id without a user).

Common Mistakes

Using Client Credentials for User Actions

A backend that fetches a client-credentials token with broad scopes and then acts for any user loses per-user authorization, creating a confused-deputy risk. Carry user identity through token exchange, or explicit authorization checks.

Requesting a Token per Request

This hammers the authorization server, adds latency to every call, and can hit rate limits. Cache until near expiry.

Over-Scoped Service Clients

Granting a reporting job * or admin scopes means a leak of its credentials compromises everything. Scope narrowly per client.

FAQ

When should I use the client credentials flow?

For machine-to-machine communication where the calling application acts on its own behalf: backend services, scheduled jobs, daemons, data pipelines, and trusted partner integrations. It isn't for applications acting on behalf of a signed-in user.

Does the client credentials flow return a refresh token?

No. The client can always authenticate again to get a new access token, so refresh tokens aren't needed. Cache the access token and request a new one shortly before it expires.

What is private_key_jwt?

A client authentication method where the client signs a short-lived JWT with its private key and sends it as a client_assertion. The authorization server verifies it with the client's registered public key. No shared secret is transmitted or stored on the server.

How is client credentials different from an API key?

Both identify an application, but client credentials produce short-lived, scoped, audience-restricted access tokens from a central authorization server, with standardized validation and rotation. API keys are usually long-lived static secrets checked directly by the API. OAuth tokens limit damage from leaks, and centralize policy.

Related Topics

References