Skip to content

OAuth2 Client Credentials Grant — Machine-to-Machine Authentication

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about OAuth2 Client Credentials Grant. We cover key concepts, practical examples, and best practices to help you master this topic.

The Client Credentials grant allows a client to authenticate directly to the authorization server using its own credentials, receiving an access token without any user involvement.

What You'll Learn

How Client Credentials works, when to use it, implementation, and security considerations.

Why It Matters

Many API integrations are server-to-server with no user present. Cron jobs, microservice-to-microservice communication, automated pipelines — the Client Credentials grant is designed for these scenarios.

Real-World Use

Stripe's API uses Client Credentials for backend integrations. GitHub Actions uses it for automated workflows. Durga Antivirus Pro's backend services use Client Credentials to authenticate between threat intelligence and device management services.

flowchart LR
    A["Backend Service"] -->|"POST /token\ngrant_type=client_credentials"| B["Authorization Server"]
    B -->|"Verify client_id + secret"| B
    B -->|"Access Token"| A
    A -->|"API call + Bearer Token"| C["Resource Server"]
    C -->|"Protected Data"| A
    style A fill:#dbeafe,stroke:#2563eb
    style B fill:#fef3c7,stroke:#d97706
    style C fill:#dcfce7,stroke:#16a34a

Code Example: Client Credentials Flow

import requests

CLIENT_ID = "threat-service"
CLIENT_SECRET = "its-secret"
TOKEN_URL = "https://auth.dodatech.com/oauth/token"
API_URL = "https://api.dodatech.com/threats"

# Step 1: Get access token
response = requests.post(TOKEN_URL, data={
    "grant_type": "client_credentials",
    "client_id": CLIENT_ID,
    "client_secret": CLIENT_SECRET,
    "scope": "threat:read"
})

token_data = response.json()
print(f"Token: {token_data['access_token'][:20]}...")
print(f"Expires in: {token_data['expires_in']}s")

# Step 2: Use token
headers = {"Authorization": f"Bearer {token_data['access_token']}"}
api_response = requests.get(API_URL, headers=headers)
print(f"API status: {api_response.status_code}")

Common Mistakes

1. Using Client Credentials for User Actions

This grant identifies the application, not a user. Do not use it for actions needing user context or audit trail.

2. Hardcoding Client Secrets

Client secrets are sensitive credentials. Use environment variables or a secret manager.

3. Not Scoping Tokens

Requesting admin scope when only reports:read is needed violates Least Privilege.

4. Storing Tokens Without Expiry Handling

The token expires. Check expires_in and request a new one proactively.

5. Ignoring Token Endpoint Security

The token endpoint must be protected with HTTPS and Rate Limiting.

Practice Questions

  1. What grant type is used for machine-to-machine auth?
  2. How does the client authenticate to the token endpoint?
  3. What is the purpose of scopes in Client Credentials?
  4. Why should Client Credentials not be used for user-specific actions?
  5. How do you handle token expiry with Client Credentials?

Answers:

  1. Client Credentials grant (grant_type=client_credentials).
  2. Using client_id and client_secret in the POST body or HTTP Basic Auth header.
  3. Scopes limit what the token can do (e.g., reports:read). Request minimal scopes.
  4. Client Credentials identifies the application. There is no user context. User-specific actions need Authorization Code or ROPC.
  5. Simply request a new token when the old one expires. Since no user is involved, there is no refresh token — just get a new one.

Challenge: Build a microservice that authenticates to another service using Client Credentials, caches the token, and automatically refreshes before expiry. Handle 401 responses by requesting a new token.

FAQ

Can Client Credentials be used with mobile apps?

No. Mobile apps cannot keep secrets. A client secret extracted from a mobile binary can be used to obtain tokens.

What happens if a client secret is compromised?

Rotate the secret immediately. All existing tokens remain valid until they expire.

Does Client Credentials support refresh tokens?

Typically no. Request a new token when the current one expires. Some providers issue refresh tokens for long-lived processes.

How long should Client Credentials tokens live?

1 hour is standard. Shorter (15 minutes) for higher security. Longer for high-throughput services.

Is Client Credentials the same as API keys?

No. Client Credentials uses OAuth2 with scopes and short-lived tokens. API keys are static and simpler but less flexible.

Mini Project

Build a Python service that authenticates to a mock API using Client Credentials, caches the token, automatically refreshes before expiration, and handles 401 responses by requesting a new token.

What's Next

Now learn about the Resource Owner Password Credentials Grant for trusted first-party apps.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro