How to Use Client Credentials Flow (Machine-to-Machine, M2M) with Fabrixly-IDS

Overview

The Client Credentials Flow is for server-to-server (machine-to-machine, M2M) communication—no user involved! Your server authenticates with Fabrixly-IDS using client ID and secret to get an access token for APIs!

Step 1: Configure M2M Client

First, set up a client for client credentials flow!

Admin Console Setup

  1. Go to Fabrixly-IDS Admin ConsoleClients
  2. Click Create Client → fill in details:
    • Client Name: "My M2M Client"
    • Response Types: Leave empty or add "token" (optional)
    • Grant Types: add client_credentials
    • Token Endpoint Auth Method: choose client_secret_basic or client_secret_post
  3. Save! Note your client ID and secret!

API Setup

Authenticating API Requests

Management API endpoints (like /api/clients, /api/users, etc.) require administrative authentication. To call them:

  1. Include the Token in the Authorization Header: Add -H "Authorization: Bearer <your-admin-jwt-token>" to your API calls.

Obtain an Admin JWT Token:

curl -X POST https://ids.fabrixly.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@example.com",
    "password": "your-admin-password"
  }'

Note: This returns a JSON response containing a token.

curl -X POST https://ids.fabrixly.com/api/clients \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <your-admin-jwt-token>" \
  -d '{
    "client_name": "M2M Client",
    "grant_types": ["client_credentials"],
    "response_types": [],
    "token_endpoint_auth_method": "client_secret_basic",
    "scope": "api:read api:write"
  }'

Step 2: Get Access Token via Client Credentials

To get an access token, send a POST request to the token endpoint:

Example 1: Using curl

curl -X POST https://ids.fabrixly.com/oidc/token \
  -u "your-client-id:your-client-secret" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&scope=api:read"

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "api:read"
}

Example 2: Using Node.js

Create m2m-app.js:

const fetch = require('node-fetch');
const { URLSearchParams } = require('url');

const TOKEN_URL = 'https://ids.fabrixly.com/oidc/token';
const CLIENT_ID = 'your-client-id';
const CLIENT_SECRET = 'your-client-secret';
const SCOPE = 'api:read api:write';

async function getAccessToken() {
  const params = new URLSearchParams();
  params.append('grant_type', 'client_credentials');
  params.append('scope', SCOPE);
  
  const credentials = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64');
  
  const response = await fetch(TOKEN_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': `Basic ${credentials}`
    },
    body: params
  });
  
  const tokenData = await response.json();
  return tokenData;
}

async function callApi(accessToken) {
  // Call your API with the access token
  const apiResponse = await fetch('https://ids.fabrixly.com/api/some-endpoint', {
    headers: { 'Authorization': `Bearer ${accessToken}` }
  });
  return apiResponse.json();
}

// Use it
getAccessToken().then(async (tokenData) => {
  console.log('Access Token:', tokenData.access_token);
  const apiResult = await callApi(tokenData.access_token);
  console.log('API Result:', apiResult);
}).catch(err => console.error('Error:', err));

Example 3: Using openid-client

const { Issuer } = require('openid-client');

async function main() {
  const issuer = await Issuer.discover('https://ids.fabrixly.com/oidc');
  const client = new issuer.Client({
    client_id: 'your-client-id',
    client_secret: 'your-client-secret'
  });
  
  const tokenSet = await client.grant({
    grant_type: 'client_credentials',
    scope: 'api:read api:write'
  });
  
  console.log('Access token:', tokenSet.access_token);
  console.log('Expires in:', tokenSet.expires_in);
}

main();

Step 3: Use Access Token to Call APIs

Once you have an access token, use it in the Authorization header for API calls:

GET https://ids.fabrixly.com/api/some-endpoint
Host: ids.fabrixly.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Scopes for M2M

Define scopes to control what your M2M client can do:

# Example scopes
SCOPE_READ=api:read
SCOPE_WRITE=api:write
SCOPE_ADMIN=api:admin

Token Expiry & Refresh

Client credentials flow tokens expire after some time (default: 3600 seconds, 1 hour). When a token expires, just request a new one!

Security Best Practices

  1. Keep Client Secret Secure: Never expose client secret in frontend code!
  2. Rotate Secrets: Regularly rotate client secrets!
  3. Limit Scopes: Only grant the scopes your M2M client actually needs!
  4. Use Short-Lived Tokens: Prefer short expiry for access tokens!
  5. Use HTTPS Always: Never send credentials over unencrypted connections!

Troubleshooting

  • "Invalid client" error: Check client ID and secret are correct!
  • "Unauthorized client": Ensure client has client_credentials grant type enabled!
  • "Invalid scope": Make sure requested scopes are allowed for your client!

Use Cases for M2M Flow

  • Cron jobs that call APIs
  • Backend services talking to each other
  • IoT devices authenticating to cloud APIs
  • Scripts that need API access

Next Steps

  • Define custom scopes for your APIs
  • Implement token caching for M2M tokens

Subscribe to The Fabrixly Blog

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe