Docs

Integrate Convex with Clerk

You will learn the following:

  • Create a JWT template based on Convex
  • Configure Convex with the Clerk issuer domain
  • Install and configure Clerk's React SDK
  • Configure the Clerk and Convex providers
  • Access user identity in Convex queries and mutations

Convex is the full-stack TypeScript development platform. With Convex you get to build a backend with a provided realtime database, file storage, text search, scheduling and more. Paired with Clerk's user authentication and management features, you can build a powerful application with minimal effort.

This tutorial assumes that you have already set up a Clerk application and a React + Convex application. This tutorial will also assume that you have not added Clerk to your application yet.

Create a JWT template based on Convex

In the Clerk Dashboard, navigate to the JWT templates page. Select the New template button to create a new template based on Convex.

The JWT templates page in the Clerk Dashboard. The 'New template' button was clicked, and a pop up titled 'New JWT template' is shown. The 'Convex' template is hovered over

Once the Convex template is created, you will be redirected to the template's page. You can now configure the template to your needs.

The 'Create new template' page of the JWT templates page in the Clerk Dashboard

The Convex template will pre-populate the default audience (aud) claim required by Convex. You can include additional claims as necessary. Shortcodes are available to make adding dynamic user values easy.

The 'Create new template' page of the JWT templates page in the Clerk Dashboard. The page is scrolled down to the 'Claims' section

By default, Clerk will sign the JWT with a private key automatically generated for your application, which is what most developers use for Convex. If you so choose, you can customize this key.

Configure Convex with the Clerk issuer domain

The next step is to configure Convex with the issuer domain provided by Clerk. From your Clerk JWT template screen, find the Issuer input and click to Copy the URL.

The 'Create new template' page of the JWT templates page in the Clerk Dashboard. There is a red box surrounding the 'Issuer' section

In your convex folder, add an auth.config.js file with the following configuration:

convex/auth.config.js
export default {
  providers: [
    {
      domain: 'https://your-issuer-url.clerk.accounts.dev/',
      applicationID: 'convex',
    },
  ],
}

Replace the domain string with the Issuer URL you copied.

Deploy your changes to Convex

Run npx convex dev to automatically sync your configuration to your backend.

Install @clerk/clerk-react

Run the following command to install Clerk's React SDK:

terminal
npm install @clerk/clerk-react
terminal
yarn add @clerk/clerk-react
terminal
pnpm add @clerk/clerk-react

Set environment variables

In your React project's root folder, you may have an .env.local file alongside package.json and other configuration files. If you don't see it, create it.

.env.local
VITE_CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY

Configure the Clerk and Convex providers

Both Clerk and Convex have provider components that are required to provide authentication and client context.

Clerk's provider component is <ClerkProvider>, which should wrap your entire app at the entry point to make authentication globally accessible. See the reference docs for other configuration options.

Convex offers a provider that is specifically for integrating with Clerk called <ConvexProviderWithClerk>.

The following example demonstrates how to configure Clerk and Convex's providers. Clerk's useAuth() hook must be passed to <ConvexProviderWithClerk> and Clerk's <ClerkProvider> must be wrapped around it.

src/main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import { ClerkProvider, useAuth } from '@clerk/clerk-react'
import { ConvexProviderWithClerk } from 'convex/react-clerk'
import { ConvexReactClient } from 'convex/react'

// Import your Publishable Key
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY

if (!PUBLISHABLE_KEY) {
  throw new Error('Missing Publishable Key')
}

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string)

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <ClerkProvider publishableKey={PUBLISHABLE_KEY}>
      <ConvexProviderWithClerk client={convex} useAuth={useAuth}>
        <App />
      </ConvexProviderWithClerk>
    </ClerkProvider>
  </React.StrictMode>,
)

Access user identity in Convex queries and mutations

You can access the user information from the JWT in Convex queries and mutations. Use the ctx.auth.getUserIdentity() which returns the parsed information from the JWT, or null if the client isn't authenticated.

import type { UserIdentity } from 'convex/server'
import { query } from './_generated/server'

export default query(async (ctx) => {
  const user = await ctx.auth.getUserIdentity()

  if (user === null) {
    return null
  }

  return user.tokenIdentifier
})

You can customize the information in the JWT by navigating to the JWT templates page in the Clerk Dashboard. Previously, Convex explicitly listed fields derived from OpenID standard claims. Now, Convex allows keys to accept custom claims.

Finished!

You now have a fully functioning React and Convex application with Clerk authentication. Be aware that Convex may require usage of their custom hooks and methods rather than Clerk's, such as using Convex's useConvexAuth() hook instead of Clerk's useAuth() hook in some cases. For more information on how to use Convex with Clerk, see the Convex docs.

Feedback

What did you think of this content?

Last updated on