What Is the Client Credentials Grant?
The Client Credentials grant is the simplest OAuth 2.0 flow: there is no resource owner and no browser redirect. A confidential client authenticates directly to the /token endpoint using its client_id and client_secret (or a client assertion), and if valid, the authorization server issues an access token scoped to that client itself. This models machine-to-machine access, a billing microservice calling an inventory API, a CI pipeline calling a deployment API, where the 'user' of the resource is the application, not a human sitting at a browser.
Cricket analogy: It's like a ground curator badge at Lord's: the curator doesn't need a spectator ticket checked at the gate for each visitor they bring; their own staff ID alone grants them direct access to the pitch and equipment sheds.
Requesting and Scoping the Token
A Client Credentials request is a single POST to /token with grant_type=client_credentials, and the client authenticates either via HTTP Basic auth (client_id:client_secret), a signed JWT client assertion (private_key_jwt), or mTLS. Because there's no user consent screen, scopes must be pre-approved administratively when the client is registered; the token the server issues reflects only what that specific client is allowed to do, which is why fine-grained, least-privilege scope design matters even more here than in user-facing flows, since there's no human reviewing a consent prompt to catch an over-broad request.
Cricket analogy: It's like a groundstaff access card pre-configured to open only the pitch and covers store, not the players' dressing room, decided by the ground manager in advance, with no gate steward reviewing it visitor by visitor.
Storing and Rotating Client Secrets
Because the client_secret is the only thing standing between an attacker and full access to whatever the client is scoped for, it must be treated with the same rigor as a database password: stored in a secrets manager (not source control or environment files checked into git), rotated on a schedule, and rotated immediately if a leak is suspected. Many providers support two active secrets simultaneously specifically to allow zero-downtime rotation, deploy the new secret, confirm services pick it up, then revoke the old one, rather than a hard cutover that risks an outage.
Cricket analogy: It's like a team keeping the exact wording of their coded field-placement signals in a locked notebook rather than a shared team WhatsApp, and changing the code entirely if a rival team is suspected of decoding it.
# Client Credentials token request using HTTP Basic auth
curl -X POST https://auth.example.com/oauth/token \
-u "billing-service:$CLIENT_SECRET" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "scope=inventory:read inventory:reserve"
# Example response
# {
# "access_token": "eyJhbGciOiJSUzI1NiIs...",
# "token_type": "Bearer",
# "expires_in": 3600,
# "scope": "inventory:read inventory:reserve"
# }
# Calling the protected API with the resulting token
curl https://api.example.com/inventory/sku-4471 \
-H "Authorization: Bearer $ACCESS_TOKEN"Client Credentials never returns a refresh token, because there's nothing to 'refresh' beyond re-authenticating with the same client_secret. When the access token expires, the service simply requests a new one the same way it requested the first. Most production services cache the token in memory and refetch a few minutes before expires_in elapses, avoiding a token request on every single API call.
When Not to Reach for Client Credentials
It's tempting to use Client Credentials whenever a human isn't directly clicking a consent screen, but it is the wrong choice whenever the API call needs to act on behalf of a specific user with that user's own permissions, for example, a backend fetching 'my orders' for a logged-in customer. Using Client Credentials there collapses all users into one flat service identity, losing per-user authorization and audit trail; the correct pattern is Authorization Code (the user authenticates once) possibly combined with a token exchange or on-behalf-of flow if a downstream service needs to act as that user.
Cricket analogy: It's like letting the team manager's single all-access pass be used to check every player in and out individually, losing the ability to know exactly which player entered when, when each player really should swipe their own personal pass.
A Client Credentials token represents the application, not a user. If you find yourself passing a user_id as a query parameter alongside a Client Credentials token to say 'act as this user', you've built an authorization bypass: any caller with the shared client secret can now access any user's data by changing the ID. Use Authorization Code (or a proper delegation/token-exchange flow) whenever user-specific data or actions are involved.
- Client Credentials is for machine-to-machine calls where the client is acting as itself, with no resource owner in the flow.
- The client authenticates directly to /token using client_id/client_secret, private_key_jwt, or mTLS, with no browser redirect.
- Scopes must be configured administratively at registration time since there is no user consent screen to review requested scopes.
- No refresh token is issued; expired access tokens are replaced by simply requesting a new one with the same credentials.
- Client secrets should live in a secrets manager, rotate on a schedule, and support zero-downtime dual-secret rotation.
- Never use Client Credentials to act on behalf of a specific end user; that requires Authorization Code or a delegation flow.
- Least-privilege scoping matters more here than in user flows, since there's no human reviewing a consent prompt as a safety check.
Practice what you learned
1. What is the defining characteristic of the Client Credentials grant?
2. Why does the Client Credentials grant never return a refresh token?
3. How are scopes determined in a Client Credentials flow, given there's no consent screen?
4. Which scenario is an inappropriate use of the Client Credentials grant?
5. Why is client_secret rotation with two simultaneously valid secrets useful?
Was this page helpful?
You May Also Like
Authorization Code with PKCE
The Authorization Code grant is OAuth 2.0's most secure and widely used flow, and PKCE hardens it further so it is safe for public clients like single-page apps and mobile apps.
The Refresh Token Grant
Refresh tokens let a client obtain new access tokens without repeating the full authorization flow, keeping short-lived access tokens practical for long-running sessions.
Choosing the Right Grant
OAuth 2.0 offers several grant types built for different trust boundaries; picking the wrong one is one of the most common real-world sources of OAuth vulnerabilities.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics