Skip to content

Commit 3868a88

Browse files
alexisintechNWylynkogithub-advanced-security[bot]kylemacSarahSoutoul
authored
Add SDK-specificity to Authentication flows, User management, and Session management sections (#2595)
Co-authored-by: Nick Wylynko <[email protected]> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Kyle MacDonald <[email protected]> Co-authored-by: Sarah Soutoul <[email protected]> Co-authored-by: Kyle MacDonald <[email protected]> Co-authored-by: Michael Novotny <[email protected]>
1 parent e375e0e commit 3868a88

35 files changed

+1707
-1252
lines changed
Lines changed: 160 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,165 @@
1-
```tsx
2-
import { createClerkClient } from '@clerk/backend'
1+
<Tabs items={["Next.js", "Astro", "Express", "JS Backend SDK", "React Router", "Tanstack React Start"]}>
2+
<Tab>
3+
```tsx {{ filename: 'app/api/example/route.ts' }}
4+
import { clerkClient } from '@clerk/nextjs/server'
35

4-
export async function GET(req: Request) {
5-
const clerkClient = createClerkClient({
6-
secretKey: process.env.CLERK_SECRET_KEY,
7-
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
8-
})
6+
// Initialize the JS Backend SDK
7+
// This varies depending on the SDK you're using
8+
// https://clerk.com/docs/js-backend/getting-started/quickstart
9+
const client = await clerkClient()
910

10-
const { isSignedIn } = await clerkClient.authenticateRequest(req, {
11-
jwtKey: process.env.CLERK_JWT_KEY,
12-
authorizedParties: ['https://example.com'],
13-
})
11+
export async function GET(req: Request) {
12+
// Use the `authenticateRequest()` method to verify the token
13+
const { isAuthenticated } = await client.authenticateRequest(req, {
14+
authorizedParties: ['https://example.com'],
15+
jwtKey: process.env.CLERK_JWT_KEY,
16+
})
1417

15-
if (!isSignedIn) {
16-
return Response.json({ status: 401 })
17-
}
18+
// Protect the route from unauthenticated users
19+
if (!isAuthenticated) {
20+
return Response.json({ status: 401 })
21+
}
1822

19-
// Add logic to perform protected actions
23+
// Add logic to perform protected actions
2024

21-
return Response.json({ message: 'This is a reply' })
22-
}
23-
```
25+
return Response.json({ message: 'This is a reply' })
26+
}
27+
```
28+
</Tab>
29+
30+
<Tab>
31+
```tsx {{ filename: 'src/api/example.ts' }}
32+
import { clerkClient } from '@clerk/astro/server'
33+
import type { APIRoute } from 'astro'
34+
35+
export const GET: APIRoute = async (context) => {
36+
// Use the `authenticateRequest()` method to verify the token
37+
const { isAuthenticated } = await clerkClient(context).authenticateRequest(context.request, {
38+
authorizedParties: ['https://example.com'],
39+
jwtKey: process.env.CLERK_JWT_KEY,
40+
})
41+
42+
// Protect the route from unauthenticated users
43+
if (!isAuthenticated) {
44+
return Response.json({ status: 401 })
45+
}
46+
47+
// Add logic to perform protected actions
48+
49+
return Response.json({ message: 'This is a reply' })
50+
}
51+
```
52+
</Tab>
53+
54+
<Tab>
55+
```js {{ filename: 'index.js' }}
56+
import { createClerkClient } from '@clerk/express'
57+
import express from 'express'
58+
59+
const app = express()
60+
const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY })
61+
62+
app.get('/user', async (req, res) => {
63+
const { isAuthenticated } = await clerkClient.authenticateRequest(req, {
64+
authorizedParties: ['https://example.com'],
65+
jwtKey: process.env.CLERK_JWT_KEY,
66+
})
67+
68+
if (!isAuthenticated) {
69+
res.status(401).json({ error: 'User not authenticated' })
70+
}
71+
72+
// Add logic to perform protected actions
73+
74+
// Return the Backend User object
75+
res.json({ message: 'This is a reply' })
76+
})
77+
```
78+
</Tab>
79+
80+
<Tab>
81+
If you are using the [JS Backend SDK](/docs/js-backend/getting-started/quickstart) on its own, you need to provide the `secretKey` and `publishableKey` to `createClerkClient()` so that it is passed to `authenticateRequest()`. You can set these values as [environment variables](/docs/guides/development/clerk-environment-variables#clerk-publishable-and-secret-keys) and then pass them to the function.
82+
83+
```tsx
84+
import { createClerkClient } from '@clerk/backend'
85+
86+
// Initialize the JS Backend SDK
87+
// This varies depending on the SDK you're using
88+
// https://clerk.com/docs/js-backend/getting-started/quickstart
89+
const clerkClient = createClerkClient({
90+
secretKey: process.env.CLERK_SECRET_KEY,
91+
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
92+
})
93+
94+
export async function GET(req: Request) {
95+
// Use the `authenticateRequest()` method to verify the token
96+
const { isAuthenticated } = await clerkClient.authenticateRequest(req, {
97+
authorizedParties: ['https://example.com'],
98+
jwtKey: process.env.CLERK_JWT_KEY,
99+
})
100+
101+
// Protect the route from unauthenticated users
102+
if (!isAuthenticated) {
103+
return Response.json({ status: 401 })
104+
}
105+
106+
// Add logic to perform protected actions
107+
108+
return Response.json({ message: 'This is a reply' })
109+
}
110+
```
111+
</Tab>
112+
113+
<Tab>
114+
```tsx {{ filename: 'app/routes/example.tsx' }}
115+
import { redirect } from 'react-router'
116+
import { clerkClient } from '@clerk/react-router/server'
117+
import type { Route } from './+types/example'
118+
119+
export async function loader(args: Route.LoaderArgs) {
120+
// Use the `authenticateRequest()` method to verify the token
121+
const { isAuthenticated } = await clerkClient(args).authenticateRequest(args.request, {
122+
authorizedParties: ['https://example.com'],
123+
jwtKey: process.env.CLERK_JWT_KEY,
124+
})
125+
126+
if (!isAuthenticated) {
127+
return redirect('/sign-in?redirect_url=' + args.request.url)
128+
}
129+
130+
// Add logic to perform protected actions
131+
132+
return Response.json({ message: 'This is a reply' })
133+
}
134+
```
135+
</Tab>
136+
137+
<Tab>
138+
```tsx {{ filename: 'app/routes/api/example.tsx' }}
139+
import { createFileRoute } from '@tanstack/react-router'
140+
import { clerkClient } from '@clerk/tanstack-react-start/server'
141+
142+
export const ServerRoute = createFileRoute('/api/example')({
143+
server: {
144+
handlers: {
145+
GET: async ({ request }) => {
146+
// Use the `authenticateRequest()` method to verify the token
147+
const { isAuthenticated } = await clerkClient().authenticateRequest(request, {
148+
authorizedParties: ['https://example.com'],
149+
jwtKey: process.env.CLERK_JWT_KEY,
150+
})
151+
152+
if (!isAuthenticated) {
153+
return Response.json({ status: 401 })
154+
}
155+
156+
// Add logic to perform protected actions
157+
158+
return Response.json({ message: 'This is a reply' })
159+
},
160+
},
161+
},
162+
})
163+
```
164+
</Tab>
165+
</Tabs>

docs/_partials/backend/usage.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
> [!NOTE]
2-
> Importing `clerkClient` varies based on your framework. Refer to the [JS Backend SDK overview](/docs/js-backend/getting-started/quickstart) for usage details, including guidance on [how to access the `userId` and other properties](/docs/js-backend/getting-started/quickstart#get-the-user-id-and-other-properties).
2+
> Using `clerkClient` varies based on your framework. Refer to the [JS Backend SDK overview](/docs/js-backend/getting-started/quickstart) for usage details, including guidance on [how to access the `userId` and other properties](/docs/js-backend/getting-started/quickstart#get-the-user-id-and-other-properties).
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<Tabs items={["Next.js", "Astro", "Express", "React Router", "Tanstack React Start"]}>
2+
<Tab>
3+
```ts {{ filename: 'app/api/example/route.ts' }}
4+
import { clerkClient } from '@clerk/nextjs/server'
5+
import { NextResponse } from 'next/server'
6+
7+
export async function POST() {
8+
const client = await clerkClient()
9+
const invitation = await client.invitations.createInvitation({
10+
emailAddress: '[email protected]',
11+
redirectUrl: 'https://www.example.com/my-sign-up',
12+
publicMetadata: {
13+
example: 'metadata',
14+
example_nested: {
15+
nested: 'metadata',
16+
},
17+
},
18+
})
19+
20+
return NextResponse.json({ message: 'Invitation created', invitation })
21+
}
22+
```
23+
</Tab>
24+
25+
<Tab>
26+
```tsx {{ filename: 'src/api/example.ts' }}
27+
import type { APIRoute } from 'astro'
28+
import { clerkClient } from '@clerk/astro/server'
29+
30+
export const POST: APIRoute = async (context) => {
31+
await clerkClient(context).invitations.createInvitation({
32+
emailAddress: '[email protected]',
33+
redirectUrl: 'https://www.example.com/my-sign-up',
34+
publicMetadata: {
35+
example: 'metadata',
36+
example_nested: {
37+
nested: 'metadata',
38+
},
39+
},
40+
})
41+
42+
return new Response(JSON.stringify({ success: true }), { status: 200 })
43+
}
44+
```
45+
</Tab>
46+
47+
<Tab>
48+
```ts {{ filename: 'public.ts' }}
49+
import { getAuth, clerkClient } from '@clerk/express'
50+
51+
app.post('/createUser', async (req, res) => {
52+
await clerkClient.invitations.createInvitation({
53+
emailAddress: '[email protected]',
54+
redirectUrl: 'https://www.example.com/my-sign-up',
55+
publicMetadata: {
56+
example: 'metadata',
57+
example_nested: {
58+
nested: 'metadata',
59+
},
60+
},
61+
password: 'password',
62+
})
63+
64+
res.status(200).json({ success: true })
65+
})
66+
```
67+
</Tab>
68+
69+
<Tab>
70+
```tsx {{ filename: 'app/routes/example.tsx' }}
71+
import { clerkClient } from '@clerk/react-router/server'
72+
import type { Route } from './+types/example'
73+
import { json } from 'react-router-dom'
74+
75+
export async function action({ request }: Route.ActionArgs) {
76+
const formData = await request.formData()
77+
const emailAddress = formData.get('emailAddress')
78+
const redirectUrl = formData.get('redirectUrl')
79+
const publicMetadata = formData.get('publicMetadata')
80+
81+
await clerkClient.invitations.createInvitation({
82+
emailAddress: emailAddress,
83+
redirectUrl: redirectUrl,
84+
publicMetadata: publicMetadata,
85+
})
86+
87+
return json({ success: true })
88+
}
89+
```
90+
</Tab>
91+
92+
<Tab>
93+
```tsx {{ filename: 'app/routes/api/example.tsx' }}
94+
import { json } from '@tanstack/react-start'
95+
import { createFileRoute } from '@tanstack/react-router'
96+
import { clerkClient } from '@clerk/tanstack-react-start/server'
97+
98+
export const ServerRoute = createFileRoute('/api/example')({
99+
server: {
100+
handlers: {
101+
POST: async () => {
102+
await clerkClient().invitations.createInvitation({
103+
emailAddress: '[email protected]',
104+
redirectUrl: 'https://www.example.com/my-sign-up',
105+
publicMetadata: {
106+
example: 'metadata',
107+
example_nested: {
108+
nested: 'metadata',
109+
},
110+
},
111+
})
112+
113+
return json({ success: true })
114+
},
115+
},
116+
},
117+
})
118+
```
119+
</Tab>
120+
</Tabs>

0 commit comments

Comments
 (0)