How to Set Up API Authentication with Access Tokens in Logto: A Complete Guide

Logto implements standard OAuth 2.0 client-credentials flow for machine-to-machine API authentication, automatically caching access tokens and refreshing them 60 seconds before expiry via the @logto/api SDK.

Setting up API authentication with access tokens in Logto enables secure server-to-server communication with the Management API. The logto-io/logto repository provides a dedicated TypeScript SDK (@logto/api) that abstracts the token exchange, caching, and renewal logic. This guide walks through creating machine-to-machine credentials, configuring the SDK, and making authenticated requests using source-accurate implementation details.

Prerequisites

Install the official Logto API SDK to handle token management and API client instantiation.

npm install @logto/api

Understanding the OAuth 2.0 Client Credentials Architecture

Logto’s core OIDC provider implements a custom client_credentials grant handler located at packages/core/src/oidc/grants/client-credentials.ts. This supports both standard access tokens and organization-scoped tokens for multi-tenant scenarios.

The SDK abstracts this complexity through two primary components:

  • ClientCredentials class (packages/api/src/client-credentials.ts): Manages token requests, validates JSON responses, caches tokens, and handles automatic refresh with a default 60-second leeway before expiry.
  • createManagementApi helper: Wraps the ClientCredentials instance to expose a typed apiClient for CRUD operations on Logto resources.

When initialized, the SDK posts a URL-encoded request to /oidc/token with grant_type=client_credentials, retrieves an opaque access token, and stores it in memory for subsequent requests.

Step 1: Create a Machine-to-Machine Application

Before writing code, configure the credentials in the Logto Console:

  1. Navigate to Applications and create a new Machine-to-Machine application.
  2. Grant the application permissions to the Management API (select scopes like all or specific resource permissions).
  3. Copy the generated client ID and client secret—these authenticate your SDK instance.

Step 2: Implement the Authentication Flow

Choose the implementation pattern based on your deployment type (Logto Cloud vs. self-hosted).

Using the Management API SDK with Logto Cloud

For Logto Cloud deployments, provide your tenant ID and M2M credentials to createManagementApi. The SDK automatically targets the correct token endpoint and API base URL.

import { createManagementApi } from '@logto/api/management';

const { apiClient } = createManagementApi('your-tenant-id', {
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
});

// Example: Fetch all users
const response = await apiClient.GET('/api/users');
console.log('Users:', response.data);

The apiClient automatically injects the Authorization: Bearer <token> header using the cached access token from the internal ClientCredentials instance.

Self-Hosted Configuration

For open-source deployments, explicitly define the baseUrl and apiIndicator to point to your Logto instance.

import { createManagementApi } from '@logto/api/management';

const { apiClient } = createManagementApi('default', {
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  baseUrl: 'https://logto.example.com',
  apiIndicator: 'https://logto.example.com/api',
});

// Create an application via Management API
await apiClient.POST('/api/applications', {
  json: { 
    name: 'My App', 
    redirectUris: ['https://app.example.com/callback'] 
  },
});

Direct ClientCredentials Usage

For custom HTTP clients or non-standard implementations, instantiate the ClientCredentials class directly from packages/api/src/client-credentials.ts.

import { ClientCredentials } from '@logto/api/src/client-credentials';

const credentials = new ClientCredentials({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  tokenEndpoint: 'https://logto.example.com/oidc/token',
});

// Retrieve cached token (fetches new if expired or not present)
const token = await credentials.getAccessToken();

// Use with any HTTP client
await fetch('https://logto.example.com/api/users', {
  headers: { Authorization: `Bearer ${token.value}` },
});

The getAccessToken() method constructs the token request body as:

grant_type=client_credentials&
client_id=YOUR_CLIENT_ID&
client_secret=YOUR_CLIENT_SECRET

Optional parameters like scope or resource can be passed via the tokenParams constructor option.

How Token Caching and Automatic Refresh Works

The ClientCredentials class in packages/api/src/client-credentials.ts implements an in-memory token cache. When getAccessToken() is called, the SDK checks the cached token’s expiry timestamp. If the token expires within 60 seconds (the default leeway), the SDK automatically requests a new token before returning the value.

This eliminates race conditions in high-throughput scenarios and ensures API calls never use expired tokens. The SDK handles network errors and OIDC error responses according to RFC 6749 specifications.

Summary

  • API authentication with access tokens in Logto relies on the OAuth 2.0 client-credentials flow implemented in packages/core/src/oidc/grants/client-credentials.ts.
  • The @logto/api SDK provides the ClientCredentials class (packages/api/src/client-credentials.ts) to handle token acquisition, caching, and automatic refresh with a 60-second leeway.
  • Use createManagementApi for typed Management API access, or instantiate ClientCredentials directly for custom HTTP implementations.
  • Always send access tokens in the Authorization: Bearer <token> header when calling Logto Management API endpoints.

Frequently Asked Questions

What is the default token expiry leeway in the Logto SDK?

The ClientCredentials class refreshes tokens 60 seconds before their actual expiry by default. This prevents authentication failures due to clock skew or network latency during request transmission.

Can I use the access token with custom HTTP clients instead of the SDK?

Yes. While the createManagementApi helper provides convenient typed methods, you can extract the raw token via credentials.getAccessToken() from the ClientCredentials class and use it with fetch, axios, or any HTTP library by setting the Authorization: Bearer <token> header manually.

Does Logto support organization-scoped access tokens for the Management API?

Yes. According to the implementation in packages/core/src/oidc/grants/client-credentials.ts, Logto extends the standard OAuth 2.0 client-credentials grant to support organization-scoped tokens. Pass the organization_id parameter via tokenParams when constructing the ClientCredentials instance to receive tokens scoped to specific organizations.

Where are the M2M application credentials stored in the Logto system?

The client ID and client secret are generated when you create a Machine-to-Machine application in the Logto Console. These credentials are stored in Logto's database and validated against the OIDC token endpoint at /oidc/token when the SDK requests an access token.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →