Integrate Encore with Clerk
Before you start
Encore is an open source backend framework for TypeScript with built-in infrastructure automation and observability.
This tutorial outlines how to integrate Clerk's authentication into your Encore backend application, allowing you to manage user authentication and sessions securely. This guide uses TypeScript and Encore's built-in auth handler pattern.
Install @clerk/backend
@clerk/backend is a wrapper around the Backend API that makes it easier to interact with the API for JavaScript environments. It provides utilities to verify session tokens and manage users.
Run the following command to install the SDK:
npm install @clerk/backendpnpm add @clerk/backendyarn add @clerk/backendbun add @clerk/backendSet your Clerk API keys
-
In the Clerk Dashboard, navigate to the API keys page.
-
In the Quick Copy section, copy your Clerk .
-
Encore provides built-in secrets management to securely store sensitive values. Add your key to Encore's secrets with the following command:
terminal encore secret set --dev ClerkSecretKey
Create a Clerk client
- Create an
authfolder. - In the
authfolder, create aclerk.tsfile. - In your
clerk.tsfile, configure the Clerk client using the Clerk you set, usingcreateClerkClientfrom@clerk/backend:
import { createClerkClient } from '@clerk/backend'
import { secret } from 'encore.dev/config'
const clerkSecretKey = secret('ClerkSecretKey')
export const clerk = createClerkClient({
secretKey: clerkSecretKey(),
})Create an auth handler
Encore has a built-in auth handler pattern for protecting endpoints. In the auth folder, create a handler.ts file and copy and paste the following code. This is the auth handler that verifies Clerk session tokens using the verifyToken() function and makes authenticated user data available to your endpoints:
import { APIError, Gateway, Header } from 'encore.dev/api'
import { authHandler } from 'encore.dev/auth'
import { verifyToken } from '@clerk/backend'
import { secret } from 'encore.dev/config'
import { clerk } from './clerk'
const clerkSecretKey = secret('ClerkSecretKey')
interface AuthParams {
authorization: Header<'Authorization'>
}
export interface AuthData {
userID: string
email: string
}
export const auth = authHandler<AuthParams, AuthData>(async (params) => {
const token = params.authorization?.replace('Bearer ', '')
if (!token) {
throw APIError.unauthenticated('Missing session token')
}
try {
const payload = await verifyToken(token, {
secretKey: clerkSecretKey(),
// Optional: restrict allowed origins to prevent subdomain cookie leakage
// Replace with your authorized parties
authorizedParties: ['http://localhost:3001', 'https://example.com'],
})
const userId = payload.sub
if (!userId) {
throw new Error('No user ID in session token')
}
const user = await clerk.users.getUser(userId)
return {
userID: user.id,
email:
user.emailAddresses.find((e) => e.id === user.primaryEmailAddressId)?.emailAddress || '',
}
} catch (err) {
throw APIError.unauthenticated('Invalid session token')
}
})
export const gateway = new Gateway({
authHandler: auth,
})Protect your routes using getAuthData()
This endpoint gets the authenticated user's profile information. The auth: true option protects the endpoint, allowing only authenticated requests to access it. The getAuthData() function retrieves the authenticated user's data from the auth handler. Learn more about authentication in Encore documentation.
import { api } from 'encore.dev/api'
import { getAuthData } from '~encore/auth'
export const getProfile = api(
{ expose: true, auth: true, method: 'GET', path: '/user/profile' },
async () => {
const auth = getAuthData()!
return {
userId: auth.userID,
email: auth.email,
}
},
)Run your project
Start your Encore app with the following command:
encore runOpen the local development dashboard at http://localhost:9400 in your browser to view traces for all requests, including auth handler execution.
If you want to add more to your Clerk + Encore integration, such as database integration, webhooks, or organizations, check out this advanced Clerk + Encore tutorial guide.
Feedback
Last updated on