Skip to main content

Machine-to-machine: Auth with Logto

note

This guide assumes you have created an Application of type "Machine-to-machine" in Admin Console.

Intro

Machine-to-machine (M2M) is a common practice to authenticate if you have an app (not user) that needs to directly talk to resources (usually, using M2M app doesn't need user interactions, so it has no UI). E.g., an API service that updates users' custom data in Logto, a statistic service that pulls daily orders, etc.

Since Logto uses RBAC as its access control policy, assigning M2M roles to M2M apps is necessary for protecting your API which needs direct service talk.

info

To learn our current RBAC and the difference between user role and M2M role, see Manage permissions and roles to learn more

There are two common use cases of using machine-to-machine apps in Logto:

  1. Accessing Logto Management API: In this case, you need to assign a M2M role that include the all permission from the built-in Logto Management API to your M2M app.
  2. Accessing your API resource: In this case, you need to assign M2M roles that include permissions from your API resources to your M2M app.

During the M2M app creation process, you’ll be directed to a page where you can assign M2M roles to your applications:

Assign M2M roles modal

Or you can also assign these roles on the M2M app detail page when you already have an M2M app created:

Assign M2M roles page

Now, let’s walk through the end-to-end process. For clarity, we will separate the steps for accessing Logto Management API and other API resources. And we assume you have already created an M2M app in Logto.

Fetch an access token

Basics about access token request

M2M app makes a POST request to the token endpoint to fetch an access token by adding the following parameters using the application/x-www-form-urlencoded format in the HTTP request entity-body:

  • grant_type: Must be set to client_credentials
  • resource: The resource you want to access
  • scope: The scope of the access request

And you also need to include your M2M app's credentials in the request header for the token endpoint to authenticate your M2M app.

This is achieved by including the app's credentials in the Basic authentication form in the request Authorization header, where username is the App ID, and password is the App Secret.

You can find the App ID and App Secret from your M2M app's details page:

App ID and App Secret

An example of the access token request is:

POST /oidc/token HTTP/1.1
Host: your.logto.endpoint
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&resource=https://shopping.api
&scope=read:products write:products

Request an access token

note

In the following demonstration, replace https://your.logto.endpoint with the Logto endpoint you are targeting. For Logto Cloud, it will be https://{your-tenant-id}.logto.app.

Logto provides a built-in “Logto Management API” resource, it’s a readonly resource with the all permission to access Logto Management API, you can see it from your API resource list. The resource API indicator is in the pattern of https://{your-tenant-id}.logto.app/api , and this will be your resource value used in the access token request body.

Logto Management API details

Before accessing Logto Management API, make sure your M2M app has been assigned with M2M roles that include the all permission from this built-in “Logto Management API” resource.

info

Logto also provides a pre-configured “Logto Management API access” M2M role for new created tenants, which the Logto Management API resource’s all permission has already assigned to. You can use it directly without manually setting permissions. This pre-configured role can also be edited and deleted as needed.

Now, compose all we have and send the request:

const logtoEndpoint = 'https://your.logto.endpoint'; // Replace with your Logto endpoint
const tokenEndpoint = `${logtoEndpoint}/oidc/token`;
const applicationId = 'your-application-id';
const applicationSecret = 'your-application-secret';
const tenantId = 'your-tenant-id';

const fetchAccessToken = async () => {
return await fetch(tokenEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Basic ${Buffer.from(`${applicationId}:${applicationSecret}`).toString(
'base64'
)}`,
},
body: new URLSearchParams({
grant_type: 'client_credentials',
resource: `https://${tenantId}.logto.app/api`,
scope: 'all',
}).toString(),
});
};
caution

For Logto Cloud users: when you’re interacting with Logto Management API, you can not use custom domain, use the default Logto endpoint https://{your_tenant_id}.logto.app/oidc/token to grant access tokens.

Access token response

A successful access response body would be like:

{
"access_token": "eyJhbG...2g", // Use this token for accessing the Logto Management API
"expires_in": 3600, // Token expiration in seconds
"token_type": "Bearer", // Auth type for your request when using the access token
"scope": "all" // scope `all` for Logto Management API
}
note

Logto does not currently support the M2M app to represent a user. The sub in the access token payload will be the App ID.

Access resource using access token

You may notice the token response has a token_type field, which it's fixed to Bearer.

Thus you should put the access token in the Authorization field of HTTP headers with the Bearer format (Bearer YOUR_TOKEN) when you're interacting with your API resource server.

Using the requested access token with the built-in Logto Management API resource https://[your-tenant-id].logto.app/api to get all applications in Logto:

const logtoEndpoint = 'https://your.logto.endpoint'; // Replace with your Logto endpoint
const accessToken = 'eyJhb...2g'; // Access Token

const fetchLogtoApplications = async () => {
return await fetch(`${logtoEndpoint}/api/applications`, {
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
};

Authentication

If you are protecting your own API Resources other than Logto Management API, remember to implement the authentication for your resource. See Protect your API for details.