Skip to main content
Version: Canary

Clerk Authentication

To get started, run the setup command:

yarn rw setup auth clerk

This installs all the packages, writes all the files, and makes all the code modifications you need. For a detailed explanation of all the api- and web-side changes that aren't exclusive to Clerk, see the top-level Authentication doc. There's one Clerk-specific thing we'll get to, but for now, let's focus on Clerk's side of things.

If you don't have a Clerk account yet, now's the time to make one: navigate to and sign up, then create an application. The defaults are good enough to get us going, but feel free to configure things as you wish. We'll get the application's API keys from its dashboard next.

we'll only focus on the development instance

By default, Clerk applications have two instances, "Development" and "Production". We'll only focus on the "Development" instance here. When you're ready to deploy, switch the instance the dashboard is displaying by clicking "Development" in the header at the top. How you get your API keys to production depends on your deploy provider.

We're looking for three API keys. Head over to the "Developers" section in the nav on the left and click "API Keys". You'll need all three of the ones on this page: the Frontend API key, the default Backend API key, and the JWT verification key. Copy them into your project's .env file:

# This one is the default Backend API Key.

Lastly, in your project's redwood.toml file, include CLERK_FRONTEND_API_URL in the list of env vars that should be available to the web side:

# ...
includeEnvironmentVariables = ["CLERK_FRONTEND_API_URL"]

That should be enough; now, things should just work. Let's make sure: if this is a brand new project, generate a home page. There we'll try to sign up by destructuring signUp from the useAuth hook (import that from 'src/auth'). We'll also destructure and display isAuthenticated to see if it worked:

import { useAuth } from 'src/auth'

const HomePage = () => {
const { isAuthenticated, signUp } = useAuth()

return (
{/* MetaTags, h1, paragraphs, etc. */}

<p>{JSON.stringify({ isAuthenticated })}</p>
<button onClick={signUp}>sign up</button>

Clicking sign up should open a sign-up box:


After you sign up, you should see {"isAuthenticated":true} on the page.

Deep dive: the ClerkStatusUpdater component

At the start of this doc, we said that there's one Clerk-specific thing worth noting. We'll discuss it here, but feel free to skip this section if you'd like—this is all extracurricular.

Clerk is a bit unlike the other auth providers Redwood integrates with in that it puts an instance of its client SDK on the browser's window object. That means we have to wait for it to be ready. With other providers, we instantiate their client SDK in web/src/auth.ts, then pass it to createAuth. Not so with Clerk—instead we use special Clerk components and hooks, like ClerkLoaded and useUser, to update Redwood's auth context with the client when it's ready.

Avoiding feature duplication

Redwood's Clerk integration is based on Clerk's React SDK. This means that there's some duplication between the features in the SDK and the ones in @redwoodjs/auth-clerk-web. For example, the SDK ha a SignedOut component that redirects a user away from a private page—very much like wrapping a route with Redwood's Private component. We recommend you use Redwood's way of doing things as much as possible since it's much more likely to get along with the rest of the framework.