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
- A service POSTs
grant_type=client_credentialswith its client authentication to the token endpoint and gets an access token. - The token represents the application, not a user. Authorize by scopes and audience.
- Client authentication options: client secret (simplest),
private_key_jwt(asymmetric, recommended), or mutual TLS. - Cache tokens until shortly before expiry, and don't request a new token per API call.
- Prefer workload identity federation (Kubernetes, cloud, or CI identities) over stored secrets where available.
- Don't use it to act on behalf of users; use the authorization code flow or token exchange instead.
Quick Example
A caching client using private_key_jwt (Python):
Core Concepts
The Grant
- The client authenticates to the token endpoint and requests scopes (and often an audience or resource indicator).
- The authorization server verifies the client, checks which scopes it's allowed, and issues an access token.
- The client calls APIs with
Authorization: Bearer <token>. - 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:
- Kubernetes projected service account tokens.
- GitHub Actions OIDC tokens. See GitHub Actions security.
- AWS, GCP, or Azure instance and managed identities.
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
- OAuth — The framework overview
- OAuth Token Lifecycle — Expiry, caching, and validation
- OAuth Security Best Practices — Sender-constrained tokens and more
- Microservices — Service-to-service authentication
- Secrets Management — Storing client credentials
- Zero Trust — Authenticating every workload