← Return to Pantheon
👑

Machinus, The Machine Herald

Master of Machine-to-Machine Divine Authority

Essential Flow

"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

Application

POST /token with client_id, client_secret, grant_type=client_credentials, scope

Auth Server

Divine Commentary: No mortals here! The machines speak directly to me with their sacred credentials!

Auth Server

Validates client credentials

Auth Server

Divine Commentary: I verify the machine's identity. Is it truly who it claims to be?

Auth Server

Returns access_token and token metadata

Application

Divine Commentary: The machine is authenticated! I grant the token of divine authority!

Application

Requests resources with Bearer token

Resource Server

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

🔐
Auth Server
🖥️
Service
🟩 Back-channel
1

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.

2

Request Access Token

3

Cache Token

4

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 Implementationjavascript
// 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

Microservices Communication

Service A needs to call Service B without user involvement

Background Jobs & Cron Tasks

Scheduled tasks that run without user interaction

CLI Tools & Scripts

Command-line applications authenticating as themselves

IoT Devices & Daemons

Automated systems that operate independently

User-Delegated Access

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