-
Notifications
You must be signed in to change notification settings - Fork 590
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
119 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
--- | ||
title: Machine-to-Machine Requests | ||
description: Learn how to use machine tokens to make and verify authenticated requests. | ||
--- | ||
|
||
## Introduction | ||
|
||
Machine-to-machine (M2M) authentication allows services, scripts, or devices to securely communicate with each other without the need for a user's session. | ||
|
||
For example, you might need machine tokens for: | ||
|
||
- Cron jobs that update your database | ||
- Background workers processing queued tasks | ||
- Microservices communicati\@ng with each other | ||
|
||
## Creating Machine Requests | ||
|
||
If your client is a backend service, you can create a [machine token](/docs/machine-requests/machine-tokens) and use it in the `Authorization` header of outgoing request. | ||
|
||
### Creating requests with the JavaScript Backend SDK | ||
|
||
Use the `clerkClient.machineTokens` object to create a [machine token](/docs/machine-requests/machine-tokens), then use the created token to make authenticated requests. | ||
|
||
> [!WARNING] | ||
> Creating machine tokens is subject to the [Backend API rate limits](/docs/backend-requests/resources/rate-limits) | ||
```tsx | ||
import { createClerkClient } from '@clerk/backend' | ||
|
||
export default async function cronJob() { | ||
const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY }) | ||
|
||
const { token } = await clerkClient.machineTokens.create({ | ||
machineId: 'mch_cron', | ||
claims: { | ||
permissions: ['read', 'write'], | ||
}, | ||
expiresInSeconds: 60, | ||
}) | ||
|
||
await fetch('https://api.example.com/cron', { | ||
method: 'POST', | ||
headers: { | ||
Authorization: `Bearer ${token}`, | ||
}, | ||
body: JSON.stringify({ | ||
message: 'Hello World!', | ||
}), | ||
}) | ||
} | ||
``` | ||
|
||
## Verifying Machine Requests | ||
|
||
For a machine request to be valid, it must include a valid [machine token](/docs/machine-requests/machine-tokens) in the Bearer `Authorization` header. | ||
|
||
You can verify machine tokens in two ways: | ||
|
||
1. Using Clerk's Backend SDK (recommended) | ||
1. Manually verifying the JWT using your instance's public key. | ||
|
||
### Verifying requests with the JavaScript Backend SDK | ||
|
||
#### Using the `authenticateRequest()` method | ||
|
||
You can use the `authenticateRequest()` method with the [JavaScript Backend SDK](/docs/references/backend/overview) to verify that the token is a valid machine token generated by Clerk. | ||
|
||
```tsx | ||
import { createClerkClient } from '@clerk/backend' | ||
|
||
export async function GET(req: Request) { | ||
const clerkClient = createClerkClient({ | ||
secretKey: process.env.CLERK_SECRET_KEY, | ||
publishableKey: process.env.CLERK_PUBLISHABLE_KEY, | ||
}) | ||
|
||
const { isMachineAuthenticated, machineId } = await clerkClient.authenticateRequest(req, { | ||
entity: 'machine', | ||
}) | ||
|
||
if (!isMachineAuthenticated) { | ||
return Response.json({ status: 401 }) | ||
} | ||
|
||
return Response.json({ | ||
message: `Machine is authenticated with ID: ${machineId}`, | ||
}) | ||
} | ||
``` | ||
|
||
#### Using the `await auth()` Next.js helper | ||
|
||
You can use the `await auth()` Next.js helper to verify that the request is authenticated and that the user is a machine. | ||
|
||
NOTE FOR REVIEWER: | ||
|
||
> [!NOTE] | ||
> Currently the `auth()` helper does not support **any** parameters, adding the `entity` paramter would be a big change to the sdk. | ||
> I think we can add this and default to `entity: 'user'` -- but I am not confident here, so we probably want some back and forth on this. | ||
> Also, in the Next.js `auth()` function, will it know that the token is in the Authorization header? Not the cookie? | ||
```tsx | ||
import { auth } from '@clerk/nextjs/server' | ||
|
||
export async function GET() { | ||
const { isMachineAuthenticated, machineId } = await auth({ entity: 'machine' }) | ||
|
||
if (!isMachineAuthenticated) { | ||
return new Response('Machine authentication failed.', { status: 401 }) | ||
} | ||
|
||
return new Response(`Machine is authenticated with ID: ${machineId}`, { status: 200 }) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters