/
Contact usSee pricingStart building
Node
​

    About Stytch

    Introduction
    Integration Approaches
      Full-stack overview
      Frontend (pre-built UI)
      Frontend (headless)
      Backend
    Migrations
      Migration overview
      Migrating users statically
      Migrating users dynamically
      Additional migration considerations
      Zero-downtime deployment
      Defining external IDs for users
      Exporting from Stytch
    Custom Domains
      Overview

    Authentication

    DFP Protected Auth
      Overview
      Setting up DFP Protected Auth
      Handling challenges
    Magic Links
    • Email Magic Links

      • Getting started with the API
        Getting started with the SDK
        Replacing your password reset flow
        Building an invite user flow
        Add magic links to an existing auth flow
        Adding PKCE to a Magic Link flow
        Magic Link redirect routing
    • Embeddable Magic Links

      • Getting started with the API
    MFA
      Overview
      Backend integration
      Frontend integration
    Mobile Biometrics
      Overview
    M2M Authentication
      Authenticate an M2M Client
      Rotate client secrets
      Import M2M Clients from Auth0
    OAuth
    • Identity providers

      • Overview
        Provider setup
      Getting started with the API (Google)
      Add Google One Tap via the SDK
      Email address behavior
      Adding PKCE to an OAuth flow
    Connected AppsBeta
      Setting up Connected Apps
      About Remote MCP Servers
    • Resources

      • Integrate with AI agents
        Integrate with MCP servers
        Integrate with CLI Apps
    Passcodes
      Getting started with the API
      Getting started with the SDK
    • Toll fraud

      • What is SMS toll fraud?
        How you can prevent toll fraud
      Unsupported countries
    Passkeys & WebAuthn
    • Passkeys

      • Passkeys overview
        Set up Passkeys with the frontend SDK
    • WebAuthn

      • Getting started with the API
        Getting started with the SDK
    Passwords
      Getting started with the API
      Getting started with the SDK
      Password strength policy
    • Email verification

      • Overview
        Email verification before password creation
        Email verification after password creation
    Sessions
      How to use sessions
      Backend integrations
      Frontend integrations
      Custom claims
      Custom claim templates
      Session tokens vs JWTs
      How to use Stytch JWTs
    TOTP
      Getting started with the API
      Getting started with the SDK
    Web3
      Getting started with the API
      Getting started with the SDK

    Authorization

    Implement RBAC with metadata

    3rd Party Integrations

    Planetscale
    Supabase
    Feathery
    Unit

    Testing

    E2E testing
    Sandbox values
Get support on SlackVisit our developer forum

Contact us

Consumer Authentication

/

Guides

/

Authentication

/

M2M Authentication

/

Authenticate an M2M Client

Authenticate an M2M Client

Stytch's M2M Authentication enables your services to communicate and authenticate without any human involvement. Use our M2M Auth API to create clients, retrieve access tokens, and define permissions with scopes to securely communicate between machines.

In this guide, you'll learn how to create and authenticate an M2M Client. By the end, you'll have:

  • Created an M2M Client.
  • Issued an access_token.
  • Authenticated the M2M Client by validating the access_token.
  • Deactivated or deleted an M2M Client.

Before you start

In order to complete this guide, you'll need the following:

  • A Stytch project (either Consumer or B2B). If you don't have one already, in the Dashboard, click on your existing project name in the top left corner of the Dashboard, click Create a new project, and then select B2B Authentication or Consumer Authentication.
  • The project Test environment's project_id and secret from the API keys section. You'll need to pass these values into the Authorization request header for most Stytch API calls.

Step 1: Create an M2M Client

An M2M (machine-to-machine) client represents a machine identity. To create one, call the Create M2M Client endpoint and provide optional attributes like client_name, client_description, scopes, and trusted_metadata that describe the client use case.

If you prefer, you also have a UI option for creating M2M Clients in the Dashboard. For the purposes of this guide, we'll be using the API.

curl --request POST \
	--url https://test.stytch.com/v1/m2m/clients \
	-u 'PROJECT_ID:SECRET' \
	-H 'Content-Type: application/json' \
	-d '{
		"client_name": "Example client",
		"client_description": "Following the Stytch guide.",
		"scopes": ["read:settings", "write:settings"],
		"trusted_metadata": {
			"billing_tier": "standard",
			"api_version": "v2"
		}
	}'

After a successful API call, the response will look like this.

{
	"m2m_client": {
		"client_description": "Following the Stytch guide.",
		"client_id": "m2m-client-test-a50053...",
		"client_name": "Example client",
		"client_secret": "FXvejQZKicBl7Lq...QqNU",
		"client_secret_last_four": "QqNU",
		"next_client_secret_last_four": null,
		"scopes": [
			"read:settings",
			"update:settings"
		],
		"status": "active",
		"trusted_metadata": {
			"billing_tier": "standard",
			"api_version": "v2"
		}
	},
	"request_id": "request-id-test-c50eb06f-69b4-41be-8640-0d9fd2f561ae",
	"status_code": 200
}

Important: This is the only time you will be able to view the generated client_secret in the API response. Stytch stores a hash of the client_secret and cannot recover the value if lost. Be sure to persist the client_secret in a secure location. If the client_secret is lost, you will need to trigger a secret rotation flow to receive another one.

Step 2: Call the Get Access Token endpoint.

After creating an M2M client, you'll need to issue and retrieve an access token.

Call the Get Access Token endpoint and provide the following parameters in the request body and URL path:

  • project_id from the Basic Auth header in Step 1
  • client_secret from the response in Step 1
  • client_id from the response in Step 1
  • grant_type set to the value "client_credentials"
curl --request POST \
	--url https://test.stytch.com/v1/public/PROJECT_ID/oauth2/token \
	-H 'Content-Type: application/json' \
	-d '{
		"client_id": "m2m-client-test-a50053..",
		"client_secret": "FXvejQZKicBl7Lq...QqNU",
		"grant_type": "client_credentials"
	}'

The response will contain the access_token, a JWT signed with your project's JWKS. The lifespan of the access_token is one hour.

{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "access_token": "eyJ...",
    "token_type": "bearer",
    "expires_in": 3600
}

Step 3: Authenticate the access token

At this point, the M2M Client you've created from Step 1 will communicate with your services with the issued access_token from Step 2.

Your services will need to authenticate the access_token locally with one of Stytch's backend SDKs (available in Node, Python, Go, and Ruby). You can also alternatively use a library that supports JWT signature validation.

Using the backend Node SDK as an example, your services will call the Authenticate Access Token method with the provided access_token.

As an option for enforcing permissions, you can also specify required_scopes the access_token must contain in order to be valid: any missing scope will return an error.

const stytch = require('stytch');

// Note if you're using B2B you'll want to call new stytch.B2BClient
const client = new stytch.Client({
  project_id: 'PROJECT_ID',
  secret: 'SECRET',
});

const params = {
  access_token: 'eyJ...',
  required_scopes: ['write:settings'],
};

client.m2m
  .authenticateToken(params)
  .then((resp) => {
    console.log(resp);
  })
  .catch((err) => {
    console.log(err);
  });

A successful response will contain the M2M Client's client_id, scopes, and custom_claims (Check out our using custom claim templates guide to learn how to pass customized claims to every issued JWT for M2M Clients).

{
    "client_id": "m2m-client-test-a50053....",
    "scopes": ["read:settings","write:settings"],
    "custom_claims": {}
}

At this point, the M2M Client has successfully been authenticated.

Step 4: Deactivate or delete the M2M Client

If the M2M Client needs to be deactivated, call the Update M2M Client endpoint and set the status to inactive, which will prevent the M2M Client from receiving new access tokens.

curl --request POST \
	--url https://test.stytch.com/v1/m2m/clients/m2m-client-test-d73... \
	-u 'PROJECT_ID:SECRET' \
	-H 'Content-Type: application/json' \
	-d '{
		"status": "inactive"
	}'

M2M Clients can be reactivated by setting the status to active.

If the M2M Client needs to be deleted, call the Delete M2M Client endpoint.

curl --request DELETE \
	--url https://test.stytch.com/v1/m2m/clients/m2m-client-test-d73... \
	-u 'PROJECT_ID:SECRET'

Important: Deactivating or deleting an M2M Client will not invalidate any existing JWTs issued to the client, only prevent it from receiving new ones.

What's next

Keep your M2M Clients' identities secure and learn how to rotate client secrets.

Also, take a look at our comprehensive M2M Authentication example app tutotrial, which includes an open-source GitHub repo utilizing the Node.js SDK.

Before you start

Step 1: Create an M2M Client

Step 2: Call the Get Access Token endpoint.

Step 3: Authenticate the access token

Step 4: Deactivate or delete the M2M Client

What's next