Machinus, The Machine Herald
Master of Machine-to-Machine Divine Authority
"I am Machinus! Herald of the Machine Age! Where mortals are not needed, I reign supreme! Services speak unto services, APIs commune with APIs, and no user shall interrupt these sacred exchanges! Your microservices, your cron jobs, your background workers—all shall bow before me!"
Mortal Translation
The Client Credentials flow is designed for machine-to-machine (M2M) authentication where no user is involved. Your service authenticates itself directly to the authorization server using its client ID and secret, then receives an access token to call other APIs. This is perfect for backend services, cron jobs, daemons, and microservices that need to communicate with each other.
The Machine's Sacred Exchange
POST /token with client_id, client_secret, grant_type=client_credentials, scope
Divine Commentary: No mortals here! The machines speak directly to me with their sacred credentials!
Validates client credentials
Divine Commentary: I verify the machine's identity. Is it truly who it claims to be?
Returns access_token and token metadata
Divine Commentary: The machine is authenticated! I grant the token of divine authority!
Requests resources with Bearer token
Divine Commentary: Armed with my blessing, the machine may now access the sacred resources!
⚡ Interactive Flow Simulator
Experience the Authorization Code flow step-by-step with visual animations
Flow Visualization
Configure Service Credentials
Your service has client_id and client_secret from the OAuth provider
🔒 Store credentials securely using environment variables or secrets managers. Never commit secrets to version control.
Request Access Token
Cache Token
Access Protected API
The Divine Purpose
Machinus speaks: "When your backend service needs to call another API without a user being present, you call upon ME! No redirects, no browser ceremonies, no mortal involvement—just pure machine authentication!"
In mortal terms: This flow is for automated systems, background jobs, CLI tools, and server-to-server communications. The client acts on its own behalf, not on behalf of a user. Think microservices, scheduled tasks, or daemon processes.
The Sacred Ritual
Step 1: Authenticate
Your service makes a POST request to the token endpoint withgrant_type=client_credentials
, along with yourclient_id
andclient_secret
.
Step 2: Receive Token
The authorization server validates your credentials and returns an access token. Note: No refresh token is typically provided since you can always request a new token using your credentials.
Step 3: Use Token
Include the access token in the Authorization header when making API requests. Cache the token and reuse it until it expires to reduce unnecessary token requests.
Ancient Wisdom (Best Practices)
- ✓Cache tokens until expiry - Don't request a new token for every API call; respect rate limits
- ✓Store credentials securely - Use environment variables, secrets managers (AWS Secrets Manager, HashiCorp Vault)
- ✓Request minimal scopes - Only ask for permissions your service actually needs
- ✓Rotate credentials regularly - Implement credential rotation policies
- ✓Monitor token usage - Log authentication events and detect anomalies
- ✓Handle expiration gracefully - Implement retry logic with exponential backoff
Forbidden Arts (Common Mistakes)
- ✗Using this flow with user context - If you need user permissions, consult Codeus instead
- ✗Exposing client_secret in frontend code - This flow is ONLY for backend services
- ✗Hardcoding credentials - Never commit secrets to version control
- ✗Requesting new token for every request - Cache and reuse tokens until they expire
- ✗Ignoring token expiration - Always check expires_in and refresh proactively
The Mortal's Guide to Implementation
// Client Credentials Flow Implementation
// This code runs on your backend server/service ONLY
async function getAccessToken() {
const tokenUrl = 'https://auth-server.com/oauth/token';
// Prepare credentials
const credentials = {
grant_type: 'client_credentials',
client_id: 'your-service-client-id',
client_secret: 'your-service-client-secret',
scope: 'api.read api.write' // Request specific scopes
};
try {
const response = await fetch(tokenUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
// Some servers prefer Basic Auth:
// 'Authorization': `Basic ${Buffer.from(`${client_id}:${client_secret}`).toString('base64')}`
},
body: new URLSearchParams(credentials)
});
if (!response.ok) {
throw new Error(`Token request failed: ${response.status}`);
}
const tokens = await response.json();
// tokens = { access_token, token_type, expires_in, scope }
return tokens;
} catch (error) {
console.error('Failed to obtain access token:', error);
throw error;
}
}
// Use the token to access protected resources
async function callProtectedAPI(accessToken) {
const response = await fetch('https://api.example.com/data', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}
return response.json();
}
// Example: Token caching for efficiency
class TokenManager {
constructor() {
this.token = null;
this.expiresAt = null;
}
async getValidToken() {
// Check if we have a valid cached token
if (this.token && this.expiresAt && Date.now() < this.expiresAt) {
return this.token;
}
// Fetch new token
const tokenData = await getAccessToken();
this.token = tokenData.access_token;
// Set expiration with 5 minute buffer
const expiresIn = tokenData.expires_in || 3600;
this.expiresAt = Date.now() + (expiresIn - 300) * 1000;
return this.token;
}
}
// Usage example
const tokenManager = new TokenManager();
async function performBackgroundJob() {
try {
const token = await tokenManager.getValidToken();
const data = await callProtectedAPI(token);
console.log('Job completed:', data);
} catch (error) {
console.error('Job failed:', error);
}
}
When to Consult Machinus
Service A needs to call Service B without user involvement
Scheduled tasks that run without user interaction
Command-line applications authenticating as themselves
Automated systems that operate independently
If you need to act on behalf of a user, consult Codeus or the PKCE Guardian
⚠️ Security Warning from Machinus
Critical: The client credentials flow grants access based on the service's identity, NOT a user's identity. Tokens obtained through this flow have the permissions of the service itself.
This means:
- Never use this flow for user-specific operations
- Services have broad permissions—apply the principle of least privilege
- If client_secret is compromised, an attacker gains full service access
- Implement IP whitelisting and other network-level controls when possible
Consult Also With
⚡ Codeus - For web applications requiring user authorization
🛡️ PKCE Guardian - For mobile and single-page applications with user involvement
Divine Decree: RFC 6749 Section 4.4