Skip to content

Commit

Permalink
adding docs pages
Browse files Browse the repository at this point in the history
running prettier

removing redundant ids

a "valid" id was in fact - not valid

removing unneccessary "s"
  • Loading branch information
Ben2W committed Nov 21, 2024
1 parent ec0c475 commit d6aa27f
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 11 deletions.
54 changes: 48 additions & 6 deletions docs/backend-requests/handling/manual-jwt.mdx
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
---
title: Manual JWT verification
description: Learn how to manually verify Clerk-generated session tokens (JWTs).
title: Manual JWT Verification
description: Learn how to manually verify Clerk-generated session and machine tokens (JWTs).
---

Your Clerk-generated [session tokens](/docs/backend-requests/resources/session-tokens) are essentially JWTs which are signed using your instance's private key and can be verified using your instance's public key. Depending on your architecture, these tokens will be in your backend requests either via a cookie named `__session` or via the Authorization header.
## Verifying Tokens

For every request, you must validate its token to make sure it hasn't expired and it is authentic (i.e. no malicious user tried to tamper with it). If these validations pass, then it means that the user is authenticated to your application and you should consider them signed in.
Clerk-generated tokens, including [session tokens](/docs/backend-requests/resources/session-tokens) and [machine tokens](/docs/backend-requests/resources/machine-tokens), are JWTs signed using your instance's private key and can be verified using your instance's public key.

The `authenticateRequest()` method from the JavaScript Backend SDK does all of this for you. It accepts the `request` object and authenticates the session token in it. See the [reference page](/docs/references/backend/authenticate-request) for more information.
For every request, you must validate the token to ensure it hasn't expired and is authentic (i.e., no malicious user tried to tamper with it). If these validations pass, it means that the user or machine is authenticated to your application.

## Networkless token verification
The `authenticateRequest()` method from the JavaScript Backend SDK handles these validations for you. It accepts the `request` object and authenticates the token in it. See the [reference page](/docs/references/backend/authenticate-request) for more information.

### Session Tokens

Session tokens authenticate users. Depending on your architecture, these tokens will be in your backend requests either via a cookie named `__session` or via the Authorization header.

If the token is valid, you can consider the user signed in to your application.

#### Networkless token verification

{/* Note: this example is duped from /authenticate-request. Probably a good opportunity to use a partial here */}

Expand Down Expand Up @@ -38,3 +46,37 @@ export async function GET(req: Request) {
return Response.json({ message: 'This is a reply' })
}
```

### 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,
})
}
```
44 changes: 44 additions & 0 deletions docs/backend-requests/making/machine.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
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/backend-requests/resources/machine-tokens) and use it in the `Authorization` header of your 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**
17 changes: 12 additions & 5 deletions docs/backend-requests/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ title: Request authentication
description: Learn about various ways to make authenticated requests to the backend when using Clerk SDKs.
---

A request is considered “authenticated” when the backend can securely identify the user and device that is making the request. The reasons for making authenticated requests to the backend include:
A request is considered “authenticated” when the backend can securely identify the entity that is making the request. The reasons for making authenticated requests to the backend include:

- Associating the user with the action being performed
- Associating a user with the action being performed
- Associating a machine with the action being performed
- Ensuring the user has permission to make the request
- Keeping an audit log of which device the user is performing actions from

In order to authenticate the user on the backend using Clerk's SDK, the short-lived [session token](/docs/backend-requests/resources/session-tokens) needs to be passed to the server.
In order to authenticate a request on the backend using Clerk's SDK, a short-lived [session token](/docs/backend-requests/resources/session-tokens) or a [machine token](/docs/backend-requests/resources/machine-tokens) needs to be passed to the server.

## Frontend requests

Expand All @@ -27,7 +28,7 @@ For same-origin requests, refer to our guide on [making same-origin requests](/d

For cross-origin requests, refer to our guide on [making cross-origin requests](/docs/backend-requests/making/cross-origin).

## Backend requests
## Backend middleware

Clerk provides various middleware packages to set the session property for easy access. These packages can also require a session to be available on the current request. Choose the guide based on the language or framework you're using:

Expand All @@ -36,7 +37,13 @@ Clerk provides various middleware packages to set the session property for easy
- [Go](/docs/backend-requests/handling/go)
- [Ruby on Rails / Rack](/docs/backend-requests/handling/ruby-rails)

If there is not middleware available for your preferred language or framework, you can extract the session token manually.
If there is not middleware available for your preferred language or framework, you can extract the token manually.

### Machine

For machine requests, you need to create a machine token using Clerk's backend API. This token is similiar to a session token, but it allows you to authenticate backend requests without a user session. Include the machine token as a Bearer token in the `Authorization` header when making requests to your backend.

You can learn more about [creating machine tokens](/docs/backend-requests/resources/machine-tokens) and [handling machine tokens](/docs/backend-requests/handling/manual-jwt#authenticating-machine-tokens) for additional information

### Same-origin

Expand Down
74 changes: 74 additions & 0 deletions docs/backend-requests/resources/machine-tokens.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: Machine tokens
description: Learn about machine tokens and how to validate them in your backend.
---

When you want a machine to authenticate requests to your backend, you authorize the requests with machine tokens.

Machine tokens are JWTs that contain information about your machine.

## Customizing your machine tokens.

### Machine ID

Every machine token you create needs to be associated with a `machine_id`. You can pick any value for the `machine_id` as long as it meets the following requirements:

- It must be prefixed with `mch_`
- It must only contain lowercase letters and numbers

> [!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.
### Some **valid** machine\_ids

- mch\_cron
- mch\_pub\_sub
- mch\_scheduler
- mch\_device\_ada3f8b7\_d491\_4fe4\_b76e\_99e4c00b56d1

#### Some invalid machine\_ids

- user\_1234
- mch\_OH\_HI
- MCH\_123
- mch-123

### Claims

You can add custom claims to your machine token to include any additional information that your application might need. Claims are key-value pairs included in the token's payload, and they can convey important data such as permissions, roles, or any other attributes relevant to the machine's identity.

For example, it is a good practice to include any permissions that your service requires directly in the claims. This allows your backend to easily verify what actions the machine is authorized to perform.

> [!NOTE]
> You cannot add claims that are [already set by clerk](#default-machine-claims).
### Expires In Seconds

The `expiresInSeconds` parameter defines how long the machine token remains valid, specified in seconds. This parameter is optional and defaults to 60 seconds (1 minute).

If you need the machine token to be valid for a longer period of time, you can set the `expiresInSeconds` parameter to a higher value. However, keep in mind that longer-lived tokens can present a higher security risk if compromised, while shorter-lived tokens may require more frequent token generation, potentially impacting your [Backend API rate limits](/docs/backend-requests/resources/rate-limits). Therefore, it's important to balance token lifespan with security requirements and rate limit considerations.

### Clock Skew

The `allowedClockSkew` parameter provides a leeway in seconds to account for clock differences between servers. This setting affects the `nbf` (Not Before) claim in the token, calculated as `nbf = current_time - allowed_clock_skew`. The default value is 5 seconds.

Adjusting the clock skew helps prevent token validation failures due to minor time discrepancies between the issuing server and the verifying server.

## Default machine claims

Every generated token has default claims that cannot be overridden by custom claims. Clerk's default claims include:

- `exp`: expiration time - the time after which the token will expire, as a Unix timestamp. Determined using the **Token Expires In Seconds** request body parameter when creating machine tokens. See [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4) for more information.
- `iat`: issued at - the time at which the token was issued as a Unix timestamp. For example: `1516239022`. See [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6) for more information.
- `jti`: JWT ID - the ID of the token internally generated by Clerk. For example: `a1b2c3d4e5f67890abcd`. See [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7) for more information.
- `iss`: issuer - the Frontend API URL of your instance. For example: `https://clerk.your-site.com` for a production instance or `https://your-site.clerk.accounts.dev` for a development instance. See [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1) for more information.
- `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

To start making machine requests, refer to [making machine requests](/docs/backend-requests/making/machine).

## Validating Machine Tokens

To learn how to manually verify a machine token, refer to [validating machine tokens](/docs/backend-requests/handling/manual-jwt#machine-tokens).
8 changes: 8 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,10 @@
{
"title": "JWT Templates",
"href": "/docs/backend-requests/making/jwt-templates"
},
{
"title": "Machine Requests",
"href": "/docs/backend-requests/making/machine"
}
]
]
Expand Down Expand Up @@ -753,6 +757,10 @@
"title": "Session tokens",
"href": "/docs/backend-requests/resources/session-tokens"
},
{
"title": "Machine tokens",
"href": "/docs/backend-requests/resources/machine-tokens"
},
{
"title": "Rate limits",
"href": "/docs/backend-requests/resources/rate-limits"
Expand Down
35 changes: 35 additions & 0 deletions docs/references/backend/authenticate-request.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ It is recommended to set these options as [environment variables](/docs/deployme

---

- 'entity?'
- 'session' | 'machine'

Determines what type of authentication to perform. If set to `'session'`, the function will authenticate a user session. If set to `'machine'`, the function will authenticate a machine-to-machine request. Defaults to `session`

---

- `domain?`
- `string`

Expand Down Expand Up @@ -225,3 +232,31 @@ export async function GET(req: Request) {
return Response.json({ message: 'This is a reply' })
}
```
### Machine token verification
The following example uses the `authenticateRequest()` to verify a machine token.
```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,
})
}
```

0 comments on commit d6aa27f

Please sign in to comment.