Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update fastify doc and quickstart #1555

Merged
merged 17 commits into from
Sep 27, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 89 additions & 72 deletions docs/quickstarts/fastify.mdx
Original file line number Diff line number Diff line change
@@ -1,21 +1,59 @@
---
title: Use Clerk with Fastify
description: Learn how to use Clerk to easily add authentication focused on security, speed, and DX to your Fastify server.
title: Fastify Quickstart
description: Learn how to integrate Clerk for secure authentication and user management into your application using a Fastify backend.
---

Learn how to use Clerk to easily add authentication focused on security, speed, and DX to your Fastify server.
<TutorialHero
framework="react"
exampleRepo={[
{
title: "Fastify Quickstart",
link: "https://github.com/clerk/clerk-fastify-quickstart"

After following this guide, you should have a working Fastify app with public and private routes, authenticated using the `clerkPlugin` and `getAuth` helpers.
}
]}
beforeYouStart={[
{
title: "Set up a Clerk application",
link: "/docs/quickstarts/setup-clerk",
icon: "clerk",
}, {
title: "Add Fastify as your backend",
link: "https://fastify.dev/docs/latest/Guides/Getting-Started",
icon: "fastify",
victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved
}
]}
>
- Create a Clerk application
- Install `@clerk/fastify`
- Set your Clerk API keys
- Configure `clerkPlugin` for all routes
- Use `getAuth()` to access the current auth state
- Protect specific routes
- Configure `clerkPlugin` for specific routes only
</TutorialHero>

Learn how to integrate Clerk into your Fastify backend for secure user authentication and management. This guide uses TypeScript and allows you to choose your frontend framework.

> [!IMPORTANT]
> [Fastify is only compatible with Next.js versions 13.4 and below](https://github.com/fastify/fastify-nextjs). If you're using a newer version of Next.js, consider using a different backend framework that supports the latest Next.js features.
victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved

> [!NOTE]
> If you're looking for a more complete example, check out our [Fastify example app](https://github.com/clerk/clerk-fastify-starter/).
> If you're using ECMAScript Modules (ESM) in your project, you must include `"type": "module"` in your `package.json` to enable ESM support in Node.js.
victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved

<Steps>
### Create a Clerk application

You need to create a Clerk application in your Clerk Dashboard before you can set up Clerk Fastify. For more information, refer to the [Set up your application](/docs/quickstarts/setup-clerk) guide.

victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved
### Install `@clerk/fastify`

Once your application is ready, install [Clerk's Fastify SDK](https://github.com/clerk/javascript/tree/main/packages/fastify). The SDK gives you access to our prebuilt components and hooks for your application.
victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved

<CodeBlockTabs type="installer" options={["npm", "yarn", "pnpm"]}>
victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved
```bash {{ filename: 'terminal' }}
npm install @clerk/fastify

```

```bash {{ filename: 'terminal' }}
Expand All @@ -27,55 +65,46 @@ After following this guide, you should have a working Fastify app with public an
```
</CodeBlockTabs>

### Set environment variables
### Set your Clerk API keys

<SignedIn>
Add the following keys to your `.env.local` file. These keys can always be retrieved from the [API Keys](https://dashboard.clerk.com/last-active?path=api-keys) page of your Clerk Dashboard.
</SignedIn>

Below is an example of an `.env.local` file.
<SignedOut>
1. Navigate to the Clerk Dashboard.
1. In the navigation sidebar, select [API Keys](https://dashboard.clerk.com/last-active?path=api-keys).
1. In the **Quick Copy** section, copy your Clerk publishable and secret key.
1. Paste your keys into your `.env` file.

**Pro tip!** If you are signed into your Clerk Dashboard, your secret key should become visible by clicking on the eye icon. Otherwise, you can find your keys in the Clerk Dashboard on the [API Keys](https://dashboard.clerk.com/last-active?path=api-keys) page.
The final result should resemble the following:
</SignedOut>

```env {{ filename: '.env.local' }}
```env {{ filename: '.env' }}
CLERK_PUBLISHABLE_KEY={{pub_key}}
CLERK_SECRET_KEY={{secret}}
```

This examples uses `dotenv` to load the environment variables. You can use any other library or method, if you so wish.
### Configure `clerkPlugin` for all routes

<CodeBlockTabs type="installer" options={["npm", "yarn", "pnpm"]}>
```bash {{ filename: 'terminal' }}
npm install dotenv
npm install -D @types/dotenv
```

```bash {{ filename: 'terminal' }}
yarn add dotenv
yarn add -D @types/dotenv
```

```bash {{ filename: 'terminal' }}
pnpm add dotenv
pnpm add -D @types/dotenv
```
</CodeBlockTabs>
The `clerkPlugin` can be registered globally or for specific routes. The following example registers the plugin for all routes. To register the plugin for specific routes only, refer to the [**Using Clerk for specific pages only**](/docs/quickstarts/fastify#using-clerk-for-specific-routes-only) section.
victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved

### Configure `clerkPlugin` in your Fastify application

The Clerk plugin can be registered globally or for specific routes. This examples registers the plugin globally.
> [!IMPORTANT]
> The `dotenv/config` module must be imported before any Clerk modules. This order is important because Clerk instances are created during the import process and rely on environment variables, such as API keys, to be initialized correctly. For more details, refer to the [Fastify docs](https://fastify.dev/docs/latest/Guides/Getting-Started/#loading-order-of-your-plugins).

```ts {{ filename: 'index.ts' }}
import * as dotenv from 'dotenv'

dotenv.config()

import 'dotenv/config'
import Fastify from 'fastify'
import { clerkClient, clerkPlugin, getAuth } from '@clerk/fastify'
import { clerkPlugin } from '@clerk/fastify'

const fastify = Fastify({ logger: true })

fastify.register(clerkPlugin)

const start = async () => {
try {
await fastify.listen({ port: 3000 })
await fastify.listen({ port: 8080 })
fastify.log.info('Server is running on port 8080.')
} catch (err) {
fastify.log.error(err)
process.exit(1)
Expand All @@ -85,54 +114,47 @@ After following this guide, you should have a working Fastify app with public an
start()
```

### Accessing auth state using `getAuth`
### Use `getAuth()` to access the current auth state
victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved

The `getAuth` helper can be used to access the auth state of the current request.

```ts {{ filename: 'index.ts' }}
import * as dotenv from 'dotenv'

dotenv.config()
The `getAuth()` method can access the authentation state of the current request. In the following example, the `userId` loads the entire [`User`](/docs/references/javascript/user/user) object from Clerk.

```ts {{ filename: 'index.ts', mark: [3, [9, 15]] }}
import 'dotenv/config'
import Fastify from 'fastify'
import { clerkClient, clerkPlugin, getAuth } from '@clerk/fastify'

const fastify = Fastify({ logger: true })

fastify.register(clerkPlugin)

// Declare a route and access the auth state for this request
fastify.get('/', async (req, reply) => {
/**
* Access the auth state for this request.
* In this example, the userId loads the whole User object
* from the Clerk servers
*/
const { userId } = getAuth(req)
const user = userId ? await clerkClient.users.getUser(userId) : null
reply.send({ message: 'Authentication state retrieved successfully.' })
return { user }
})

const start = async () => {
try {
await fastify.listen({ port: 3000 })
await fastify.listen({ port: 8080 })
fastify.log.info('Server is running on port 8080.')
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}

start()
```

### Require authentication for a route
### Protect specific routes

To protect a route using Clerk, you can use `getAuth` to check if the user is authenticated. If the user is not authenticated, you can return a 403 error.
To protect a route using Clerk, use the `getAuth()` method to check if the user is authenticated.

```ts {{ filename: 'index.ts' }}
fastify.get('/protected', async (request, reply) => {
const { userId } = getAuth(request)
if (!userId) {
return reply.code(403).send()
return reply.code(403).send({ message: 'Access denied. Authentication required.' })
}

const user = await clerkClient.users.getUser(userId)
Expand All @@ -141,55 +163,50 @@ After following this guide, you should have a working Fastify app with public an
```
</Steps>

### Using Clerk for specific routes only
### Configure `clerkPlugin` for specific routes only

If you want to use Clerk for specific routes only, you can register the plugin for specific routes. In this example, the routes are split into two groups: one for public routes and one for private routes.
If you want to use Clerk for specific pages only, you can register the plugin for specific routes. In the following example, the routes are split into public and private routes.

```ts {{ filename: 'index.ts' }}
import * as dotenv from 'dotenv'

dotenv.config()

import 'dotenv/config'
import Fastify, { FastifyPluginCallback } from 'fastify'
import { clerkClient, clerkPlugin, getAuth } from '@clerk/fastify'

const fastify = Fastify({ logger: true })

/**
* Register Clerk only for a subset of your routes
*/
const protectedRoutes: FastifyPluginCallback = (instance, opts, done) => {
const protectedRoutes: FastifyPluginCallback = (instance, options, done) => {
instance.register(clerkPlugin)

instance.get('/protected', async (request, reply) => {
const { userId } = getAuth(request)
if (!userId) {
return reply.code(403).send()
return reply.code(403).send({ message: 'Access denied. Authentication required.' })
}

const user = await clerkClient.users.getUser(userId)

// Only authenticated users will see the following message
reply.send({ message: 'This is a protected route.' })
return { user }
})
victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved

done()
}

const publicRoutes: FastifyPluginCallback = (instance, opts, done) => {
const publicRoutes: FastifyPluginCallback = (instance, options, done) => {
instance.get('/', async (request, reply) => {
return {
message: 'This is a public endpoint. Request /protected to test the Clerk auth middleware',
}
return { message: 'This is a public route.' }
victoriaxyz marked this conversation as resolved.
Show resolved Hide resolved
})

done()
}

/**
* Register your routes as you normally would
*/
fastify.register(protectedRoutes)
fastify.register(publicRoutes)

const start = async () => {
try {
await fastify.listen({ port: 3000 })
await fastify.listen({ port: 8080 })
} catch (err) {
fastify.log.error(err)
process.exit(1)
Expand Down
Loading