diff --git a/docs/machine-requests/machine-requests.mdx b/docs/machine-requests/machine-requests.mdx new file mode 100644 index 0000000000..3dbf300186 --- /dev/null +++ b/docs/machine-requests/machine-requests.mdx @@ -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 }) +} +``` diff --git a/docs/machine-requests/machine-tokens.mdx b/docs/machine-requests/machine-tokens.mdx index 5dac13cf73..b960dbb303 100644 --- a/docs/machine-requests/machine-tokens.mdx +++ b/docs/machine-requests/machine-tokens.mdx @@ -15,7 +15,7 @@ Every machine token you create needs to be associated with a `machine_id`. You c - It must be prefixed with `mch_` - It must only contain lowercase letters and numbers -- It must be 255 characters or less +- It must be 96 characters or less > [!TIP] > It is a good idea to have the `machine_id` correspond with the identity of the service generating the token. For example if you have a cron service, a `machine_id` of `mch_cron` would make sense. @@ -60,10 +60,6 @@ Every generated token has default claims that cannot be overridden by custom cla - `nbf`: not before - the time before which the token is considered invalid, as a Unix timestamp. Determined using the **Allowed Clock Skew** request body parameter when creating machine tokens. See [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5) for more information. - `sub`: subject - the ID of the machine that created the token. Determined using the **Machine ID** request body parameter when creating machine tokens. For example: `mch_123`. See [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2) for more information. -## Making Machine Requests +## Using Machine Tokens to create and verify requests -To start making machine requests, refer to [making machine requests](/docs/machine-requests/making). - -## Validating Machine Tokens - -To learn how to manually verify a machine token, refer to [validating machine tokens](/docs/machine-requests/verifying). +To start using machine tokens to create and verify requests, refer to [making machine requests](/docs/machine-requests/machine-requests). diff --git a/docs/machine-requests/making.mdx b/docs/machine-requests/making.mdx deleted file mode 100644 index a9bd3af135..0000000000 --- a/docs/machine-requests/making.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Making Machine Requests -description: Lean about making machine-to-machine requests. ---- - -If your client is a backend service, you can create a [machine token](/docs/machine-requests/overview) and use it in the `Authorization` header of outgoing request. - -## Using the Node.js SDK - -The Node.js SDK has a `machineTokens` object that can be used to create machine tokens. - -> [!WARNING] -> Use of the Node.js SDK is still subject to the [Backend API rate limits](/docs/backend-requests/resources/rate-limits) - -```tsx -import { createClerkClient } from '@clerk/backend' - -export default function machineFetch() { - const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY }) - - // creates a token with no additional claims. - const { token } = await clerkClient.machineTokens.create({ - machineId: 'mch_cron', - claims: { - permissions: ['read', 'write'], - }, // custom claims customer's can add to their token - expiresInSeconds: 60, - }) - - const authenticatedFetch = async (...args) => { - return fetch(...args, { - headers: { Authorization: `Bearer ${await getToken()}` }, - }).then((res) => res.json()) - } - - return authenticatedFetch -} -``` - -## Using the Backend API reference - -You can also generate machine tokens by simply making a requests to Clerk's Backend API - -Go to the Backend API reference to learn more. **The API reference for this endpoint doesn't exist yet** diff --git a/docs/machine-requests/overview.mdx b/docs/machine-requests/overview.mdx deleted file mode 100644 index de13d145e5..0000000000 --- a/docs/machine-requests/overview.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Machine-to-Machine Authentication Overview -description: Learn about machine-to-machine authentication and how to implement it using Clerk. ---- - -## 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. - -## Why Use Machine-to-Machine Authentication? - -- **Automated Processes**: Services like cron jobs, background workers, or CI/CD pipelines often need to interact with your backend services. -- **Inter-Service Communication**: Microservices architectures require secure communication between different services within your infrastructure. -- **Device Authentication**: IoT devices or embedded systems may need to authenticate with backend services to send or receive data. - -## How Machine Tokens Work in Clerk - -In the context of Clerk, machine-to-machine authentication is facilitated through [machine tokens](/docs/machine-requests/machine-tokens), which are JSON Web Tokens (JWTs) specifically designed to represent the identity of a machine. - -These tokens allow you to [create machine requests](/docs/machine-requests/making) from one service, and [verify incoming machine requests](/docs/machine-requests/verifying) in another service. diff --git a/docs/machine-requests/verifying.mdx b/docs/machine-requests/verifying.mdx deleted file mode 100644 index c2c139bb6b..0000000000 --- a/docs/machine-requests/verifying.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Manual JWT Verification -description: Learn how to manually verify Clerk-generated session and machine tokens (JWTs). ---- - -## Verifying Tokens - -For every valid Clerk [machine request](/docs/machine-requests/overview), a [machine token](/docs/machine-requests/machine-tokens) will be present in the Bearer `Authorization` header. You must validate this token isn't expired and is authentic (i.e., no malicious user tried to tamper with it), which indicates that the machine is authenticated to your application. - -The `authenticateRequest()` method from the JavaScript Backend SDK handles these validations for you. It accepts the `request` object and authenticates the machine token in it. See the [reference page](/docs/references/backend/authenticate-request) for more information. - -### Machine Tokens - -Machine tokens authenticate machines. They are typically provided via the Authorization header in your backend requests. - -If the token is valid, it means that the machine is authenticated to your application. - -To authenticate machine requests using `authenticateRequest()`, specify the `entity` parameter as `'machine'`. See the [reference page](/docs/references/backend/authenticate-request) for more information. - -The following example uses 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, machinedId } = await clerkClient.authenticateRequest(req, { - entity: 'machine', - }) - - if (!authReq.isMachineAuthenticated) { - return Response.json({ status: 401 }) - } - - return Response.json({ - message: 'Machine is authenticated', - machineId, - }) -} -``` diff --git a/docs/manifest.json b/docs/manifest.json index 5f163f7009..ea97e3d1c0 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -770,20 +770,12 @@ "items": [ [ { - "title": "Overview", - "href": "/docs/machine-requests/overview" + "title": "Machine requests", + "href": "/docs/machine-requests/machine-requests" }, { "title": "Machine tokens", "href": "/docs/machine-requests/machine-tokens" - }, - { - "title": "Making machine requests", - "href": "/docs/machine-requests/making" - }, - { - "title": "Verifying machine requests", - "href": "/docs/machine-requests/verifying" } ] ]