Skip to content

Commit e82f177

Browse files
authored
feat(backend): Introduce M2M endpoints authentication using machine secret keys (#6479)
1 parent 0d27281 commit e82f177

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+923
-181
lines changed

.changeset/hot-tables-worry.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
"@clerk/backend": minor
3+
---
4+
5+
Adds machine-to-machine endpoints to the Backend SDK:
6+
7+
**Note:** Renamed from "machine_tokens" to "m2m_tokens" for clarity and consistency with canonical terminology. This avoids confusion with other machine-related concepts like machine secrets.
8+
9+
### Create M2M Tokens
10+
11+
A machine secret is required when creating M2M tokens.
12+
13+
```ts
14+
const clerkClient = createClerkClient({
15+
machineSecretKey: process.env.CLERK_MACHINE_SECRET_KEY
16+
})
17+
18+
clerkClient.m2mTokens.create({
19+
// or pass as an option here
20+
// machineSecretKey: process.env.CLERK_MACHINE_SECRET_KEY
21+
secondsUntilExpiration: 3600,
22+
})
23+
```
24+
25+
### Revoke M2M Tokens
26+
27+
You can revoke tokens using either a machine secret or instance secret:
28+
29+
```ts
30+
// Using machine secret
31+
const clerkClient = createClerkClient({ machineSecretKey: process.env.CLERK_MACHINE_SECRET_KEY })
32+
clerkClient.m2mTokens.revoke({
33+
// or pass as an option here
34+
// machineSecretKey: process.env.CLERK_MACHINE_SECRET_KEY
35+
m2mTokenId: 'mt_xxxxx',
36+
revocationReason: 'Revoked by user',
37+
})
38+
39+
// Using instance secret (default)
40+
const clerkClient = createClerkClient({ secretKey: 'sk_xxxx' })
41+
clerkClient.m2mTokens.revoke({
42+
m2mTokenId: 'mt_xxxxx',
43+
revocationReason: 'Revoked by user',
44+
})
45+
```
46+
47+
### Verify M2M Tokens
48+
49+
You can verify tokens using either a machine secret or instance secret:
50+
51+
```ts
52+
// Using machine secret
53+
const clerkClient = createClerkClient({ machineSecretKey: process.env.CLERK_MACHINE_SECRET_KEY })
54+
clerkClient.m2mTokens.verifySecret({
55+
// or pass as an option here
56+
// machineSecretKey: process.env.CLERK_MACHINE_SECRET_KEY
57+
secret: 'mt_secret_xxxxx',
58+
})
59+
60+
// Using instance secret (default)
61+
const clerkClient = createClerkClient({ secretKey: 'sk_xxxx' })
62+
clerkClient.m2mTokens.verifySecret({
63+
secret: 'mt_secret_xxxxx',
64+
})
65+
```
66+
67+
To verify machine-to-machine tokens using when using `authenticateRequest()` with a machine secret, use the `machineSecret` option:
68+
69+
```ts
70+
const clerkClient = createClerkClient({
71+
machineSecretKey: process.env.CLERK_MACHINE_SECRET_KEY
72+
})
73+
74+
const authReq = await clerkClient.authenticateRequest(c.req.raw, {
75+
// or pass as an option here
76+
// machineSecretKey: process.env.CLERK_MACHINE_SECRET_KEY
77+
acceptsToken: 'm2m_token', // previously machine_token
78+
})
79+
80+
if (authReq.isAuthenticated) {
81+
// ... do something
82+
}
83+
```

.changeset/pink-countries-hunt.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
"@clerk/astro": patch
3+
"@clerk/express": patch
4+
"@clerk/fastify": patch
5+
"@clerk/nextjs": patch
6+
"@clerk/nuxt": patch
7+
"@clerk/react-router": patch
8+
"@clerk/remix": patch
9+
"@clerk/tanstack-react-start": patch
10+
---
11+
12+
Add ability to define a machine secret key to Clerk BAPI client function
13+
14+
```ts
15+
const clerkClient = createClerkClient({ machineSecretKey: 'ak_xxxxx' })
16+
17+
clerkClient.m2mTokens.create({...})
18+
```

packages/astro/src/env.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface InternalEnv {
1111
readonly CLERK_API_VERSION?: string;
1212
readonly CLERK_JWT_KEY?: string;
1313
readonly CLERK_SECRET_KEY?: string;
14+
readonly CLERK_MACHINE_SECRET_KEY?: string;
1415
readonly PUBLIC_CLERK_DOMAIN?: string;
1516
readonly PUBLIC_CLERK_IS_SATELLITE?: string;
1617
readonly PUBLIC_CLERK_PROXY_URL?: string;

packages/astro/src/integration/create-integration.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ function createClerkEnvSchema() {
190190
PUBLIC_CLERK_TELEMETRY_DISABLED: envField.boolean({ context: 'client', access: 'public', optional: true }),
191191
PUBLIC_CLERK_TELEMETRY_DEBUG: envField.boolean({ context: 'client', access: 'public', optional: true }),
192192
CLERK_SECRET_KEY: envField.string({ context: 'server', access: 'secret' }),
193+
CLERK_MACHINE_SECRET_KEY: envField.string({ context: 'server', access: 'secret', optional: true }),
193194
CLERK_JWT_KEY: envField.string({ context: 'server', access: 'secret', optional: true }),
194195
};
195196
}

packages/astro/src/server/clerk-client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type CreateClerkClientWithOptions = (context: APIContext, options?: ClerkOptions
88
const createClerkClientWithOptions: CreateClerkClientWithOptions = (context, options) =>
99
createClerkClient({
1010
secretKey: getSafeEnv(context).sk,
11+
machineSecretKey: getSafeEnv(context).machineSecretKey,
1112
publishableKey: getSafeEnv(context).pk,
1213
apiUrl: getSafeEnv(context).apiUrl,
1314
apiVersion: getSafeEnv(context).apiVersion,

packages/astro/src/server/get-safe-env.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ function getSafeEnv(context: ContextOrLocals) {
2727
proxyUrl: getContextEnvVar('PUBLIC_CLERK_PROXY_URL', context),
2828
pk: getContextEnvVar('PUBLIC_CLERK_PUBLISHABLE_KEY', context),
2929
sk: getContextEnvVar('CLERK_SECRET_KEY', context),
30+
machineSecretKey: getContextEnvVar('CLERK_MACHINE_SECRET_KEY', context),
3031
signInUrl: getContextEnvVar('PUBLIC_CLERK_SIGN_IN_URL', context),
3132
signUpUrl: getContextEnvVar('PUBLIC_CLERK_SIGN_UP_URL', context),
3233
clerkJsUrl: getContextEnvVar('PUBLIC_CLERK_JS_URL', context),

0 commit comments

Comments
 (0)