# Clerk Blog — Page 9

# Build a Cookie Clicker App with Clerk and Hasura
URL: https://clerk.com/blog/build-a-cookie-clicker-app-with-clerk-and-hasura.md
Date: 2023-07-23
Category: Guides
Description: In this tutorial we will use Clerk with Hasura to build a full-stack Next.js app with a database and GraphQL API, all without having to write any backend code.

[Hasura](https://hasura.io) provides a GraphQL engine that can help you build real-time APIs and ship modern apps faster. Although Hasura itself does not handle authentication, you can bring your own auth server and integrate it with Hasura via JWTs. This is where [Clerk](https://clerk.com/) fits in.

In this tutorial we will use Clerk with Hasura to build a full-stack Next.js app with a database and GraphQL API, all without having to write any backend code.

> If you would like to skip ahead and see the completed codebase, browse to the repo [here](https://github.com/clerkinc/more-cookies-please).

## Assumptions

This tutorial makes the following assumptions:

- Basic command line usage
- Node.js installed and `npm` (or `yarn` if you prefer) for package management
- Experience with React components and hooks
- Familiarity with the Next.js application structure (created with `create-next-app`)
- Comfortable running Docker Compose commands (alternative path is to use Hasura Cloud)
- [Clerk](https://dashboard.clerk.com/sign-in) and [Hasura](https://cloud.hasura.io/login) accounts already set up (if you haven’t done so, do it now\... we’ll wait)

## Set up Clerk project

We’re going to start off with creating a new project from the Clerk dashboard. I’m going to name this application “More Cookies Please” (you’ll see why shortly) and leave the default options selected for authentication strategy and turn on social login with Google.

![Build A Cookie Clicker App With Clerk And Hasura guide illustration](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/deb49deb5a617c0b5dc625a4c03525a1c4110354-1176x1514.png)

The next thing we need to do is navigate to JWT Templates from the left menu and create a template based on Hasura.

![Hasura template](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/c32bdcf8bc58e5c2e8787e5f5cfbc32d7fd2b352-1636x1000.png)

The next thing we need to do is navigate to JWT Templates from the left menu and create a template based on Hasura.

![Hasura token claims](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/460f05efd18bcbfa6120d6c2296969b088c000e0-2072x1360.png)

Click the “Apply changes” button and navigate back to the Home dashboard. Here we’re going to copy the Frontend API key.

![Frontend API key](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/848ed7537b737ab642164c7df56400766316b770-2050x506.png)

That’s all we need to do in the Clerk dashboard.

## Clone the starter repo

Now it’s time to clone the [clerk-hasura-starter](https://github.com/clerkinc/clerk-hasura-starter) repo from GitHub. Name this project directory `more-cookies-please` to match the Clerk instance name.

```bash
git clone https://github.com/clerkinc/clerk-hasura-starter.git more-cookies-please
```

Once you have the repository downloaded to your computer, run the following commands to change into the directory, install the package dependencies, and copy the `.env.local.sample` so we can set a couple environment variables:

```bash
cd more-cookies-please/
npm install
cp .env.local.sample .env.local
```

Add in the Frontend API key from Clerk that was copied earlier. We’re also going to set the GraphQL endpoint even though it hasn’t been created yet.

```bash
NEXT_PUBLIC_CLERK_FRONTEND_API=<YOUR_FRONTEND_API>
NEXT_PUBLIC_HASURA_GRAPHQL_API=http://localhost:8080/v1/graphql
```

**Note**: `CLERK_API_KEY` is available in the sample but isn’t needed for this tutorial.

Once those environment variables are set, start up the application with `npm run dev`

Open your web browser to http://localhost:3000 and you should see the starter application homepage, which prompts you to sign up. So now let’s sign up for an account.

Click the Sign up button and you will be redirected to a Sign Up form generated for your application with Clerk components. I’m going to choose **Sign up with Google** since it's the fastest (and doesn’t require a new password).

Once you’ve signed up and logged in, you should see the following screen:

![App welcome](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/2586548dde72a7d28cd9ea95d1a9d5b9ffedd8ae-2276x1666.png)

Now it’s time to customize this application. We’re going to install a little package I created based on the excellent [react-rewards](https://github.com/thedevelobear/react-rewards) library and inspired by [Cookie Clicker](https://en.wikipedia.org/wiki/Cookie_Clicker) (thank [@bsinthewild](https://twitter.com/bsinthewild) for reminding me of this).

```bash
npm install react-cookie-clicker
```

**Note**: ⚠️ You will see some warnings about conflicting peer dependencies due to a mismatch of React versions, but it’s safe to proceed.

We’re going to create a new file called `MoreCookies.js` inside of the `components/` folder.

Because this library does not support server-side rendering (SSR), we need to make use of the [dynamic imports from Next.js](https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr) or we’ll get some nasty errors.

```jsx
import dynamic from 'next/dynamic'
const CookieClicker = dynamic(() => import('react-cookie-clicker'), {
  ssr: false,
})

const MoreCookies = () => {
  return (
    <div style={{ marginTop: 150 }}>
      <CookieClicker />
      <h2>Click the cookie</h2>
    </div>
  )
}

export default MoreCookies
```

Now let’s add the component to `pages/index.js`:

```jsx
import styles from '../styles/Home.module.css'
import Link from 'next/link'
import { SignedIn, SignedOut } from '@clerk/nextjs'
import MoreCookies from '../components/MoreCookies'

const SignupLink = () => (
  <Link href="/sign-up">
    <a className={styles.cardContent}>
      <img src="/icons/user-plus.svg" alt="Clone the starter repo illustration" />
      <div>
        <h3>Sign up for an account</h3>
        <p>Sign up and sign in to explore all the features provided by Clerk out-of-the-box</p>
      </div>
      <div className={styles.arrow}>
        <img src="/icons/arrow-right.svg" alt="Clone the starter repo illustration" />
      </div>
    </a>
  </Link>
)

const Main = () => (
  <main className={styles.main}>
    <SignedOut>
      <h1 className={styles.title}>Welcome to your new app</h1>
      <p className={styles.description}>Sign up for an account to get started</p>
      <div className={styles.cards}>
        <div className={styles.card}>
          <SignupLink />
        </div>
      </div>
    </SignedOut>
    <SignedIn>
      <MoreCookies />
    </SignedIn>
  </main>
)
```

The `ClerkFeatures` component can be removed, but the `Footer` and `Home` components should remain untouched.

You can see here we are making use of the `SignedIn` and `SignedOut` components from Clerk. We can also finally see the big cookie button!

Go ahead and click it for a nice reward. You’ve earned it. 🍪

![Cookie button](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/a99cf1d2ef740351be1972ded05a878652b92a3a-1686x1206.png)

## Set up Hasura GraphQL engine

Clicking the cookie is a lot of fun, but what is even more fun? Keeping count of all those clicks!

This is where the Hasura GraphQL integration comes in.

There are two different ways we can connect to Hasura: we can use Hasura Cloud or Hasura Core running from a Docker container. We’re going to do the latter for this tutorial, but you can see instructions for connecting with Hasura Cloud in our [integration documentation](https://clerk.com/docs/integrations/databases/hasura.md).

The starter repo already contains the `docker-compose.yml` file we need.

The only part we need to update here is the JWT secret. Uncomment the line for `HASURA_GRAPHQL_JWT_SECRET` and add in the value for your Clerk Frontend API. The JWT URL path points to the JSON Web Key Set (JWKS) endpoint we have set up for your application.

```yaml
HASURA_GRAPHQL_JWT_SECRET: '{"jwk_url":"https://<YOUR_FRONTEND_API>/.well-known/jwks.json"}'
```

**Note**: Make sure the **https://** protocol is included in the URL in front of the Frontend API.

Once the JWT secret is set, run the following command:

```bash
docker compose up -d
```

This will spin up Docker services for GraphQL engine as well as a Postgres database.

You can confirm that the services are running correctly with the following:

```bash
docker compose ps
```

If all is good, you should see output similar to:

```bash
COMMAND                  SERVICE           STATUS        PORTS
"graphql-engine serve"   graphql-engine    running       0.0.0.0:8080->8080/tcp
"docker-entrypoint.s…"   postgres          running       5432/tcp
```

Head to http://localhost:8080/console to open the Hasura console.

![Hasura GraphiQL console](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/24485ecee44a1614483815c81820affa357376d0-2544x1670.png)

Hasura has already done the work of setting up a GraphQL endpoint for us and also provided the GraphiQL integrated development environment (IDE) to explore the API.

It’s time to set up the database to keep the score count.

Navigate to the **Data** page and fill out the form to Connect Existing Database. (Remember we have the Postgres one running from Docker Compose?)

![Connect database](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/c8140b09ad7a9a761bb9633a079b5c8c85f260cd-1668x1430.png)

Name the database `default` (or something more clever) and input the database URL copied from the `docker-compose.yml` file. Click connect and the data source will be added.

The next step is to create the database table named `scoreboard` and add two fields:

1. `user_id` is a Text field that will contain the user ID from Clerk
2. `count` is an Integer field that will keep track of the click count

![Add new table](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/a8236a9c8daf4eff6717e6055e3fd52feec692df-2244x1324.png)

Set the `user_id` as the **Primary Key** for the table. Then click the Add Table button.

The next thing we need to do is set permissions for the “user” role. Click on the **Permissions** tab and enter `user` as a new role. Then we need to set the basic **CRUD** (Create, Read, Update, Delete) operations on the table.

### Insert (Create)

For **Insert** permissions, set the following values:

- **Row insert permissions**: Without any checks
- **Column insert permissions**: `count` checked
- **Column presets**: `user_id` from session variable `X-Hasura-User-Id`

![Insert permissions](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/6f63cdd947fd37c6bd707ac93579f28b074f031d-1966x1300.png)

With the Clerk integration, the user ID will be set as the session variable and Hasura will then set that as the `user_id` column when the request is made.

### Select (Read)

For **Select** permissions, set the following values:

- **Row select permissions**: With custom check `{"user_id":{"_eq":"X-Hasura-User-Id"}}`
- **Column select permissions**: `count` and `user_id` checked

![Select permissions](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/0cfbbb9668e9a9d95c05b6c457301f30136977d2-1966x1412.png)

The custom check ensures only the current authenticated user can read their own count. If the user ID from the session variable matches the one from the table, the user is granted read permission to every column in their database row.

### Update

For Update permissions, set the following values:

- **Pre-update check**: With same check as select `{"user_id":{"_eq":"X-Hasura-User-Id"}}`
- **Column update permissions**: `count` checked

![Update permissions](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/23862bf8f3bbffaef05ad5d6f9d239f2a2efd5fc-1958x1464.png)

Having the same custom check prevents another authenticated user from updating someone else’s count.

### Delete

We can skip over **Delete** permissions since we aren’t implementing a mechanism to delete user records from the scoreboard.

Your final permissions access chart should look like the following:

![Permissions chart](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/b4cfa610c9a9316934c6ea992f1e6c9973009aad-1744x920.png)

## Configure the client

Now it’s time to make authenticated requests from the codebase to Hasura.

If you take a look at `hooks/index.js`, you can see the `useQuery` hook that has been set up. It makes use of [graphql-request](https://github.com/prisma-labs/graphql-request), a minimal GraphQL client, with the [useSWR](https://swr.vercel.app) hook to perform query requests to the GraphQL endpoint.

```jsx
import { request } from 'graphql-request'
import { useAuth } from '@clerk/nextjs'
import useSWR from 'swr'

export const useQuery = (query, variables, blockRequest) => {
  if (!query) {
    throw Error('No query provided to `useQuery`')
  }
  const { getToken } = useAuth()
  const endpoint = process.env.NEXT_PUBLIC_HASURA_GRAPHQL_API
  const fetcher = async () =>
    request(endpoint, query, variables, {
      authorization: `Bearer ${await getToken({ template: 'hasura' })}`,
    })

  return useSWR(query, blockRequest ? () => {} : fetcher)
}
```

What we’re doing is reading the custom JWT (from the template we named `hasura`) from the session object provided by Clerk. Note that the call to `getToken` is asynchronous and returns a Promise that needs to be resolved before accessing the value.

We pass the custom fetcher function, which accepts a GraphQL query and optional variables, to `useSWR`. The `blockRequest` parameter is something we’ll make use of later to prevent certain calls from happening.

Let’s try this out to make sure we can get some data. Open up `components/MoreCookies.js` and import the `useQuery` hook and log the `data` to the console:

```jsx
import dynamic from 'next/dynamic'
import { useQuery } from '../hooks'
const CookieClicker = dynamic(() => import('react-cookie-clicker'), {
  ssr: false,
})

const MoreCookies = () => {
  const { data } = useQuery(`query { scoreboard { count } }`)
  console.log('data >>', data)

  return (
    <div style={{ marginTop: 150 }}>
      <CookieClicker />
      <h2>Click the cookie</h2>
    </div>
  )
}

export default MoreCookies
```

If all went well, you should see the following:

```jsx
data >> undefined
data >> { scoreboard: Array(0) }
```

The data is `undefined` at first but then gets populated. `scoreboard` is an empty Array because we haven’t recorded any click counts yet. So let’s do that now.

In order to make the GraphQL mutation we’re going to create another custom hook in `hooks/index.js`:

```jsx
export const useCountMutation = (count, data) => {
  const prevCount = data?.scoreboard[0]?.count ?? 0
  const blockRequest = count < 1 || prevCount === count

  // Block mutation if count is less than 1 or equal to previous value
  return useQuery(
    `mutation {
      insert_scoreboard_one(
        object: { count: ${count} },
        on_conflict: { constraint: scoreboard_pkey, update_columns: count }) {
        count
        user_id
      }
  }`,
    null,
    blockRequest,
  )
}
```

This hook accepts the `count` as the first parameter and the `data` object containing previous data as the second parameter. It makes use of the `useQuery` hook to apply the `insert_scoreboard_one` insert mutation as an [upsert](https://hasura.io/docs/2.0/mutations/postgres/upsert). Instead of adding multiple rows to the database table, the `on_conflict` argument sets a constraint on the primary key (`user_id`) and if it already exists, only the `count` column will be updated. Both `count` and `user_id` values are returned from a successful mutation.

If we replace the `useQuery` with `useCountMutation` in the `MoreCookies` component, we can give us some credit for those clicks we’ve already made. (I set mine at `10` but you can be more or less generous.)

```jsx
import dynamic from 'next/dynamic'
import { useCountMutation } from '../hooks'
const CookieClicker = dynamic(() => import('react-cookie-clicker'), {
  ssr: false,
})

const MoreCookies = () => {
  const { data } = useCountMutation(10)
  console.log('data >>', data)

  return (
    <div style={{ marginTop: 150 }}>
      <CookieClicker />
      <h2>Click the cookie</h2>
    </div>
  )
}

export default MoreCookies
```

If you look at the browser console, you should now see something like:

```
data >> { insert_scoreboard_one: { count: 10, user_id: 'user_29IqLFGiidcpkwqplE1F8C8EnD1' } }
```

You can confirm that this made it into the Postgres database by going to the **Data** tab in the Hasura Console and clicking into **scoreboard** and **Browse Rows**:

![Browse rows](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/31968443a55bf5e2b2d0bced0969311a221cc0d9-1940x924.png)

Success! The count (fake or not) has made it into the database and is associated with the authenticated user.

So now that everything is working as intended, we can go ahead and connect it all together. We’ll add one more custom hook that performs both the initial `useQuery` and the `useCountMutation`. This is going to need both `useState` and `useEffect` from React so make sure you import those.

```jsx
export const useScoreboard = () => {
  const [count, setCount] = useState(0)
  const { data } = useQuery(`query {
    scoreboard { count, user_id }
  }`)
  const increment = () => {
    setCount(count + 1)
  }

  // Perform mutation on count
  useCountMutation(count, data)

  useEffect(() => {
    if (!count && data?.scoreboard[0]) {
      // Set initial count from database
      setCount(data.scoreboard[0].count)
    }
  }, [count, data])

  return [count, increment]
}
```

It returns the current `count` as well as an `increment` function, both of which we can pass as props to the `<CookieClicker />` component.

```jsx
import dynamic from 'next/dynamic'
import { useScoreboard } from '../hooks'
const CookieClicker = dynamic(() => import('react-cookie-clicker'), {
  ssr: false,
})

const MoreCookies = () => {
  const [count, increment] = useScoreboard()

  return (
    <div style={{ marginTop: 150 }}>
      <CookieClicker count={count} onClick={increment} />
      <h2>Click the cookie</h2>
      <p>Current count: {count}</p>
    </div>
  )
}

export default MoreCookies
```

By setting the `count` and `onClick` props on `CookieClicker`, it will now reward you with cookies based on the number of times the button is clicked. Keep clicking for more cookies!

![Build A Cookie Clicker App With Clerk And Hasura guide illustration](https://clerk.com/_media/blog/build-a-cookie-clicker-app-with-clerk-and-hasura/276b94611d06d56484ba13d0b5cdb9b803964b0a-1526x1265.jpg)

## Closing thoughts

Hope you had fun building this. You now have a complete Cookie Clicker app built using Clerk, Hasura, and Next.js — with no backend code required! To take it even further, you could implement an actual scoreboard that keeps track of all the cookie clicks from multiple users. Then [deploy this app to production](https://clerk.com/docs/deployments/overview.md), share it with your friends, and see how much idle time they have on their hands. 😆

If you enjoyed this tutorial or have any questions, feel free to reach out to me ([@devchampian](https://x.com/devchampian)) on X, follow [@clerk](https://x.com/clerk), or join our [Discord community](https://clerk.com/discord) to connect with other developers. Happy coding!


---

# RedwoodJS Blog Tutorial with Clerk
URL: https://clerk.com/blog/redwoodjs-blog-tutorial-with-clerk.md
Date: 2023-07-23
Category: Guides
Description: Branching off from the excellent (and mighty) Redwood tutorial, the guide will lead you through setting up Clerk as the authentication provider.

> As of April 4, 2025, RedwoodJS is no longer actively developed. [Learn more](https://community.redwoodjs.com/t/the-future-of-redwood-launches-today/7938).

Branching off from the excellent (and mighty) Redwood tutorial, the guide will lead you through setting up Clerk as the authentication provider. You can think of Clerk as the ranger of the forest, only allowing verified users pass through the secluded parts of your app. (Be prepared for tree puns ahead — you’ve been warned! 🌲)

## Assumptions

This tutorial makes the following assumptions:

- Basic command line usage
- Node.js installed with both `npm` and `yarn` (required by Redwood)
- Experience with React components and hooks
- Have gone through the first part of the [Redwood tutorial](https://learn.redwoodjs.com/docs/tutorial/welcome-to-redwood)
- [Clerk](https://dashboard.clerk.com/sign-in) account already set up (if you haven’t done so, do it now\... we’ll wait)

> If you would like to skip ahead and see the completed codebase, browse to the repo [here](https://github.com/clerkinc/redwood-tutorial-with-clerk).

## Getting started

This journey begins with cloning the [example repo](https://github.com/redwoodjs/redwood-tutorial) that Redwood has set up.

```bash
git clone https://github.com/redwoodjs/redwood-tutorial.git redwood-tutorial-with-clerk
```

Follow their instructions to run the following commands:

```bash
cd redwood-tutorial-with-clerk/
yarn install
yarn rw prisma migrate dev
yarn rw dev
```

**Note**: If the `rw` (short for `redwood`) command isn’t working, make sure you have the proper versions of [Node.js and Yarn](https://learn.redwoodjs.com/docs/tutorial/prerequisites#nodejs-and-yarn-versions) installed.

If all went well, you should be looking at the most beautiful blog you’ve ever seen...

![Redwood blog](https://clerk.com/_media/blog/redwoodjs-blog-tutorial-with-clerk/2733571d4e74adab3f76818c54be7968d468dd9c-2348x1372.png)

If you try to navigate to http://localhost:8910/admin/posts you will be redirected back to the homepage. This is due to the `<Private unauthenticated="home">` wrapper around the admin routes that was already set up.

## Set up Clerk authentication

As part of the [Authentication chapter](https://learn-redwood.netlify.app/docs/tutorial/authentication) of the Redwood tutorial, they went through the setup of their built-in database-backed authentication system called dbAuth. (Can’t blame them for planting those seeds.)

To transplant Clerk as the new authentication provider, first, navigate to your [Clerk dashboard](https://dashboard.clerk.com) and create a new application. Give your application any name you’d like, leave the default authentication strategy selected, and then choose a social login provider if you would like. (Google OAuth is pretty fast and doesn’t make you create a new password.)

![Redwoodjs Blog Tutorial With Clerk guide illustration](https://clerk.com/_media/blog/redwoodjs-blog-tutorial-with-clerk/079ce27b85ebf6511a2a2f55d090c87dcf4cafd0-1174x1352.png)

Once the application has been created and the confetti clears, scroll down to the **Connect your application** section to grab your API keys.

Back in the codebase, create a new `.env` file in the project directory and set the following environment variables to the respective values from your Clerk dashboard:

```bash
CLERK_API_KEY=<YOUR_BACKEND_API_KEY>
CLERK_FRONTEND_API_URL=<YOUR_FRONTEND_API_KEY>
```

Once you have the environment variables set, the next step is to root out the existing auth logic. The quickest way to do this is to run:

```bash
yarn rw setup auth clerk --force
```

Note: If you’re into the more labor-intensive, manual way of doing things, [here are the instructions](https://redwoodjs.com/docs/authentication#clerk) for you. (Chainsaws not required.)

You should see terminal output similar to the following:

```bash
✔ Overwrite existing /api/src/lib/auth.[jt]s? … yes
  ✔ Generating auth lib...
    ✔ Successfully wrote file `./api/src/lib/auth.js`
  ✔ Adding auth config to web...
  ✔ Adding auth config to GraphQL API...
  ✔ Adding required web packages...
  ✔ Adding required api packages...
  ✔ Installing packages...
  ✔ One more thing...

You will need to add two environment variables with your Clerk URL and API key.
Check out web/src/App.{js,tsx} for the variables you need to add.
See also: https://redwoodjs.com/docs/authentication#clerk
```

If you already followed the instructions to add your environment variables, great job! If you didn’t, please add them now.

In your code editor of choice, open up `web/src/App.js`

Wrap the Redwood `<AuthProvider />` component with `<ClerkAuthProvider />` and replace the prop `type="dbAuth"` with `type="clerk"`:

```jsx
const App = () => (
  <FatalErrorBoundary page={FatalErrorPage}>
    <RedwoodProvider titleTemplate="%PageTitle | %AppTitle">
      <ClerkAuthProvider>
        <AuthProvider type="clerk">
          <RedwoodApolloProvider>
            <Routes />
          </RedwoodApolloProvider>
        </AuthProvider>
      </ClerkAuthProvider>
    </RedwoodProvider>
  </FatalErrorBoundary>
)
```

## Add Clerk components

Now that Clerk is set up, restart the dev server with `yarn rw dev`. If you had the dev server running, it needs to be restarted to read the newly added environment variables.

Open the `web/src/layouts/BlogLayout/BlogLayout.js` component in your code editor and add the following imports:

```jsx
import { SignInButton, UserButton } from '@clerk/clerk-react'
```

While the `login` and `logOut` methods from the Redwood `useAuth()` hook will work, Clerk provides nice UI components to accomplish the same thing. Remove the `logIn` and `logOut` methods and replace the last navigation list item with the following code:

```jsx
<li className={isAuthenticated ? 'ml-2' : null}>
  {isAuthenticated ? (
    <UserButton afterSignOutAll={window.location.href} />
  ) : (
    <SignInButton mode="modal">
      <button className="rounded px-4 py-2 transition duration-100 hover:bg-blue-600">
        Log in
      </button>
    </SignInButton>
  )}
</li>
```

**Note**: The `afterSignOutAll` prop needs to be set to the current URL when using Clerk Hosted Pages to redirect back to your app.

Making use of the `isAuthenticated` property checks if there is an active user session. If there isn’t one, the Clerk `<SignInButton />` component renders a custom button element matching the blog styles. Clicking “Log in”, opens a modal window allowing you to sign in with Google or sign up with an email and password.

![Clerk sign in modal](https://clerk.com/_media/blog/redwoodjs-blog-tutorial-with-clerk/1a05816face419ca2799bb6268f42d82c5ea0824-2348x1366.png)

After signing in, you should see the `<UserProfile />` component with an avatar.

If you look in the code right underneath the navigation, there is a conditionally rendered text block for `currentUser.email`. This doesn’t render anything because the Clerk user object is structured a little differently. To display the current user’s email address, make the following tweaks:

```jsx
{
  isAuthenticated && (
    <div className="text-right text-xs text-blue-300">
      {currentUser?.emailAddresses[0]?.emailAddress}
    </div>
  )
}
```

This reads the primary email address property and removes the absolute positioning styles.

The navigation header should now look similar to:

![Navigation header](https://clerk.com/_media/blog/redwoodjs-blog-tutorial-with-clerk/c013386659d283218c0ea71a36cc353597168e6b-1778x166.png)

(Displaying your own account of course.)

Clerk makes it super easy to add in these authentication components. There are more options for customization available as well.

Now that you have an authenticated user, you should be able to safely navigate to http://localhost:8910/admin/posts and manage the blog posts.

That’s really all there is to it.

## Going deeper

If you’d like to go deeper into the forest (really stretching this metaphor here), you could try your hand at the following:

- Update the Login and Sign Up pages with [mounted Clerk components](https://clerk.com/docs/components/authentication/sign-in.md)
- Add `roles: ['admin']` to the user public metadata to [implement role-based access control](https://clerk.com/docs/guides/basic-rbac.md)
- Go outside and visit the [Redwood National and State Parks](https://www.nps.gov/redw/index.htm) to see these majestic trees in person
- Connect with other developers or say hi in our [Discord community](https://clerk.com/discord) 👋


---

# How We Roll – Chapter 8: Sessions
URL: https://clerk.com/blog/how-we-roll-sessions.md
Date: 2023-07-21
Category: Company
Description: How We Roll is a deep dive into how Clerk implements authentication. This chapter covers how Sessions unlock security and performance capabilities for Clerk.

Welcome to How We Roll! This series is meant to help product owners, developers, and security professionals understand exactly how we implement (or, roll) authentication at Clerk.

## Chapter 8: Sessions

One of the primary objectives of Clerk is to ensure application security while providing the developer with ways to adjust it. Clerk’s auth is configured for a smooth user experience by default, but developers can enable additional layers of security like [multi-factor auth](https://clerk.com/docs/authentication/custom-flows/multifactor.md) depending on the needs of the business.

Sessions is another tool in the authentication toolkit that allows fine-tuning of application security and user experience. A session is an abstract concept that refers to the period of time that a user is signed-in to an application. Like most abstract concepts, it can be modeled and designed to fit your needs.

Before describing Sessions, it’s helpful to grasp the idea of Clients.

### Clients

If a Session is the period of time a user is logged in, the Client is the device with which the user is logged in. Clients can be browsers, native applications, or any other medium that is usually the requesting part in a request/response architecture.

It’s also helpful to think of a Client as a running instance of ClerkJS. When the ClerkJS library is loaded into a browser by an application, it creates an active Client instance. A Clerk Client supports connecting to multiple sessions. This allows users to be logged in to multiple accounts at the same time and easily switch between them.

To learn more about multi-session handling [read the documentation](https://clerk.com/docs/authentication/multi-session-applications.md).

Clerk stores information about the Client and the device it’s running on. This allows users to easily identify which devices they have logged in with and sign that device out of their account. This feature is crucial in case the device gets lost or stolen, or an account gets compromised.

![How We Roll Sessions guide illustration](https://clerk.com/_media/blog/how-we-roll-sessions/142db168fc61365864c470ef858a2001e034bc73-1818x1424.png)

### Creating a Session

To achieve the “Sign out of this device” functionality, Clerk stores the Session that is created when a user logs in. This Session object stores a reference to the Client that was used to create it. In the account security section, Clerk shows all the Sessions for the current user along with the Client information, and when the Session was created to further help identify what devices should and should not be signed in. Signing out from a Client is as simple as deleting the Session object.

Sessions have a maximum lifetime that can be adjusted on the Clerk Dashboard in the Sessions tab. If the application attempts to authenticate with an expired session, the authentication will fail and the user will have to log in again.

[View video](https://clerk.com/_media/blog/how-we-roll-sessions/8a3855ff21760e0335362b4b6aee9062dee0adb3-1060x720.mp4)

Upon sign-in, a reference to the created Session is stored in the `__client` cookie. This cookie is _Secure_ and _HttpOnly_, so it’s inaccessible to [MitM](https://developer.mozilla.org/en-US/docs/Glossary/MitM) and [XSS](https://developer.mozilla.org/en-US/docs/Web/Security/Types_of_attacks#cross-site_scripting_xss) attacks.

From here, this cookie can be used to authenticate with an application. When an HTTP request is received, the cookie can be used to fetch the Session object which has the user ID. If the Session doesn’t exist, the user has signed out of this Client, and the request would throw an Unauthorized error.

However, this process adds extra overhead to the request by introducing a database call. Usually developers attempt to mitigate this overhead by storing the Session object in memory, or in a low-latency store such as a Redis cache. This reduces the cost of fetching the Session object, but requires additional infrastructure to scale.

### Web APIs love JWTs

[JWTs](https://clerk.com/blog/guide-jwt-authentication-json-web-tokens.md) were invented primarily to solve this additional overhead problem. Since JWTs can be verified to have been generated on a trusted server, the contents of the JWT can be trusted. This means Clerk can encode the Session object into a JWT, which the Client will use to authenticate with the application. When the application receives an HTTP request, the verified token can be used to access the Session object and process the request, instead of having to fetch the Session object from Clerk’s Backend API. The overhead required to verify a JWT is significantly lower than fetching data over a network. This Session token is stored in the `__session` cookie where it’s accessible to the Client. Alternatively, the Client can store this Session token in the browser’s local storage or a native equivalent, and pass it to the server through the Authorization HTTP header.

**JWKS refresher:** [JSON Web Key Set (JWKS)](https://medium.com/javarevisited/json-web-key-set-jwks-94dc26847a34) is a way for an application to advertise the public key that can be used to verify that a token was generated and signed by that application. Clerk applications expose their public keys at the `clerk.your-site.com/.well-known/jwks.json` endpoint.

When an API receives a request with a token, the JWKS is used to verify that the token was generated by Clerk. The API server fetches the JWKS at startup time and stores it in memory to save the network latency of fetching JWKS on demand. JSON Web Keys are stable and don’t need to be refreshed.

However, since the Session object is now stored on the Client that created it, only this Client is able to invalidate or terminate the session. This removes the ability to remotely sign out from a specific device. So while JWT Sessions solve the extra overhead, they disable a key security feature.

### It Always Comes Down To Cache Invalidation

Since the ability to remotely sign out of devices is a crucial feature, the source of truth has to be the Session object stored on the server. It cannot be the one stored on the Client. But fetching from the database is expensive. Whereas the JWT essentially acts as a cached version of the Session object that can never be programmatically invalidated. It’s the other extreme of the spectrum.

Fortunately, JWTs have a lifetime of their own and can be set to expire at some point in the future. When Clerk generates a Session token for a sign-in, the token is set to expire 60 seconds into the future. This Session token can be used to authenticate for the next 60 seconds. A database fetch for the Session is only required once the token has expired and a new token needs to be generated.

When a Session is deleted (user signs out of a device), new tokens cannot be generated, but the most recently generated token can still be used if it was generated less than 60 seconds ago. This guarantees that authentication states in an application will never be invalid for more than 60 seconds.

This approach allows Clerk to offer highly performant authentication without compromising on the security benefits of persistent Sessions.

### Inactivity

Generating short-lived tokens for a long-lived session comes with an additional benefit - it is a great indicator of user activity. If the user stops interacting with the application for more than 60 seconds, a new Session token is not generated. The creation time of the most recent session token can be used by Clerk to determine when the user was last _using_ the application instead of just being logged in.

Clerk allows developers to enable Inactivity timeout - this is the maximum amount of time the user can be away from the application and come back to it without having to log in again. Inactivity timeout can also be set on the Clerk Dashboard in the Sessions tab.

[View video](https://clerk.com/_media/blog/how-we-roll-sessions/a9662b29b31bc473213b3a21e3fe4b00c929c811-1060x720.mp4)

### Dynamic Permissions

Sessions are not only created and destroyed - they can also be mutated within their lifetime. The most common use case for mutating Sessions is changing permissions or authorization policies. While a user is logged into the application, they might get added to or removed from organizations, or their roles within an organization could change.

Clerk saves this information in the Session object and ensures it’s updated so that new Session tokens can cache it and the application can process the request without making additional calls to Clerk.

Clerk also allows customization of the Session tokens. Developers can add additional claims to the Session token in the Clerk Dashboard. Shortcodes can be used to inject user data and metadata. In this example, a new claim `verified` is added to the token. Users with an unverified email address will have this claim set to `false` in the token. Once they verify their email, the next Session token that is generated will have this set to true, so any access rules depending on this claim will work as expected.

[View video](https://clerk.com/_media/blog/how-we-roll-sessions/9af974ad04a3df8a8e75110fc4d74e073000b784-1060x720.mp4)

To learn more about Session token customization [read the documentation](https://clerk.com/docs/backend-requests/making/custom-session-token.md).

## Summary

Sessions are a very powerful tool for enabling security capabilities like multi-sign-in, inactivity timeout, remote sign-out, and dynamic permissions. Clerk takes on the burden of implementing the complex mechanism of Session handling so that developers have access to a performant and flexible authentication system that is easy to integrate.

To learn more about the elements of session management and relevant security concerns, check out [this blog post](https://clerk.com/blog/what-is-session-management.md).

## How We Roll Series Index

- [How We Roll – Chapter 1: Passwords](https://clerk.com/blog/how-we-roll-passwords.md)
- [How We Roll – Chapter 2: Avatars](https://clerk.com/blog/how-we-roll-avatars.md)
- [How We Roll – Chapter 3: Multifactor](https://clerk.com/blog/how-we-roll-multifactor.md)
- [How We Roll – Chapter 4: Email Verification](https://clerk.com/blog/how-we-roll-email-verification.md)
- [How We Roll – Chapter 5: Customization](https://clerk.com/blog/how-we-roll-customization.md)
- [How We Roll – Chapter 6: User Profile](https://clerk.com/blog/how-we-roll-user-profile.md)
- [How We Roll – Chapter 7: JWT Single Sign-On](https://clerk.com/blog/how-we-roll-jwt-sso.md)
- [How We Roll – Chapter 8: Sessions](https://clerk.com/blog/how-we-roll-sessions.md)
- [How We Roll – Chapter 9: Infrastructure](https://clerk.com/blog/how-we-roll-infrastructure.md)
- [How We Roll – Chapter 10: Roundup](https://clerk.com/blog/how-we-roll-roundup.md)


---

# How We Roll – Chapter 7: JWT Single Sign-On
URL: https://clerk.com/blog/how-we-roll-jwt-sso.md
Date: 2023-07-14
Category: Company
Description: How We Roll is a deep dive into how Clerk implements authentication. This chapter covers how Clerk integrates with BaaS providers with JWT SSO.

Welcome to How We Roll! This series is meant to help product owners, developers, and security professionals understand exactly how we implement (or, roll) authentication at Clerk.

## Chapter 7: JWT Single Sign-On

Clerk offers [seamless integration](https://clerk.com/docs/integration/overview.md) with Backend as a Service (BaaS) providers like [Firebase](https://firebase.google.com), [Supabase](https://supabase.com), and [Convex](https://www.convex.dev). BaaS providers enable developers to build applications quickly without worrying about the backend and infrastructure, similar to what Clerk does for auth. These providers abstract complex infrastructure logic and make it accessible to the front-end client through simple APIs and SDKs.

With that being said, any time you are accessing data from the client, there is a security concern; proper authentication and authorization is paramount, which is why these providers enable developers to configure security rules.

![How We Roll Jwt Sso guide illustration](https://clerk.com/_media/blog/how-we-roll-jwt-sso/14852af290484142fa8bcd2f2d9db1925a8261cc-1346x344.png)

Clerk's officially supported integrations with these providers allow developers to seamlessly leverage Clerk for authentication in applications that depend on a BaaS. This is achieved through a concept called **JWT Single Sign-On**.

### Web APIs love JWTs

A JSON Web Token (JWT, pronounced _jot_) is a JSON string that is cryptographically signed and base64 encoded. Anyone can decode and read this key, but it can only be generated and verified using a secret key (or a private-public key pair). It’s like a passport that web apps create to give users access.

Claims are the credentials encoded in a JWT that are used to decide what resources the user has access to. If a JWT is a passport, claims are the contents of the passport, including your name, date of birth, passport number, and any stamps.

To learn more about JWTs, check out [this blog post](https://clerk.com/blog/guide-jwt-authentication-json-web-tokens.md). Or implement JWT auth from scratch with [this blog post](https://clerk.com/blog/adding-jwt-authentication-to-react.md).

### JWT Single Sign-On

JWT SSO is conceptually similar to OIDC or SAML Single Sign-On - it enables multiple services to use a single identity provider.

**SAML refresher:** Security Assertion Markup Language is an XML-based protocol that enables Single Sign-On, similar
to OIDC. SAML is used heavily in enterprise environments with a central auth system that issues XML tokens to
applications when a user needs to authenticate.

OIDC and SAML providers act as a source of identity for a user. They provide information about the user, like email address, name, avatar, and roles.

JWT SSO providers essentially share the logged-in session of the user with the services. They provide a token that represents not just the user, but the fact that the user _recently_ signed in. If these tokens are short-lived, they can be regenerated, as long as the user is still logged in. JWT SSO allows the user to “be logged in” to multiple services (for example Clerk and Supabase) at the same time.

Clerk achieves this by generating a custom JWT for the signed-in user, which can then be used to make API requests to the provider. Developers can configure **JWT templates** in the Clerk Dashboard to generate these custom tokens.

```tsx
try {
  const token = await Clerk.session.getToken({ template: 'template_name' })
  // use token to call external service
} catch (e) {
  // handle error
}
```

### JWT Templates

To generate custom JWTs on the client, developers can configure a JWT template in the Clerk Dashboard. The template provides all the configurations necessary for JWT SSO to work with various providers.

[View video](https://clerk.com/_media/blog/how-we-roll-jwt-sso/ec12bfde008cd3169de44a27cfdeb6880be8c47d-1060x720.mp4)

These are some of the configuration options for JWT templates available on the Clerk Dashboard.

#### Token lifetime

Based on caching or security policies, developers can configure how long the token should be valid for. A long-lived token can be generated once, cached, and reused. A short-lived token has to be generated every time a request is made.

#### Custom signing key

Different providers have different ways to validate a JWT that they did not generate. For example, Firebase and Supabase require the tokens to be generated using their own secret. Developers can get this secret from the provider's dashboard, and configure the JWT template to use this secret key in the Clerk Dashboard.

When this token is generated and sent to the provider, the provider will be able to validate the token since it was generated using their key.

#### Issuer defined key

Other providers like Convex do not require using their own secrets. Instead, they can be configured with a public key or with **JSON Web Key Set** (JWKS).

A **JSON Web Key** is a public key that can be used to validate a token but cannot be used to generate one. An auth provider (issuer) like Clerk exposes its JSON Web Keys in the JWKS endpoint, which can be used by external providers to verify if a JWT was generated by Clerk. Similar to the JWT secret, the JWKS is unique to each application on Clerk.

Services like Convex allow developers to define an Issuer and a JWKS endpoint, which tells the service where to find the JWKS to validate the tokens. Both the Issuer URL and JWKS URL are available on the JWT Template configuration page on the Clerk DashboardTemplate page.

#### Custom Claims

Along with validating that the token was securely generated, data providers also need to know who the user is to check against security rules.

Most providers expect specific claims in the JWTs, optionally within a namespace. Clerk has pre-built JWT templates for popular services, and the templates are already configured with custom claims that the specific services look for. Within custom claims, handlebars-style templating can be used to include user information with shortcodes.

```json
{
  "aud": "convex",
  "name": "{{user.full_name}}",
  "nickname": "{{user.username}}",
  "picture": "{{user.image_url}}",
  "given_name": "{{user.first_name}}",
  "family_name": "{{user.last_name}}",
  "email": "{{user.primary_email_address}}",
  "phone_number": "{{user.primary_phone_number}}",
  "email_verified": "{{user.email_verified}}",
  "phone_number_verified": "{{user.phone_number_verified}}",
  "updated_at": "{{user.updated_at}}"
}
```

## Summary

Clerk strives to be a complete auth solution with an exceptional developer experience, and integrating with BaaS providers is an important part. Clerk’s JWT Single Sign-On enables this through session-sharing, or sharing the logged in state of the user with the BaaS providers, so developers can focus on building applications with minimal glue code or configuration required.

To learn more about the integrations supported by JWT SSO, check out our [Integration docs](https://clerk.com/docs/integration/overview.md).

## How We Roll Series Index

- [How We Roll – Chapter 1: Passwords](https://clerk.com/blog/how-we-roll-passwords.md)
- [How We Roll – Chapter 2: Avatars](https://clerk.com/blog/how-we-roll-avatars.md)
- [How We Roll – Chapter 3: Multifactor](https://clerk.com/blog/how-we-roll-multifactor.md)
- [How We Roll – Chapter 4: Email Verification](https://clerk.com/blog/how-we-roll-email-verification.md)
- [How We Roll – Chapter 5: Customization](https://clerk.com/blog/how-we-roll-customization.md)
- [How We Roll – Chapter 6: User Profile](https://clerk.com/blog/how-we-roll-user-profile.md)
- [How We Roll – Chapter 7: JWT Single Sign-On](https://clerk.com/blog/how-we-roll-jwt-sso.md)
- [How We Roll – Chapter 8: Sessions](https://clerk.com/blog/how-we-roll-sessions.md)
- [How We Roll – Chapter 9: Infrastructure](https://clerk.com/blog/how-we-roll-infrastructure.md)
- [How We Roll – Chapter 10: Roundup](https://clerk.com/blog/how-we-roll-roundup.md)


---

# Migrating from Pages Router to App Router: An Incremental Guide
URL: https://clerk.com/blog/migrating-pages-router-to-app-router-an-incremental-guide.md
Date: 2023-07-03
Category: Guides
Description: Already know the /pages directory? Here's a simple way to migrate to the /app directory in Next.js 13.

The Next.js [App Router](https://nextjs.org/docs/app) (in the **/app** directory) is a new way to build React applications. If you're already familiar with the [Pages Router](https://nextjs.org/docs/pages) (in the **/pages** directory), Next.js has made it really easy to adopt the App Router incrementally, quite literally on a page-by-page basis. This guide explains how.

## How is this guide different?

The App Router already has a [migration guide](https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration), so how is this different?

We want to demonstrate a 1-to-1 mapping of Pages Router to App Router, but this is not a complete migration. In the snippets below you will see obvious potential refactors, and **that is on purpose.**

As an example, one App Router snippet below still has function called `getServerSideProps`. It doesn't make sense to keep that name, but we want to demonstrate how `getServerSideProps` can be expressed in the context of the App Router.

One more disclaimer: this will not explain how to migrate _everything_. We focused on the best practices for the Pages Router in Next.js 12.3, but left out older APIs like `getInitialProps`.

## One quick clarification

You probably know that the App Router supports both **Client Components** and the newly introduced **Server Components**.

Before the App Router, Client Components were just called Components. We want to clarify that after the App Router, **absolutely nothing has changed about them.**

Most importantly, within the App Router, **Client Components** are still rendered on the server, then hydrated on client. Search engine crawlers can still index their HTML.

Within this guide, the React code from your Pages Router will be copied to new files and labeled with `"use client"` at the top. This is expected, since we're doing a 1-to-1 mapping.

## Migrating from the Pages Router to the App Router

### 0. Create the /app directory

Before you can get started with the App Router, you will first need to create a **/app** directory as a sibling to your **/pages** directory.

### 1. Migrate /pages/\_document to the App Router

If you have a [Custom Document](https://nextjs.org/docs/pages/building-your-application/routing/custom-document) at **/pages/\_document.tsx**, it should look something like this, though likely with some customization:

```tsx
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
```

We need to convert this into a [Root Layout](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#root-layout-required), which can be treated as a 1-to-1 corollary to a Custom Document:

1. Clone **/pages/\_document.tsx** into **/app/layout.tsx**. We will keep both files since we're doing incremental adoption. (If you use .jsx that is no problem, you can use layout.jsx instead)
2. Remove the **next/document** import line entirely
3. Replace `<Html>` and `</Html>` with the lowercase, HTML equivalent `<html>` and `</html>`. For accessibility, it's best to add a language to your opening tag, like `<html lang="en">`
4. Replace `<Head>` and `</Head>` with the lowercase, HTML equivalent `<head>` and `</head>`. If you only have a self-closing `<Head />`, you can remove it entirely
5. Replace `<Main />` with `{children}`, and update the default function export to accept a `{children}` argument. For Typescript users, `children` is of type `React.ReactNode`
6. Remove `<NextScript />` entirely

When complete, **/app/layout.tsx** should look more like this, plus your customizations:

```tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}
```

**Important: /app/layout.tsx is required** in the **/app** directory. If you do not have a Custom Document, you can copy-paste the above sample directly into **/app/layout.tsx**.

### 2. Migrate /pages/\_app.tsx to the App Router

**Note:** If you do not have a file at **/pages/\_app.tsx** you can skip to Step 3.

If you have a [Custom App](https://nextjs.org/docs/pages/building-your-application/routing/custom-app) at **/pages/\_app.tsx**, it should look something like this, though likely with some customization:

```tsx
import type { AppProps } from 'next/app'

export default function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />
}
```

The **/app** directory does not have a 1-to-1 corollary for a Custom App, but it can easily be expressed in the new structure:

1. Clone **/pages/\_app.tsx** into **/app/ClientLayout.tsx**. We will keep both files since we're doing incremental adoption. (If you use .jsx that is no problem, you can use ClientLayout.jsx instead)
2. Add a new line to the top of the file that reads `"use client"` (with the quotes)
3. Replace the default export's function signature. Instead of taking `Component` and `pageProps` arguments, it should only take a `children` argument. For Typescript users, `children` is of type `React.ReactNode`.
4. Replace `<Component {...pageProps} />` with `<>{children}</>`, or just `{children}` if you have another wrapping element
5. If there are any remaining references to `pageProps`, please comment them out for now, and revisit them on a page-by-page basis. Next.js has added a new [metadata API](https://nextjs.org/docs/app/building-your-application/optimizing/metadata) that should normally be used in place of accessing `pageProps` here
6. We recommend changing the default export name from `MyApp` to `ClientLayout`. It is not strictly necessary, but it is more conventional

When complete, **/app/ClientLayout.tsx** should look more like this, plus your customizations:

```tsx
'use client'

export default function ClientLayout({ children }: { children: React.ReactNode }) {
  return <>{children}</>
}
```

Now, this is where things get a little different:

- In the Pages Router, **/pages/\_app.tsx** is a "magic" layout file that is automatically added to the React tree
- In the App Router, the only layout file automatically added to the React tree is the Root Layout from Step 1. So, we will need to manually import and mount our `ClientLayout` inside **/app/layout.tsx**

Open **/app/layout.tsx**, import ClientLayout, and use it to wrap `{children}`. When complete, your Root Layout should look like this, plus any customizations from Step 1:

```tsx
import ClientLayout from './ClientLayout'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <ClientLayout>{children}</ClientLayout>
      </body>
    </html>
  )
}
```

### 3. Migrate each page to the App Router

Now that your layout has been copied into the App Router, it's time to start migrating your pages one-by-one. There will be a few steps for each page:

1. Create a directory for the page
2. Create one file to handle data fetching
3. Create one file to render the page
4. Remove the Pages Router page

For the avoidance of doubt: yes, we will be splitting your Pages Router page into two files: one for data fetching and one for rendering.

#### 3.1. Create a directory for the page

Both the Pages Router and the App Router are "filesystem routers," but they are organized slightly differently. In the App Router, each page gets its own directory. Here is how to determine the directory name:

- If your file is named **index.tsx**, create the same parent directory structure
  - For **/pages/foo/index.tsx**, create **/app/foo**
  - For **/pages/index.tsx**, you already have **/app**
- If your file is **not** named **index.tsx**, create a directory with that filename
  - For **/pages/bar.tsx**, create **/app/bar**
  - For **/pages/baz/[slug].tsx**, create **/app/baz/[slug]**
  - For **/pages/baz/[[...slug].tsx**, create **/app/baz/[[...slug]]**

#### 3.2. Create a file to handle data fetching

Inside your page directory, create a file called **page.tsx** to handle data fetching. Copy-paste the following snippet as the foundation of this file (**Note:** we will create **ClientPage.tsx** in 3.3.):

```tsx
import ClientPage from './ClientPage'

export default async function Page() {
  return <ClientPage />
}
```

If your Pages Router file does not have any data fetching, you can continue on to the next step. Otherwise, find your data fetcher below to learn how it can be migrated:

**Migrating getStaticProps to the App Router**

Consider the following is your implementation of `getStaticProps`:

```typescript
export const getStaticProps: GetStaticProps<PageProps> = async () => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}
```

To migrate this with as little modification as possible, we will:

1. Copy-paste `getStaticProps` into **page.tsx**
2. Call `getStaticProps` from within our `Page` component
3. Add `export const dynamic = "force-static"` so the page data is fetched once and cached, not refetched on every load
4. Pass the result to our (not yet created) `ClientPage` component

Here is the end result:

```tsx
import ClientPage from './ClientPage'

export const getStaticProps: GetStaticProps<PageProps> = async () => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}

export const dynamic = 'force-static'

export default async function Page() {
  const { props } = await getStaticProps()
  return <ClientPage {...props} />
}
```

**Migrating getServerSideProps to the App Router**

Consider the following implementation of `getServerSideProps`:

```typescript
import { getAuth } from '@clerk/nextjs/server'

export const getServerSideProps: GetServerSideProps<PageProps> = async ({ req }) => {
  const { userId } = getAuth(req)

  const res = await fetch('https://api.example.com/foo', {
    headers: {
      Authorization: `Bearer: ${process.env.API_KEY}`,
    },
  })
  const data = await res.json()
  return { props: { data } }
}
```

To migrate this with as little modification as possible, we will:

1. Copy-paste `getServerSideProps` into **page.tsx**
2. Add `export const dynamic = "force-dynamic"` so the page data is refetched on every load
3. Replace any usage of `req` with the App Router equivalent
4. Our example uses [Clerk for authentication](https://clerk.com/nextjs-authentication), so the end result will replace this line with its App Router-compatible replacement
5. Replace `req.headers` with the new [headers() helper](https://nextjs.org/docs/app/api-reference/functions/headers)
6. Replace `req.cookies` with the new [cookies() helper](https://nextjs.org/docs/app/api-reference/functions/headers)
7. Replace `req.url.searchParams` with the new [searchParams helper](https://nextjs.org/docs/app/api-reference/file-conventions/page#searchparams-optional)
8. Replace any Dynamic Route segment usage with the new [params helper](https://nextjs.org/docs/app/api-reference/file-conventions/page#params-optional)
9. Call `getServerSideProps` from within our `Page` component
10. Pass the result to our (not yet created) `ClientPage` component

Here is the end result:

```tsx
import { auth } from '@clerk/nextjs'
import ClientPage from './ClientPage'

export const getServerSideProps: GetServerSideProps<PageProps> = async () => {
  const { userId } = auth()

  const res = await fetch('https://api.example.com/foo', {
    headers: {
      Authorization: `Bearer: ${process.env.API_KEY}`,
    },
  })
  const data = await res.json()
  return { props: { data } }
}

export const dynamic = 'force-dynamic'

export default async function Page() {
  const { props } = await getServerSideProps()
  return <ClientPage {...props} />
}
```

**Migrating getStaticPaths to the App Router**

Consider the following implementation of `getStaticPaths`:

```typescript
export async function getStaticPaths() {
  return {
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
  }
}
```

In the App Router, this implementation barely changes. It's simply given a new name (`generateStaticParams`) and the output is transformed to something simpler. That means you can use your old implementation directly, and simply transform the output.

Here is the end result – we included an example of how it can be used in tandem with `getStaticProps`:

```tsx
import ClientPage from './ClientPage'

export async function getStaticPaths() {
  return {
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
  }
}

export async function generateStaticParams() {
  const staticPaths = await getStaticPaths()
  return staticPaths.paths.map((x) => x.params)
}

export const getStaticProps: GetStaticProps<PageProps> = async ({ params }) => {
  const res = await fetch(`https://api.example.com/foo/${params.id}`)
  const data = await res.json()
  return { props: { data } }
}

export default async function Page({ params }) {
  const { props } = await getStaticProps({ params })
  return <ClientPage {...props} />
}
```

#### 3.3. Create a file to render the page

Now that data fetching is ready, we need to configure the rendering. To accomplish this:

- Copy your original Pages Router page into **ClientPage.tsx**
- Remove any data fetching code, since it now lives in **page.tsx**

That's it! We have already configured **page.tsx** to mount this file and pass props, so it should be working.

#### 3.4. Remove the Pages Router page

Now that your page is ready in the App Router, you can delete the old Pages Router variant.

## What's next?

Now that your Pages Router application is working in the App Router, it's time to start taking advantage of the App Router and React Server Components.

In particular, right now your **ClientPage.tsx** files are one big Client Component. Going forward, it's best to refactor this so `"use client"` is used as sparingly as possible, ideally only on small components. A big Server Component importing many small Client Components will lead to less Javascript sent to the client, and a faster experience for your end user.


---

# Social SSO in Next.js
URL: https://clerk.com/blog/social-sso-in-next-js.md
Date: 2023-06-24
Category: Guides
Description: In this article, we explore how to incorporate OAuth SSO into a Next.js project with JSON Web Tokens (JWTs) and the new app router from Next.js.

Authentication has always been a critical aspect of web development, with user data security being paramount.

As the digital world continues to evolve, so does the need for more efficient and secure authentication methods. However, users do not necessarily want to remember secure logins for every app they use.

This is where OAuth Single Sign-On (SSO) comes into play. OAuth simplifies the user authentication process by allowing users to log in with accounts they already have with other services like [Google](https://clerk.com/blog/nextjs-google-authentication.md), Facebook, or Microsoft.

In this article, we will explore how to incorporate OAuth SSO into a Next.js project with [JSON Web Tokens (JWTs)](https://jwt.io/introduction) and Next.js’s new app router, and later see how Clerk, an [authentication service](https://clerk.com/nextjs-authentication), can help simplify this and make it more secure. We will focus on GitHub SSO for simplicity, but most other OAuth providers can be implemented similarly.

Before we get started, if you ever need to look at the full source, code, the [example code is on GitHub](https://github.com/AsyncBanana/nextjs-sso).

## Set up the project

Before we start, make sure you are on Node v18+. You can check this by running `node -v` in a terminal.

### Scaffolding

We will use [create-next-app](https://nextjs.org/docs/getting-started/installation) to scaffold our project. First, you will want to open a terminal in the directory you want to put the project in and run:

```sh
npx create-next-app@latest
```

If you want to use a different package manager, use their own counterpart to `npx`, like `pnpx`. c`reate-next-app` will ask you some questions about your project. Name the project whatever you want; it doesn’t matter. For TypeScript, ESLint, Tailwind, and using `/src`, select no. For the app router, select yes. Finally, leave the import aliases unmodified. After, the output should look like this:

![Social Sso In Next Js guide illustration](https://clerk.com/_media/blog/social-sso-in-next-js/3831e3d2719600d436fc5a7f55c3528434e9b6e0-2000x1250.png)

Now, open that directory in a code editor of your choice. You will need to install jsonwebtoken, which we will use for verifying JWTs.

```sh
npm i jsonwebtoken
```

### Create a GitHub OAuth App

Next, we will need to create the OAuth app in GitHub. Go to [github.com/settings/applications/new](https://github.com/settings/applications/new) and fill out the information. Set the homepage URL to `http://localhost:3000` and the callback URL to `http://localhost:3000/callback` (if you are running the Next.js server on a port other than 3000, you can replace 3000 with that port). You can leave device flow unchecked. Click register and you will be sent to the new application page.

![Social Sso In Next Js guide illustration](https://clerk.com/_media/blog/social-sso-in-next-js/387ca25acbfc80693dda994683b9ed4a0ba430ae-2000x1250.png)

Now, let’s go back to the code for a minute. Create a new file called `.env.local`. This is where you will store your environment variables, which are variables that specify service keys or other configuration that is specific to each deployment and are specified by writing `VARIABLE_NAME=variable_value`, with each variable being on one line.

In the `.env.local` file, create a variable named `NEXT_PUBLIC_GITHUB_OAUTH_ID`. This will contain your GitHub OAuth application’s id. Note that the `NEXT_PUBLIC` prefix tells Next.js to allow the env variable to be accessed by replacing all calls to `process.env.NEXT_PUBLIC_GITHUB_OAUTH_ID` with the value of the variable at build time. If you did not include this prefix, only the server would be able to access the value, which is good for secrets. With that aside, we need to get the GitHub OAuth application id, which you can find on the application dashboard you were sent to earlier. Copy it and paste it into the .env file.

We also need to get a secret, which we will put with the variable `GITHUB_OAUTH_SECRET`. On the dashboard, you can click “Generate a client secret” to get a new secret. Copy it and paste it in the .env file under the new variable.

Finally, we need `JWT_SECRET`, which should be a random password we use for encrypting JWTs. You can use a [password generator](https://passwordsgenerator.net) for this.

That is it for set up! Remember not to give anyone any of the secrets unless you trust them, as they can be used to impersonate users and gain unauthorized access to the application.

## Implement sign in

Our next step is to allow people to sign in by adding a sign in button on the homepage that links to the GitHub OAuth verification page. Open `app/page.js` and insert the following below the Next.js logo (You should be able to find it by looking for an `<Image>` with `src=src="/next.svg"`).

```javascript
<a
  href={`https://github.com/login/oauth/authorize?scope=user:email&client_id=${process.env.NEXT_PUBLIC_GITHUB_OAUTH_ID}`}
  className={buttonStyle.button}
>
  Sign in with GitHub
</a>
```

The link will send people to a page where they can authorize the OAuth app’s access to their account information to allow the app to verify their identity. You might notice `className` contains a style that does not currently exist. We will fix this next. In `/app`, create a file named `button.module.css` and paste the following in.

```css
.button {
  z-index: 2;
  margin: 10px;
  transition-duration: 0.2s;
  display: inline-block;
  font-weight: 600;
  border: 1px solid transparent;
  border-radius: 6px;
  white-space: nowrap;
  padding: 5px 16px;
  font-size: 14px;
  line-height: 20px;
  vertical-align: middle;
  cursor: pointer;
  user-select: none;
  color: #24292e;
  background-color: #fafbfc;
}

.button:hover {
  background-color: #f3f4f6;
}

.button:focus {
  outline: none;
  border: 1px solid #c0d3eb;
  box-shadow: 0 0 0 1px black;
}

.button:active {
  background-color: #edeff2;
}
```

This just provides some simple styling for the button. In order to use it, we need to import it in `page.js`. Add this line to the top of `page.js`.

```jsx
import buttonStyle from './button.module.css'
```

To get the layout correct, we also have to add this to `.center` in `page.module.css`.

```css
flex-direction: column;
```

Now, run `npm run dev` and go to `http://localhost:3000`. You should see this:

![Social Sso In Next Js guide illustration](https://clerk.com/_media/blog/social-sso-in-next-js/247a788c35e5ea1c9dd8c876cbac8cded81fb1ff-3840x2160.png)

If you click “Sign in with GitHub,” you should be redirected to a GitHub page asking you to authorize your OAuth app. However, if you click authorize, you will get a 404 error. That is because we have not implemented a callback page yet, which we will do next.

## Creating a callback

Before we start this step, a bit of explaining is required. You might have seen OAuth flows implemented differently, and this is perfectly fine. There are multiple ways to handle OAuth codes and retrieve access tokens. In this case, we are using [Authorization Code Grant](https://oauth.net/2/grant-types/authorization-code), which is where the OAuth provider (GitHub in this case) sends a request to the specified callback URL (which we are implementing now) with a code. Then, the server sends a request to GitHub with the code, and GitHub responds with the access token. This is generally the most secure method, but for mobile apps or SPAs, it does not always work. With that explained, we will get started on implementing the callback.

You first want to create a folder named `callback` in app and a file named r`oute.js` inside callback. This tells Next.js’s filesystem router that `route.js` should handle API requests sent to `/callback`. Now, paste this into `route.js`:

```javascript
import jwt from 'jsonwebtoken'
import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'

export async function GET(req) {
  const code = new URL(req.url).searchParams.get('code')

  if (!code) {
    return new Response('No code provided', { status: 400 })
  }

  try {
    const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
      method: 'POST',
      headers: {
        accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        client_id: process.env.NEXT_PUBLIC_GITHUB_OAUTH_ID,
        client_secret: process.env.GITHUB_OAUTH_SECRET,
        code,
      }),
    })

    const tokenData = await tokenResponse.json()

    const { access_token } = tokenData

    if (!access_token) {
      return new Response('GitHub login failed', { status: 400 })
    }

    const jwtToken = jwt.sign({ access_token }, process.env.JWT_SECRET, {
      expiresIn: '1h',
    })
    cookies().set('auth', jwtToken, {
      httpOnly: true,
      secure: process.env.NODE_ENV !== 'development',
      sameSite: 'lax',
      maxAge: 3600, // 1 hour
      path: '/',
    })
  } catch (error) {
    console.error(error)
    return new Response('Internal server error', { status: 500 })
  }
  redirect('/dashboard')
}
```

We will go through this step by step. First, we import a few different things:

- `jsonwebtoken` is for creating JWTs, which we use to store the userdata and allow us to verify that bad actors did not change it (we will do this later)
- `cookies` from `next/headers` is for setting cookies on the client. This function is an abstraction over the `Set-Cookie` HTTP header, hence the import location.
- `redirect` from `next/navigation` is for redirecting users. Similar to the `cookies` function, this function abstracts over HTTP responses by automatically responding with an HTTP 3xx status code (read: a redirect) with the `Location` header set to the value passed.

After that, we export a new function named `GET`, which takes `req` as a parameter. This function handles all HTTP requests to `/callback` with the HTTP method `GET`, which is the method used for typical requests that do not contain a body. `req` contains all of the information about the request.

The next part retrieves the code from the `code` query parameter in the URL. You can refer to the explanation at the start of this section to learn how this is used. If there is no code, the function returns a 400 error.

Now that we have the code, we send it back to GitHub to get the access token. After getting the response, we parse the JSON body and extract the access token. If there is no access token, another error is returned.

We sign the token to allow us to store it in a cookie with confidence that it cannot change without the JWT secret. Using the signed token, we set the `auth` cookie for the user. The parameters we passed are very important. `httpOnly` makes sure JavaScript cannot access the cookie’s value, `secure` makes sure that when deployed in production, the cookie cannot be sent over unencrypted HTTP, and `sameSite` prevents the cookie from being sent to third party websites. `sameSite=lax` is the default in modern browsers, but it is still a good idea to make it explicit.

Finally, we redirect the user to `/dashboard`. If you run this code, you should end up at another 404 at `/dashboard`. We will create the dashboard next.

## Creating a protected dashboard

Once again, we need to create a file named `dashboard` and a file inside it named `page.js`. Because this is a page rather than an API route, the naming is different. Copy the following into `page.js`:

```javascript
import { cookies } from 'next/headers'
import jwt from 'jsonwebtoken'
import { redirect } from 'next/navigation'
import buttonStyle from '../button.module.css'

export default async function Page() {
  const auth = cookies().get('auth')
  if (!auth) {
    redirect(
      `https://github.com/login/oauth/authorize?scope=user:email&client_id=${process.env.NEXT_PUBLIC_GITHUB_OAUTH_ID}`,
    )
    return
  }
  const user = jwt.verify(auth.value, process.env.JWT_SECRET)
  const response = await fetch('https://api.github.com/user', {
    headers: {
      Authorization: `token ${user.access_token}`,
    },
    cache: 'no-store',
  })
  const userdata = await response.json()
  return (
    <div>
      <h1
        style={{
          'text-align': 'center',
          'margin-top': '100px',
        }}
      >
        Welcome {userdata.name} to the dashboard!
      </h1>
      <a href="/logout" className={buttonStyle.button}>
        Logout
      </a>
    </div>
  )
}
```

Once again, we will go through this step by step. The imports are largely the same as the callback. The only difference is the addition of `../button.module.css`, which is the CSS file we created earlier for button styling.

This time, instead of a function named `GET`, because this is a page, we export a function named `Page`. Of course, because it is a default export in this case, the naming doesn’t really matter.

Next, we get the auth cookie. If no auth cookie is found, the user is not signed in, so we redirect the user to the sign in.

If there is an auth cookie, we verify the JWT contained in it. This is how we make sure the value was not tampered with. JWTs have a header, payload, and signature. The payload’s value can be accessed without the JWT secret. However, the JWT cannot be modified, as the signature is generated using the JWT secret and payload value. Therefore you need both of those to generate a valid signature. What we are doing here is both decrypting the payload and making sure the signature is valid.

Now that we have verified the JWT and extracted the payload, we use the access token in the JWT to request the user’s data from the GitHub API. The `cache` parameter disables Next.js’s AOT caching/static generation. Normally we would do this inside a `useEffect()` call, but because we are using [React Server Components](https://nextjs.org/docs/getting-started/react-essentials#server-components) with Next.js, this is the idiomatic way of using `fetch()` (remember that this renders once on the server and does not render on the client period). We then parse the response body to get the userdata.

After that, we just have some markup that renders a welcome message with the user’s name and a logout button. We use inline styles for the header because creating another CSS file just for two rules didn’t make sense. You might notice that the logout button links to `/logout`, which does not exist yet. We will fix that.

Tip: If you have lots of protected routes and want to avoid code repetition, you could implement the authentication as
middleware or just a function imported in the relevant routes

## Adding a logout route

This is pretty simple. The first thing to do is to create another route, just like what we did for `/callback`. Create a new folder in `app` called `logout` and a file called `route.js` in the new folder. Insert the following in the new file:

```javascript
import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'

export async function GET(req) {
  cookies().delete('auth')
  redirect('/')
}
```

As you can see, this script is pretty simple. We just intercept GET requests to `/logout`, delete the cookie named `auth`, and redirect the user to the homepage. Note that if the user tries to log in again, it might seem as if they are still signed in, as GitHub will silently send the access token and redirect the user when they click login. However, if you implement a more complete sign in solution, this will allow users to sign in to another account with a different method.

That is all! You now have a basic system for OAuth authentication. However, there are a few issues.

## Problems with this Implementation

While this works, there are some problems:

- There is no protection against CSRF (Cross Site Request Forgery)
- There are no refresh tokens, and access tokens can last indefinitely (this is a limitation of GitHub OAuth apps)
- GitHub is currently the only sign in method (non OAuth sign requires many more security measures due to the need to store information in a database)
- There is support if issues arise with authentication

We could solve most of these problems, but it would take a significant amount of time (this tutorial is already almost 3,000 words) and increase maintenance. However, there is a better solution: you can use a service like [Clerk](https://clerk.com/). Clerk is a user management platform that allows you to easily and securely implement most of the popular OAuth providers along with standard email/password sign in, [magic link/passwordless](https://clerk.com/blog/magic-links.md), and even Metamask.

## Using Clerk for Authentication

Once again, run:

```sh
npx create-next-app@latest
```

and select the same choices as previously (any name, everything “no” except for the app router). Then, run:

```sh
npm install @clerk/nextjs
```

This installs the Clerk SDK for Next.js. Now, we need to set up a Clerk app. Go to [Clerk’s app creation page](https://dashboard.clerk.com/apps/new) (create an account if you did not already) and go through the configuration. For authentication providers, you can stick to just GitHub again or add as many providers as you want. It doesn’t change the process, and you can change it later. After that, you should be redirected to a page where you see a snippet containing `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` and `CLERK_SECRET_KEY`. Copy this and paste it into a new file named `.env.local`. This includes the environment variables that store your public and private Clerk keys.

To allow us to use Clerk React components in our project, we first need to insert the `<ClerkProvider>` component into `layout.js`. Replace all content in `layout.js` with the following:

```javascript
import './globals.css'
import { Inter } from 'next/font/google'
import { ClerkProvider } from '@clerk/nextjs'
const inter = Inter({ subsets: ['latin'] })

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <ClerkProvider>{children}</ClerkProvider>
      </body>
    </html>
  )
}
```

`<ClerkProvider>` provides the context necessary to allow Clerk components to function properly, and due to it being `layout.js`, it is inserted into every page.

Next, we need to create the sign in button, just like in the first version. Open `page.js` in `app` and insert this below the Next.js logo (the image with `src="/next.svg"`):

```javascript
{
  auth().userId ? (
    <a href="/dashboard" className={buttonStyle.button}>
      Dashboard
    </a>
  ) : (
    <SignInButton mode="modal" redirectUrl="/dashboard">
      <button className={buttonStyle.button}>Sign In</button>
    </SignInButton>
  )
}
```

This checks if the user is signed in. If they are, it shows a link to the dashboard, and if not, it shows a button to sign in. To make this work, you will also need to import two things at the top of the file:

```javascript
import { SignInButton, auth } from '@clerk/nextjs'
import buttonStyle from './button.module.css'
```

The first line contains the functions and components needed from the Clerk SDK, and the second is for the styling. You will want the same styling as in the previous version, so create a new file named button.module.css and insert this into it:

```css
.button {
  z-index: 2;
  margin: 10px;
  transition-duration: 0.2s;
  display: inline-block;
  font-weight: 600;
  border: 1px solid transparent;
  border-radius: 6px;
  white-space: nowrap;
  padding: 5px 16px;
  font-size: 14px;
  line-height: 20px;
  vertical-align: middle;
  cursor: pointer;
  user-select: none;
  color: #24292e;
  background-color: #fafbfc;
}

.button:hover {
  background-color: #f3f4f6;
}

.button:focus {
  outline: none;
  border: 1px solid #c0d3eb;
  box-shadow: 0 0 0 1px black;
}

.button:active {
  background-color: #edeff2;
}
```

Then, add this to `.center` in `page.module.css`:

```css
flex-direction: column;
```

Now sign in should work, but we still need to implement the dashboard. First, we need to create a JavaScript file at the project root named middleware.js (make sure to put this at the project root, not/app). Paste the following in the new file:

```javascript
import { authMiddleware } from '@clerk/nextjs'
export default authMiddleware()

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
}
```

This is a basic setup for the [authentication middleware](https://clerk.com/nextjs-authentication). You can configure it more to exclude specific routes, but this should work in most cases.

The next step is to create a folder called `dashboard` and a file named `page.js` inside it, just like with the implementation we already made. Inside the file, paste this:

```javascript
import { currentUser, RedirectToSignIn, SignOutButton } from '@clerk/nextjs'
import buttonStyle from '../button.module.css'

export default async function Page() {
  const userdata = await currentUser()
  if (!userdata) {
    return <RedirectToSignIn />
  }
  return (
    <div>
      <h1
        style={{
          'text-align': 'center',
          'margin-top': '100px',
        }}
      >
        Welcome {userdata.emailAddresses[0].emailAddress} to the dashboard!
      </h1>
      <SignOutButton>
        <button className={buttonStyle.button}>Logout</button>
      </SignOutButton>
    </div>
  )
}
```

We will go through this step by step.

First, we import some packages.

- We import multiple different functions and components from the Clerk SDK. The first, `currentUser()`, helps us get the current user’s information. The second, `RedirectToSignIn`, not to be confused with the function `redirectToSignIn`, which is also exported, is a component that redirects the user to a sign in page. Finally, we have `SignOutButton`, which creates a button to allow the user to log out.
- `buttonStyle` is just CSS from our `button.module.css` file, which we use for the log out button.

Next, we export a function called `Page`, which has been explained previously.

After that, we use `currentUser()` to get the user’s information. If it does not exist (meaning the user is signed out), we redirect to a sign in page using a client side redirect.

Finally, using the userdata, we return markup containing a header with the user’s email and a button to log out.

Now, sign in, the dashboard, and sign out should all work.

## Easy SSO

That’s it! You now should have two implementations of OAuth authentication, one that is hand built and more limited and one that is built with Clerk and more feature rich. If you want to learn more about Clerk, check out the [Clerk Docs](https://clerk.com/docs.md). I hoped you learned something, and thanks for reading!

Interested in exploring more? Look into [Next.js Magic Links](https://clerk.com/blog/magic-links.md) for a seamless, passwordless authentication experience in your Next.js apps.


---

# How We Roll – Chapter 6: User Profile
URL: https://clerk.com/blog/how-we-roll-user-profile.md
Date: 2023-06-23
Category: Company
Description: How We Roll is a deep dive into how Clerk implements authentication. This chapter explores how we help developers ship a fully-featured account management UI.

Welcome to How We Roll! This series is meant to help product owners, developers, and security professionals understand exactly how we implement (or, roll) authentication at Clerk.

## Chapter 6: User Profile

Nothing is more frustrating than when a platform collects your information to create a profile for you, but doesn’t allow you to see what data you gave them, much less make any edits to your data without an extensive phone call or email chain. With that being said, building out an account management dashboard requires a good chunk of time to get right (think building out logic and UI components, in addition to the necessary security checks to protect users and their data), so it makes sense why some companies would push this feature off for later.

Our goal here at Clerk is to make it quick and easy for you to spin up a fully-authenticated, fully-featured application. This is why we make every effort to identify the most difficult, tedious, or time-consuming parts of standing up an authenticated app and package these features into components. One example of this is the `<UserProfile />` component, which allows you to stand up a fully featured account management UI just by dropping it into your code.

### Self service

Giving your users control over their accounts is great way to reduce support traffic and increase user satisfaction. Clerk’s `<UserProfile />` [component](https://clerk.com/docs/component-reference/user-profile.md) gives your users autonomy over their data by allowing them to:

- Update their contact information, including name, email, and phone number
- Add additional login methods such as email, phone, and OAuth providers
- Change their password
- Add additional security measures like MFA or SMS OTP
- Delete their account

Implementing a self-serve feature may seem simple, but security must also be taken into consideration. For instance, a user should not be able to add an email without verifying that they own it. Additionally, the user should not be able to use the email until it has been verified. Finally, if the newly added email becomes the primary email address, the prior primary email should be alerted to the change.

We understand that this is a lot to build, which is why we baked these complexities into the `<UserProfile />` [component](https://clerk.com/docs/component-reference/user-profile.md). It saves developers time and makes users happy, win/win!

### MFA / TOTP

Adding MFA to a user's account is a complex undertaking that involves the following steps:

1. Allow the user to choose which MFA option they want to use, such as application authentication
2. Enable the user to scan a QR code or manually type a code into their preferred MFA application
3. Require the user to provide a code provided by the MFA application or device
4. Provide backup codes in an easily accessible manner

When using Clerk’s `<UserProfile />` [component](https://clerk.com/docs/component-reference/user-profile.md), developers can enable MFA / TOTP on with a single click in the dashboard. If you want to learn more about how Clerk handles MFA check out [chapter 3 of how we roll](https://clerk.com/blog/how-we-roll-multifactor.md).

[View video](https://clerk.com/_media/blog/how-we-roll-user-profile/a41d5f481d46b077c3a063f89bd027a4c8e74f4a-1624x1080.mp4)

### Security

Our Clerk `<UserProfile/>` provides baked in security features such as listing all active devices, and the ability remotely log out a device if the user doesn’t recognize it.

![How We Roll User Profile guide illustration](https://clerk.com/_media/blog/how-we-roll-user-profile/4258d0868dc77144b4d4cb9182f86801d31cd434-1826x1198.png)

This feature ensures that users can keep track of if there are any old or unknown devices with access to their account, but is also immensely helpful in keeping a user's data safe if one of their devices becomes lost or compromised.

### Summary

Account management is a critical and complex element of any application, and it doesn't have to be something you build from scratch. Clerk's `<UserProfile/>` component makes providing your users with a fully functional account management UI a matter of adding a few characters to your app, so you can focus on the core functionality of your application.

Check out the [Clerk Docs](https://clerk.com/docs/component-reference/user-profile.md) to learn more about the `<UserProfile/>` component!

## How We Roll Series Index

- [How We Roll – Chapter 1: Passwords](https://clerk.com/blog/how-we-roll-passwords.md)
- [How We Roll – Chapter 2: Avatars](https://clerk.com/blog/how-we-roll-avatars.md)
- [How We Roll – Chapter 3: Multifactor](https://clerk.com/blog/how-we-roll-multifactor.md)
- [How We Roll – Chapter 4: Email Verification](https://clerk.com/blog/how-we-roll-email-verification.md)
- [How We Roll – Chapter 5: Customization](https://clerk.com/blog/how-we-roll-customization.md)
- [How We Roll – Chapter 6: User Profile](https://clerk.com/blog/how-we-roll-user-profile.md)
- [How We Roll – Chapter 7: JWT Single Sign-On](https://clerk.com/blog/how-we-roll-jwt-sso.md)
- [How We Roll – Chapter 8: Sessions](https://clerk.com/blog/how-we-roll-sessions.md)
- [How We Roll – Chapter 9: Infrastructure](https://clerk.com/blog/how-we-roll-infrastructure.md)
- [How We Roll – Chapter 10: Roundup](https://clerk.com/blog/how-we-roll-roundup.md)


---

# How to Authenticate API Requests with Clerk & Express
URL: https://clerk.com/blog/how-to-authenticate-api-requests-with-clerk-express.md
Date: 2023-06-16
Category: Guides
Description: In this tutorial, we'll explore how to use Clerk with Express to authenticate API requests using middleware.

APIs are essential for building powerful applications that can communicate and share data with other systems.

However, with great power comes great responsibility: it's critical to ensure that only authorized users can access your API, and that requests are properly authenticated and verified. Failure to do so can lead to serious security breaches, data leaks, and other vulnerabilities that can compromise the integrity of your application and put your users at risk.

In this tutorial, we'll explore how to use Clerk with Express to authenticate API requests using `ClerkExpressWithAuth()` and `ClerkExpressRequireAuth()` middleware, and build a secure and robust backend for your application. Let's get started!

## Always authenticate

When developing an API, especially in Express.js or any other framework, it's important to authenticate requests for a number of reasons:

1. **Security**: The most important reason is to maintain the security of your application. By authenticating API requests, you ensure that only authorized clients or users can interact with your API. This reduces the potential for malicious actions such as data theft, unauthorized modification, or even denial of service attacks.
2. **Access Control**: It allows you to control who can access certain resources and operations in your API. For instance, certain resources might only be available to admin users, while others are available to all authenticated users.
3. **Rate Limiting**: When you authenticate a user, you can associate them with a specific usage quota. This can be used to implement rate limiting, preventing any single user from overloading the server with requests.
4. **Data Accuracy**: In many cases, your API's operations will be tied to a specific user's data. For example, a "get user profile" endpoint would need to know which user's profile to retrieve. Authentication provides a way to associate requests with users.
5. **Audit and Logs**: It allows you to keep track of who did what and when. This is very useful when you need to audit the usage of your system.

Implementing express authentication or Node.js authentication is vital for maintaining the integrity, security, and reliable operation of your APIs.

That being said, there might be some API routes that you intentionally leave unauthenticated for various reasons. For instance, a login or registration route needs to be unauthenticated so that users can authenticate or create an account. Similarly, you might provide some public data through your API that doesn't require authentication.

But you should default to authentication. Consider it a component of building as you plan out epics or sprints on APIs. But adding auth doesn’t have to be particularly challenging. You can build this out yourself with middleware functions, but like a lot of elements in authentication, it’s better to use specialized components.

Let’s go through two of these we have at Clerk, `ClerkExpressWithAuth()` and `ClerkExpressRequireAuth()` to see how we can set these up Express authentication and call these endpoints from a client.

You can check out all the code for this tutorial in this [repo](https://github.com/argotdev/express-authentication).

## Authenticating Express API endpoints with Clerk

Before we get to the Clerk specifics, it’s good to define two components of API methods in Express (and elsewhere) that are fundamental concepts to how authentication will work: _callbacks_ and _middleware_.

A **_callback_** function is a function that is passed to another function as a parameter and then invoked by that function at a later time. Callbacks are heavily used in Node.js because it's designed to be asynchronous and non-blocking. When performing I/O operations like making HTTP requests, Node.js can start the operation and then continue executing other code without waiting for the operation to complete. When the operation is complete, the callback function is called with the result.

**_Middleware_** functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle. Middleware functions can perform tasks like modifying the request or response objects, ending the request-response cycle, or invoking the next middleware function in the stack.

In Express, middleware functions are often used as callbacks to handle HTTP requests. When you define a route in Express.js, you provide a callback function that's called whenever a client makes a request to that route. This callback function is also a middleware, because it has access to the `req`, `res`, and `next` objects.

```jsx
app.get('/example', function (req, res, next) {
  // This function is a middleware and a callback
})
```

So, in this sense, middleware functions are a specific type of callback. They're callbacks that are designed to be used in the context of an HTTP request to an Express.js server.

This is what we’re going to do with Clerk. We’re going to use one of two authentication middleware functions as a callback for the request to our API endpoint. Those two middleware functions are:

1. `ClerkExpressWithAuth()` is a lax authentication middleware that returns an empty auth object when an unauthenticated request is made.
2. `ClerkExpressRequireAuth()` is a strict authentication middleware that raises an error when an unauthenticated request is made.

There are subtle but important differences between these two. Let’s go through them.

### Using ClerkExpressWithAuth()

`ClerkExpressWithAuth()` is lax in that when it fails, it still returns an object, not an error.

Let’s get some code up and running to showcase this function. We’ll create a directory called ‘backend’ and make that the current directory:

```bash
mkdir backend && cd backend
```

With that done, we’ll start installing our dependencies for this code. If you don’t already have it, you’ll also need node as this is the runtime we’re building upon. You can grab the latest build from [here](https://nodejs.org/en).

Then you can run `npm init` to create a package.json in that directory. With that we can use npm to install:

- [Express](https://expressjs.com), which is the web framework for Node.js we’re going to use. Express is a great option for running node servers because it’s fast, minimal, and unopinionated.
- [dotenv](https://www.npmjs.com/package/dotenv), which is the node package you need to read environmental variables in node.
- [@clerk/clerk-sdk-node](https://www.npmjs.com/package/@clerk/clerk-sdk-node) is the Node.js SDK for the Clerk user management platform.
- [cors](https://www.npmjs.com/package/cors) allows us to easily call the endpoint from a client

```bash
npm install express dotenv cors @clerk/clerk-sdk-node
```

When they are installed, create a file in your `with-auth` directory called `app.js`:

```bash
touch app.js
```

Then create a `.env` file in the same directory:

```bash
touch .env
```

This is where you’re going to store your `CLERK_API_KEY`. You can find this in your dashboard. Because you are building these routes on the backend, you can use your secret key:

![Clerk Secret Key](https://clerk.com/_media/blog/how-to-authenticate-api-requests-with-clerk-express/c5601e5fd15a61e893bfb2d1a7aea4df6eea06f5-2056x442.png)

Then open this directory with your IDE. If you are using VS Code, you can just type `code .` and you’ll get a window ready in that directory.

Add your secret key to your .env file after `CLERK_API_KEY=key-goes-here`. Add the following code to `app.js`:

```jsx
import 'dotenv/config' // To read CLERK_API_KEY
import { ClerkExpressWithAuth } from '@clerk/clerk-sdk-node'
import express from 'express'
import cors from 'cors'
const port = process.env.PORT || 3000

const app = express()
app.use(cors())
// Use the lax middleware that returns an empty auth object when unauthenticated
app.get('/protected-endpoint', ClerkExpressWithAuth(), (req, res) => {
  res.json(req.auth)
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})
```

Let’s work through this line by line.

- Firstly we have all our imports:
  - `import "dotenv/config"` imports the "dotenv" package and automatically runs its `config` function. This package reads environmental variables from the `.env` file and adds them to `process.env`. Here we need it to access a `CLERK_API_KEY` environment variable.
  - We import `ClerkExpressWithAuth` from the "@clerk/clerk-sdk-node" package. This function is middleware for Express.js that handles authentication with Clerk.
  - We import `express` from the Express.js package
  - `import cors from "cors"` imports the "cors" package, a package used for enabling Cross Origin Resource Sharing (CORS). We’ll need this to aid calling the endpoint from our client.
- We then set a constant `port` to the value of the `PORT` environment variable if it's set, otherwise it defaults to `3000`.
- `const app = express()` creates a new Express application. The application is what is going to run our server.
- `app.use(cors())` adds the CORS middleware to the Express application, enabling CORS.
- `app.get(…)` defines a route for the path "/protected-endpoint" on the Express app. This route has two middleware functions:
  - `ClerkExpressWithAuth`: This is the function that checks the authorization of the incoming request. If the request is authenticated, it sets `req.auth` to an object representing the authenticated user.
  - `(req, res) => { res.json(req.auth); console.log(res.json); }`: This is an anonymous function that takes the incoming request and outgoing response as arguments. It sends a JSON response with the `auth` object from the request, and then it logs the JSON response function to the console.
- The final `app.listen(…)` part of the code starts the server and makes it listen for incoming connections on the specified port. It logs a message to the console indicating that the server is running and listening on that port.

Let’s run this:

```bash
node app.js
```

You should now see that message from in your `app.listen(…)` terminal:

```bash
Example app listening at http://localhost:3000
```

Great! You have a working endpoint. Let’s call that endpoint (`http://localhost:3000/protected-endpoint`) from Postman to see what it returns:

```json
{
  "sessionClaims": null,
  "sessionId": null,
  "session": null,
  "userId": null,
  "user": null,
  "actor": null,
  "orgId": null,
  "orgRole": null,
  "orgSlug": null,
  "organization": null,
  "claims": null
}
```

As we said above, `ClerkExpressWithAuth()` returns “an empty auth object when unauthenticated.” Now, you have a conundrum—you need an authenticated user to check this really works. To do that, we’ll create a quick React frontend client that calls `/protected-endpoint` after authenticating a user.

Keep that app running and open up another terminal. If it opens up in the same directory, make sure you cd .. up a level (you don’t want to create your frontend React app in a subdirectory of your backend—headaches will ensue).

We’ll first install create-react-app to help us (funnily enough) create a react app:

```bash
npm install create-react-app
```

Then run `npx create-react-app my-app` where my-app is the name of your app. Here we’ll go with auth-frontend:

```bash
npx create-react-app frontend
```

Then we’ll `cd frontend` to get into that directory and open with our IDE (again using `code .` if using VS Code).

Again, we’re going to add Clerk to this project, this time using`@clerk/clerk-react`, which is the Clerk React SDK.

We’ll also want to install `isomorphic-fetch` and `es6-promise` to polyfill the Fetch API for browsers that don't support it:

```bash
npm install @clerk/clerk-react isomorphic-fetch es6-promise
```

Like with the backend, you are going to need your Clerk API key. This time though you are going to use your public key as we’re authorizing a frontend client:

![Clerk Publishable Key](https://clerk.com/_media/blog/how-to-authenticate-api-requests-with-clerk-express/60a107564b24f529282c1cda0eaebdfb50345894-2072x360.png)

Create a .env file and then add that key to it like this: `REACT_APP_CLERK_PUBLISHABLE_KEY=key-goes-here`.

Now go to the src/App.js file, remove the boilerplate entirely and add this code:

```jsx
import React from 'react'
import './App.css'
import { ClerkProvider, SignedIn, SignedOut, RedirectToSignIn } from '@clerk/clerk-react'
import Auth from './auth'

if (!process.env.REACT_APP_CLERK_PUBLISHABLE_KEY) {
  throw 'Missing Publishable Key'
}

const clerkPubKey = process.env.REACT_APP_CLERK_PUBLISHABLE_KEY

function App() {
  return (
    <ClerkProvider publishableKey={clerkPubKey}>
      <SignedIn>
        <Auth />
      </SignedIn>
      <SignedOut>
        <RedirectToSignIn />
      </SignedOut>
    </ClerkProvider>
  )
}

export default App
```

We won’t go through this line by line because we’ve taken it entirely, with one exception, from our docs on [getting started with React](https://clerk.com/docs/quickstarts/get-started-with-create-react-app.md). Head there to learn more about Clerk and React.

That one exception is that we’ve swapped out the `<Welcome />` component in the documentation within the `<SignedIn></SignedIn>` component for an `<Auth />` component. Within the src directory add `auth.js` and add this code:

```jsx
//src/auth.js

import fetch from 'isomorphic-fetch'
import React, { useState, useEffect } from 'react'

import { useAuth } from '@clerk/clerk-react'

function Auth() {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)
  const { getToken } = useAuth()

  useEffect(() => {
    const fetchData = async () => {
      try {
        const token = await getToken()
        const response = await fetch('http://localhost:3000/protected-endpoint', {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${token}`,
            mode: 'cors',
          },
        })

        if (!response.ok) {
          throw new Error('Network response was not ok')
        }

        const result = await response.json()
        setData(result)
        setLoading(false)
      } catch (err) {
        setError(err)
        setLoading(false)
      }
    }

    fetchData()
  }, [getToken])

  if (loading) {
    return <div>Loading...</div>
  }

  if (error) {
    return <div>Error: {error.message}</div>
  }

  return (
    <div>
      <h1>Data from API:</h1>
      <p>{JSON.stringify(data, null, 2)}</p>
    </div>
  )
}

export default Auth
```

We will go through this line by line as it shows how you can pass that authentication token to the API endpoint.

- `import fetch from "isomorphic-fetch"` imports the `fetch` function from the `isomorphic-fetch` package.
- The next line imports the `React` default export and the `useState` and `useEffect` named exports from the `react` package. `useState` is a React Hook that lets you add React state to function components, and `useEffect` lets you perform side effects in function components.
- The final import is for the `useAuth` hook from the `@clerk/clerk-react` package. This hook provides access to Clerk's auth-related functionality.
- The `Auth` function component is then declared. Four pieces of state are created using the `useState` hook: `data`, `loading`, and `error` for storing API response data, the loading state, and any error messages, respectively. The `getToken` function is extracted from the `useAuth` hook to allow authentication token retrieval.
- We then create a `useEffect` hook to define a side effect that fetches data from an API when the component is first mounted and whenever the `getToken` function changes.
- Within the `useEffect` hook, the `fetchData` function tries to retrieve a token, then sends a GET request to our `/protected-endpoint`. If the request fails, it sets the error state and stops loading. If it succeeds, it sets the data state to the response data, and stops loading.
  - The critical part of this is the line `Authorization: Bearer ${token}`. Here, we’re passing the authorization token from our now-signed-in-user to our `/protected-endpoint` to use in its own authentication.
- In the rendering part of the `Auth` component, it checks if the `loading` state is true, and if so, returns a "Loading..." message. If there's an error, it displays the error message. Otherwise, it displays the data fetched from `/protected-endpoint`.
- Finally we export the `Auth` component as the default export of this module. This allows the `Auth` component to be imported and used in other parts of the application.

And thus we import that `Auth` and call it within the `SignedIn` function so we can use the authorization token and pass it to `/protected-endpoint`. Within `/protected-endpoint`, the ClerkExpressWithAuth middleware will check whether it is a valid token, and, if so, return a full auth object:

```json
{
  "sessionClaims": {
    "azp": "http://localhost:3000",
    "exp": 1686337111,
    "iat": 1686337051,
    "iss": "https://keen-moray-98.clerk.accounts.dev",
    "nbf": 1686337041,
    "sid": "sess_2QvzpU7hY6lF5GQSjQQHckp8wps",
    "sub": "user_2Qbkhxfu7VCmvM4Xguez0fmMg1c"
  },
  "sessionId": "sess_2QvzpU7hY6lF5GQSjQQHckp8wps",
  "userId": "user_2Qbkhxfu7VCmvM4Xguez0fmMg1c",
  "claims": {
    "azp": "http://localhost:3000",
    "exp": 1686337111,
    "iat": 1686337051,
    "iss": "https://keen-moray-98.clerk.accounts.dev",
    "nbf": 1686337041,
    "sid": "sess_2QvzpU7hY6lF5GQSjQQHckp8wps",
    "sub": "user_2Qbkhxfu7VCmvM4Xguez0fmMg1c"
  }
}
```

Now, on the backend we have our `sessionId` and `userId` and `claims` to use as needed and we know our user is authenticated and allowed to use this API endpoint!

### Using ClerkExpressRequireAuth()

`ClerkExpressRequireAuth` works slightly different when a user is unauthenticated. Whereas `ClerkExpressWithAuth` just returned an empty auth object, `ClerkExpressRequireAuth` returns an error.

Swap out your code in your express app.js for this below:

```jsx
import 'dotenv/config' // To read CLERK_API_KEY
import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node'
import express from 'express'

const port = process.env.PORT || 3000
const app = express()

// Use the strict middleware that raises an error when unauthenticated
app.get('/protected-endpoint', ClerkExpressRequireAuth(), (req, res) => {
  res.json(req.auth)
})

app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(401).send('Unauthenticated!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})
```

Most of this code is the same as the `ClerkExpressWithAuth` example above. The differences are:

- We’re importing the `ClerkExpressRequireAuth` from the Clerk Node.js SDK
- We’re calling that `ClerkExpressRequireAuth` middleware within our app.get() function.
- We now have an error-handling middleware function. If an error occurs in any middleware function that is run before this one (here the `ClerkExpressRequireAuth`), this function will be called. It logs the stack trace of the error and sends a response with the HTTP status code `401`, indicating that the client must authenticate to get the requested response, along with the message `Unauthenticated!`.

And lo and behold, if you call this in Postman you’ll get a 401 and this message:

```
Unauthenticated!
```

This is safer as we aren’t even sharing the structure of our auth object.

If we now call this within our React app though, we do get our auth object because we are authenticated:

```json
{
  "sessionClaims": {
    "azp": "http://localhost:3000",
    "exp": 1686337111,
    "iat": 1686337051,
    "iss": "https://keen-moray-98.clerk.accounts.dev",
    "nbf": 1686337041,
    "sid": "sess_2QvzpU7hY6lF5GQSjQQHckp8wps",
    "sub": "user_2Qbkhxfu7VCmvM4Xguez0fmMg1c"
  },
  "sessionId": "sess_2QvzpU7hY6lF5GQSjQQHckp8wps",
  "userId": "user_2Qbkhxfu7VCmvM4Xguez0fmMg1c",
  "claims": {
    "azp": "http://localhost:3000",
    "exp": 1686337111,
    "iat": 1686337051,
    "iss": "https://keen-moray-98.clerk.accounts.dev",
    "nbf": 1686337041,
    "sid": "sess_2QvzpU7hY6lF5GQSjQQHckp8wps",
    "sub": "user_2Qbkhxfu7VCmvM4Xguez0fmMg1c"
  }
}
```

And with that, you can now authenticate any API endpoint in your Express apps.

## Fast, authenticated endpoints

With Express and Clerk you can get authenticated, production-ready APIs up in a matter of just a few minutes. There is more code in our client that for our endpoint. Using `ClerkExpressWithAuth()` or `ClerkExpressRequireAuth()` you can protect any endpoint and add express authentication or node authentication without the hassle of building it yourself.

This is what you need with authentication—you want it done quickly. That way it’ll actually get done rather than sitting in your backlog queue for months until a dev can get to it. Or an attacker can get to your unprotected endpoints.

Next steps? Check out the code for this tutorial [here](https://github.com/argotdev/express-authentication). Check out Clerk [here](https://clerk.com/) and more about using Clerk for express and node authentication [here](https://clerk.com/docs/request-authentication/nodejs-express.md), and how to take these security elements even further with the [options](https://clerk.com/docs/request-authentication/nodejs-express.md#middleware-options). Learn how to set up Clerk within your client to make user management super simple [here](https://clerk.com/docs/quickstarts/overview.md).


---

# How We Roll – Chapter 5: Customization
URL: https://clerk.com/blog/how-we-roll-customization.md
Date: 2023-06-16
Category: Company
Description: How We Roll is a deep dive into how Clerk implements authentication. This chapter covers the various ways developers can customize Clerk's UI components.

Welcome to How We Roll! This series is meant to help product owners, developers, and security professionals understand exactly how we implement (or, roll) authentication at Clerk.

## Chapter 5: Customization

When you build your brand, you spend hours making sure every color, font, and logo is exactly how you envisioned. When you integrate with a 3rd party product like Clerk, you want to make sure that your brand shines. Clerk empowers developers by offering:

- Highly customizable components
- Custom flows
- Themes for our hosted pages

In this chapter we are going to be talking about how to customize our drop-in components and why we wanted to treat it as a first class experience. Grab a drink and enjoy a deep dive into our `appearance` property.

### Clerk’s Appearance Property

When Clerk introduced customization, we wanted something that wasn’t an afterthought where only minimal items could be changed, like buttons or primary colors. We wanted developers to go as deep as required, and the appearance property allowed this by letting developers:

- Have access to entire themes, like dark mode, and the ability to create a custom theme
- Control the layout
- Have global control of the appearance
- Customize individual components
- Inherit from key branding like fonts, and element sizing
- Integrate with their current CSS method of choice

### Base Themes

The `baseTheme` allows a developer to create a theme for your brand, and can be reused across multiple projects. We provide a package called `@clerk/themes` that allows you to use prebuilt versions that were crafted by Clerk, like our dark theme or shades of purple:

```tsx
import { type AppType } from 'next/app'
import { ClerkProvider } from '@clerk/nextjs'

import { dark } from '@clerk/themes'

const MyApp: AppType = ({ Component, pageProps }) => {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: dark,
      }}
      {...pageProps}
    >
      <Component {...pageProps} />
    </ClerkProvider>
  )
}
```

![How We Roll Customization guide illustration](https://clerk.com/_media/blog/how-we-roll-customization/de3892f51d7ad303f57aea7dc00f088ab22cafbe-1200x630.png)

### Controlling the Layout

The default layouts for Clerk’s sign in and sign up components show the social buttons at the top, with other forms of authentication, like email, below. In similar fashion, when a user signs up for your application, by default, we show the optional fields. For some applications this makes sense, for others, not so much.

This is where our `layout` property can be used. Developers can move social providers, change the default look of the social buttons, hide optional fields, show links to help, privacy policy, and terms and conditions pages, and much more:

```jsx
<ClerkProvider
  appearance={{
    layout: {
      showOptionalFields: false,
      socialButtonsPlacement: 'bottom',
      socialButtonsVariant: 'iconButton',
      helpPageUrl: '/help',
      privacyPageUrl: '/privacy',
      termsPageUrl: '/terms',
    },
  }}
  {...pageProps}
>
  {/* ... */}
</ClerkProvider>
```

![How We Roll Customization guide illustration](https://clerk.com/_media/blog/how-we-roll-customization/de36acd844d0309a5eb94a72f0916415763a7b51-1200x630.png)

### Global Customization

Not every application needs its own theme; it is possible to extend the Clerk `baseTheme` to fit with an application. Examples include globally setting some of the attributes, such as every `primaryButton` element having a green background and the text inside being yellow, or setting all text colors to the company’s brand color.

All of this can be done at the `ClerkProvider` level, allowing developers to speed up the customization of our components:

```jsx
<ClerkProvider
  appearance={{
    elements: {
      formButtonPrimary: {
        backgroundColor: 'green',
        color: 'yellow',
      },
    },
    variables: {
      colorText: 'red',
    },
  }}
  {...pageProps}
>
  {/* ... */}
</ClerkProvider>
```

![How We Roll Customization guide illustration](https://clerk.com/_media/blog/how-we-roll-customization/799b8b17147919db39fba9c505f8a8b73847dec8-1200x630.png)

### Individual Components

Applications are built of components, and individual components may need to be styled in a specific way. For example the Clerk `<UserButton />` might be too small for your sidebar or navigation bar, or the `<UserProfile/>` may not need to show the sidebar.

You can apply the `appearance` property directly to individual Clerk components:

```jsx
import { UserProfile } from '@clerk/nextjs'

export default function Profile() {
  return (
    <div>
      <UserProfile
        appearance={{
          elements: {
            navbar: {
              display: 'none',
            },
          },
        }}
      />
    </div>
  )
}
```

![How We Roll Customization guide illustration](https://clerk.com/_media/blog/how-we-roll-customization/12a76fb56aa7791c8bb545574e5ad0fdff4e9893-1200x630.png)

### Elements and Variables

We’ve talked a lot about the parts that make Clerk customization a first class experience, but the powerful parts are variables and elements. Whether you are globally styling or styling individual components, variables and elements are essential.

The `variables` property is used to adjust the general styles of the base theme, like colors, backgrounds, typography:

```tsx
import { ClerkProvider, SignIn } from '@clerk/nextjs'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ClerkProvider
      {...pageProps}
      appearance={{
        variables: {
          colorPrimary: 'red',
          colorText: 'white',
        },
      }}
    >
      <Component {...pageProps} />
    </ClerkProvider>
  )
}

export default MyApp
```

The `elements` property is used for fine-grained theme overrides, and is useful when styling specific HTML elements. You can find the element to target by inspecting the HTML and looking for the class name.

## Summary

Clerk allows for extensive customization when integrating with third-party products, ensuring brand elements are upheld. Developers can customize individual components, control the layout, modify the global appearance, create custom themes, and adjust the style of base themes through the `appearance`, `baseTheme`, `layout`, `variables`, and `elements` properties, ensuring the brand's unique design and user experience are reflected in every interaction.

For an in-depth look at how to leverage the full power of customization with Clerk, check out the Component Customization [docs](https://clerk.com/docs/component-customization/appearance-prop.md).

## How We Roll Series Index

- [How We Roll – Chapter 1: Passwords](https://clerk.com/blog/how-we-roll-passwords.md)
- [How We Roll – Chapter 2: Avatars](https://clerk.com/blog/how-we-roll-avatars.md)
- [How We Roll – Chapter 3: Multifactor](https://clerk.com/blog/how-we-roll-multifactor.md)
- [How We Roll – Chapter 4: Email Verification](https://clerk.com/blog/how-we-roll-email-verification.md)
- [How We Roll – Chapter 5: Customization](https://clerk.com/blog/how-we-roll-customization.md)
- [How We Roll – Chapter 6: User Profile](https://clerk.com/blog/how-we-roll-user-profile.md)
- [How We Roll – Chapter 7: JWT Single Sign-On](https://clerk.com/blog/how-we-roll-jwt-sso.md)
- [How We Roll – Chapter 8: Sessions](https://clerk.com/blog/how-we-roll-sessions.md)
- [How We Roll – Chapter 9: Infrastructure](https://clerk.com/blog/how-we-roll-infrastructure.md)
- [How We Roll – Chapter 10: Roundup](https://clerk.com/blog/how-we-roll-roundup.md)


---

# How We Roll – Chapter 4: Email Verification
URL: https://clerk.com/blog/how-we-roll-email-verification.md
Date: 2023-06-09
Category: Company
Description: How We Roll is a deep dive into how Clerk implements authentication. From codes to links to SSO, this chapter is about when and how we verify emails.

Welcome to How We Roll! This series is meant to help product owners, developers, and security professionals understand exactly how we implement (or, _roll_) authentication at Clerk.

## Chapter 4: Email Verification

Email verification is a foundational and reusable piece of modern authentication:

- **It’s used during sign-up:** usually to prevent spam accounts, or as a requirement before enrolling a user on a mailing list.
- **It’s used during sign-in:** as a workaround to forgotten password, or as an alternative to passwords altogether.
- **It’s used during account management:** as a mechanism for adding new emails or changing the email for an account.

Although many think of verification links or one-time passcodes (OTPs) as the dominant verification mechanism, both approaches have fallen out-of-favor.

Today, the fastest and most common way to verify emails is actually single-sign on (SSO)! Social SSO (like “Sign in with Google”) and enterprise SSO (like Okta) are already responsible for over half of email verifications, and their adoption continues to grow every year.

This chapter discusses when and how to verify emails, and the tradeoffs of each option. Learn how Clerk handles email verification!

### When to verify

There are two options for when to require email verification: immediately at sign-up, or sometime after completing the signup process.

The most popular approach is to verify immediately at sign-up, which ensures that users will have a valid email, and helps mitigate spam or bot accounts.

[View video](https://clerk.com/_media/blog/how-we-roll-email-verification/17a2d484b76b00aaa42cc46970aeb3de67f4317f-1592x1080.mp4)

In some cases, developers might want to allow signing up without email verification. This is usually done to give users access to some features immediately or for a limited time without jumping through an extra step, also called the foot-in-the-door strategy, while still keeping the bulk of the application behind an email verification check.

To achieve this, developers can turn off verify at sign-up through the Clerk dashboard, then check for email verification in the application to allow access to certain features. The email verification information is available on the [Clerk `User` object](https://clerk.com/docs/reference/clerkjs/user.md) which can be fetched using [the `useUser` hook](https://clerk.com/docs/reference/clerk-react/useuser.md) on the client, or [the `users.getUser` method](https://clerk.com/docs/references/backend/user/get-user.md) on the node SDK.

### How to verify

The core verification mechanism is to send a unique token to the user’s email address. The user will then give this token to the application, verifying that the user owns that email address.

We offer both verification links and one-time passcodes. Developers can enable one of them to enforce that strategy, or enable both and let the users choose during verification.

[View video](https://clerk.com/_media/blog/how-we-roll-email-verification/49da6193d2c1375204585e6719fdd24b8d9ae1eb-1592x1080.mp4)

### One time codes

The more straightforward way to implement verification is with a randomly generated 6-digit code that the user manually types into the application.

[View video](https://clerk.com/_media/blog/how-we-roll-email-verification/df35e4bce4b779d7052b4fcb2b2092a77964fbd8-1712x1080.mp4)

Code verification offers a benefit over links - users don’t need to be signed in to their email account to access the application on a device. Users could be using a different browser or a shared or public device that they don’t want to log into their email account on. This is also the reason why codes are seen a lot more for phone verification.

### Links

Clerk will generate a unique link with a signed JWT when using verification links. This link takes the user to the application where Clerk validates the JWT and signs in the user.

[View video](https://clerk.com/_media/blog/how-we-roll-email-verification/92700966f37a5818a64e6860a59031351ec8ff52-1484x1080.mp4)

The JWT carries the signup attempt information and is only valid for 10 minutes. If the signup was successful, clicking the link again shows this message instead of signing the user in again.

![How We Roll Email Verification guide illustration](https://clerk.com/_media/blog/how-we-roll-email-verification/aa54595c3d97f0d6a8c3076695da5ca706e21083-944x734.png)

Verification links offer a streamlined user experience, but it’s not without tradeoffs. Security-conscious individuals and email clients are suspicious of links in emails, as they could be malicious phishing links or download harmful files. Security policies and training often teach us to be careful with links in emails.

While we offer email verification links, for the aforementioned reasons, we recommend that developers use verification codes in most cases.

### Single Sign-on

As mentioned earlier, Single Sign-On with social providers like Google and enterprise providers like Okta is actually responsible for the majority of email verifications. We ensure that the user experience of Single Sign-On is seamless across various providers with no compromises to security.

Clerk’s SSO uses the Open ID Connect protocol (OIDC), which provides an `email_verified` claim. Identity Providers are supposed to set this to `true` if they have verified the user’s email. Almost every SSO provider verifies emails, so if a user signs up with a social provider, a second email verification step is unnecessary.

**OIDC refresher:** OpenID Connect is an identity protocol built on top of the OAuth 2.0 framework. If a request scope
of OIDC is defined when initiating an OAuth flow, identity providers present the application an ID token along with an
access token on a successful sign-in. The ID token is a JWT that contains some user information like name, email, and
avatar, in the form of “claims”.

Some providers do not verify emails immediately. So if a user signs up with SSO and their email is not verified by the provider, Clerk enforces an additional email verification step.

Some providers do not adhere to the OIDC spec. We audit all providers we support to ensure they are adhering to the spec, and if not, what their own format looks like. For example, the ID token from one of the social providers contains a `verified` claim instead of `email_verified` as defined in the spec, so we check for that. If the provider does not tell us whether the email is verified or not, we assume it’s not verified and force an additional email verification step.

Ensuring SSO providers have verified the user’s email is critical. Clerk provides account linking out of the box, which means users can sign in to the same account using multiple SSO providers as long as the email is the same. However, unless every SSO login verifies the emails, the account could be left vulnerable to takeovers. A malicious user could create a new account on a service that does not verify emails immediately, and use it to log in to an application as someone else. We are very careful with auditing every provider we work with to make sure developers don’t have to worry about the nuances across various providers.

### Summary

Email verification may seem like a straightforward task, but it is a common authentication process on the web that significantly affects both the user experience and application security. Clerk provides multiple options out of the box for developers to customize when and how they enforce email verification.

## How We Roll Series Index

- [How We Roll – Chapter 1: Passwords](https://clerk.com/blog/how-we-roll-passwords.md)
- [How We Roll – Chapter 2: Avatars](https://clerk.com/blog/how-we-roll-avatars.md)
- [How We Roll – Chapter 3: Multifactor](https://clerk.com/blog/how-we-roll-multifactor.md)
- [How We Roll – Chapter 4: Email Verification](https://clerk.com/blog/how-we-roll-email-verification.md)
- [How We Roll – Chapter 5: Customization](https://clerk.com/blog/how-we-roll-customization.md)
- [How We Roll – Chapter 6: User Profile](https://clerk.com/blog/how-we-roll-user-profile.md)
- [How We Roll – Chapter 7: JWT Single Sign-On](https://clerk.com/blog/how-we-roll-jwt-sso.md)
- [How We Roll – Chapter 8: Sessions](https://clerk.com/blog/how-we-roll-sessions.md)
- [How We Roll – Chapter 9: Infrastructure](https://clerk.com/blog/how-we-roll-infrastructure.md)
- [How We Roll – Chapter 10: Roundup](https://clerk.com/blog/how-we-roll-roundup.md)


---

# Secure Authentication in Next.js with Email Magic Links
URL: https://clerk.com/blog/secure-authentication-nextjs-email-magic-links.md
Date: 2023-06-06
Category: Guides
Description: In this guide, you will learn how to implement email magic links in Next.js.

Traditional username and password systems are ubiquitous but mostly suck. Every user needs a complicated random 8-20 character password that they can’t possibly remember for every site. Password managers make this easier, but they are ultimately just papering over the cracks.

Added to this cognitive load for users is the cognitive load for developers, who have to implement these systems securely or constantly worry about their sites becoming targets for malicious activity.

Imagine if you could simplify the user experience, decrease your system’s attack surface, and reduce your workload when it comes to user authentication. This is the promise of [magic links](https://clerk.com/blog/magic-links.md), a powerful approach to passwordless authentication that is rapidly gaining popularity in the world of web development.

Here we want to show you not just the benefits of magic links but how exactly they work, going through an implementation process in Next.js. We’ll also show you why, like most authentication patterns, you don’t want to do this all yourself and how Clerk can help you, just like magic!

## Magical magic links

So, why use magic links? Magic links can greatly improve user experience in several ways:

1. **Ease of use**: Magic links simplify the login process, as users just need to click a link sent to their email to authenticate themselves. They don’t have to remember any usernames or passwords.
2. **Security**: Since there are no passwords to guess, magic links can increase security. This can be especially beneficial for users who often reuse passwords or use weak passwords.
3. **Speed**: Magic links streamline the registration and login process. Rather than having to fill out forms, users just need to enter their email address, then check their inbox and click a link.
4. **Reduced friction**: Magic links eliminate the common frustration of forgotten passwords and the need for password reset processes. 5.**Mobile-friendly**: Typing passwords on mobile devices can be challenging, especially for complex or long passwords. With magic links, users simply click a link in their email, which is much easier on a mobile device.
5. **Trust**: When used properly, magic links can build trust, as they demonstrate a commitment to both user convenience and security.

There are downsides. For one, the user obviously needs to have access to their email. Plus, there is the slight friction element of the user having to leap from the app to their email and back again. In theory, if the user’s email is compromised, an attacker can gain easy access to the app (you can get past this by using [two-factor authentication](https://clerk.com/docs/authentication/custom-flows/multifactor.md) in your authentication flow).

Creating and validating time-sensitive tokens, like those used in magic links, typically involves the following steps:

1. **User Identification**: When the user requests a magic link, your application should first ensure that the email provided is valid and linked to a user account in your system. If the account exists, the server generates a unique, temporary token.
2. **Token Generation**: Generate a unique token using a secure method. This might involve using a secure random number generator or a library or function designed for generating secure tokens, such as JWT (JSON Web Tokens). The token should be associated with the user’s account in your database, along with a timestamp indicating when it was created.
3. **Time-Sensitive Mechanism**: Attach an expiry time to the token. This could be a specific expiry date/time or a duration after which the token will expire. This is usually stored along with the token in the database.
4. **Email Delivery**: Send an email to the user containing the magic link. The link should point to your website or app and include the token as a parameter.
5. **Token Validation**: When the user clicks the magic link, your application should validate the token. This involves checking that the token exists in your database, is linked to a user, and has not expired. If all these checks pass, the user is authenticated.
6. **Token Deletion/Invalidation**: Once a magic link has been used or has expired, it’s important to invalidate it so that it cannot be used again. This can be done by deleting the token from your database or marking it as invalid.

OK, so that’s magic links at a high level. How do you implement them in an application? Let’s go through two ways to do this. Firstly, we’ll show how you can do this with minimal additional libraries in Next.js to show what is required to generate, send, and validate time-sensitive tokens such as magic links. Then we’ll go through how you can implement them quicker and more securely with Clerk.

## Build your own magic links in Next.js

We need to expand the high-level flow above into more granular detail for what we need from our application:

1. **The user enters their email**: The user will enter their email address, which you’ll send to your backend.
2. **Generate a unique token**: On your server, generate a unique token tied to the user’s email. This can be a JWT, a UUID, or some other kind of unique identifier.
3. **Send an email with the magic link**: Include the unique token in the magic link and email it to the user.
4. **User clicks the link**: The user will click the link, which sends the token back to your server.
5. **Verify the token**: On your server, verify that the token is valid and matches the user’s email.
6. **Create a session**: If the token is valid, create a new session for the user and send it back to the client.
7. **Store the session on the client**: On the client, store the session (usually in a cookie or local storage) so that the user remains logged in.
8. **Authorize the user**: Whenever the user makes a request, check that they have a valid session.

So beyond Next.js, for this to work, we need:

- A way to generate and verify our tokens. In this instance, we’re going to use JWT for our tokens and use `jsonwebtoken` to generate and verify them.
- A way to send emails. We’ll use `nodemailer`. You’ll also need SMTP information for your email provider.
- A way to create cookies to store session data. We’ll use the `cookie` library here.

That’s all you need. Let’s first spin up a Next.js app called ‘magic-links’ as the bare bones of what we’ll create:

```bash
npx create-next-app@latest magic-links
```

You’ll be asked a bunch of questions. Here we’re not using TypeScript and neither are we using the App directory (which is the new, better way of using Next.js that we’ll use later. But it doesn’t play as nicely with some of the API routes we’re creating here).

After that we’ll install the necessary packages:

```bash
npm install jsonwebtoken nodemailer cookie
```

You can then run npm run dev to start the development server. At the moment all you’ll get at http://localhost:3000 is the regular Next.js start page:

![image1.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/e31247c8534a6bc92acfb54d8be11422ff7c074e-1999x1264.png)

Obviously we need a login component as the first step. We’ll create a /components directory and add a login.js file:

```jsx
// components/login.js

import { useState } from 'react'

function Login() {
  const [email, setEmail] = useState('')

  const handleSubmit = async (e) => {
    e.preventDefault()
    const res = await fetch('/api/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ email }),
    })
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
      <button type="submit">Send Magic Link</button>
    </form>
  )
}

export default Login
```

So there are two main parts to this component. At the bottom we have the actual form a user will fill in with their email address. As they type their email in, the state of the `email` variable will change to contain their email address.

When the press ‘Send Magic Link,’ The `handleSubmit` function will be called. This function will call a backend api route, `/api/login`. We’re going to send a POST request to this endpoint with the email address in the body.

Let’s add this to our index page. Delete all the boilerplate code within that file and replace it with:

```jsx
// pages/index.js

import { Inter } from 'next/font/google'
import Login from '../components/login'

const inter = Inter({ subsets: ['latin'] })

export default function Home() {
  return (
    <main
      className={`flex min-h-screen flex-col items-center justify-between p-24 ${inter.className}`}
    >
      <div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex">
        <Login />
      </div>
    </main>
  )
}
```

We’re importing the `Login` component and adding it to this page. Now a user will see this at http://localhost:3000:

![image8.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/f92c06581c57df46dfbf7dbd31ce2dafcb0dc877-1999x1264.png)

If they were to add their email into that field and press ‘Send Magic Link,’ guess what would happen?

Absolutely nothing! Let’s make something happen. What we need is that `/api/login` the Login component calls. We’ll create a `login.js` file in the api directory. Though this is within the `pages` directory, it won’t be treated as a page by Next.js, it will act like an API endpoint:

```jsx
// pages/api/login.js

import jwt from 'jsonwebtoken'
import nodemailer from 'nodemailer'

export default async function handler(req, res) {
  const { email } = req.body

  // Create a magic link token
  const token = jwt.sign({ email }, process.env.JWT_SECRET, {
    expiresIn: '15m',
  })

  const transporter = nodemailer.createTransport({
    host: 'mail.example.com',
    port: 587,
    secure: false,
    auth: {
      user: 'username',
      pass: 'password',
    },
  })

  // Generate magic link
  const magicLink = `${req.headers.origin}/api/verify?token=${token}`

  await transporter.sendMail({
    from: '"Your Name" <your-email@example.com>', // sender address
    to: email, // list of receivers
    subject: 'Your Magic Link', // Subject line
    text: `Click on this link to log in: ${magicLink}`, // plain text body
  })

  res.status(200).json({ success: true })
}
```

This is where the first part of the magic of magic links happens. Let’s step through this to see what’s happening:

- First we’re importing the libraries we need, `jsonwebtoken` and `nodemailer`.
- Within our `handler` function, we’ll get the `email` from the body of the request.
- With that email as the payload, we’ll use the sign method from `jsonwebtoken` to create our token. There are two extra parameters we need to pass to sign:
  - A `JWT_SECRET`. You can create a secret (for these purposes, not for production) by running `openssl rand -base64 32` in the terminal to generate a key. You then store that key in a .env file in the root of the project for the project to read.
  - An expiresIn time. Here, we’ve set this to 15 minutes.
- Now we have our token, we need to send it to the user’s email address. Here we’re using the `createTransport` method from `nodemailer` to create an object called a `transporter` that contains all our (i.e. the sender) SMTP email information.
- We’ll then create the actual magic link, which will be the origin URL (our URL) with the token appended as a query.
- Then we’ll call `sendMail` on the `transporter` object to send the email to the recipient

Now if the user presses ‘Send Magic Link,’ they should get an email like this:

![image5.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/e6395766363d25d1f351680920e1e2f63485d730-1999x221.png)

Now if they click on that guess what would happen?

Absolutely nothing!

We need an endpoint to verify the token and set a cookie on the client with the user's email. First, let’s create another file in the api directory, this one called `verify.js`:

```jsx
// pages/api/verify.js

import jwt from 'jsonwebtoken'
import { serialize } from 'cookie'

export default async function handler(req, res) {
  const { token } = req.query

  try {
    // Verify the token - this throws if the token is invalid
    const { email } = jwt.verify(token, process.env.JWT_SECRET)

    // The token is valid, so we create a session
    const sessionToken = jwt.sign({ email }, process.env.JWT_SECRET, {
      expiresIn: '1h',
    })

    res.setHeader(
      'Set-Cookie',
      serialize('auth', sessionToken, {
        httpOnly: true,
        secure: process.env.NODE_ENV !== 'development', // Use secure cookies in production
        sameSite: 'strict',
        maxAge: 3600, // Expires after 1 hour
        path: '/',
      }),
    )

    // Redirect the user to the homepage
    res.writeHead(302, { Location: '/secrets' })
    res.end()
  } catch (err) {
    // The token was invalid, return an error
    res.status(401).json({ error: 'Invalid token' })
  }
}
```

The top part of this is similar to the API route, but let’s step through the entire thing for clarity:

- First we’re importing the libraries we need, `jsonwebtoken` again and cookie for session management.
- Within our `handler` function, we’ll get the token from the query of the request.
- With that token as the payload, we’ll use the verify method from `jsonwebtoken` to verify our token. This again uses our `JWT_SECRET` that we signed it with to verify.
- If that’s a valid token, we’ll then create a session for the user, again using the `sign` method from `jsonwebtoken`. We set an expiresIn time of an hour. After that, our user will be logged out.
- We add the token to our cookie using `serialize` from the `cookie` library, then add the cookie to the headers of our result.
- We’ll then redirect the user to a logged-in-only page

That page, `/secrets` doesn’t yet exist. Let’s create it in the `/pages` directory:

```jsx
// pages/secrets.js

import { useEffect, useState } from 'react'
import { Inter } from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })

export default function Secrets() {
  const [data, setData] = useState(null)

  useEffect(() => {
    // Fetch data from our API route
    fetch('/api/secure-endpoint')
      .then((res) => {
        // If the response was not ok, throw an error
        if (!res.ok) {
          throw new Error('Failed to fetch')
        }
        return res.json()
      })
      .then((data) => {
        setData(data)
      })
      .catch((err) => {
        console.error('An error occurred: ', err.message)
      })
  }, [])

  // Render data or loading message
  return (
    <main
      className={`flex min-h-screen flex-col items-center justify-between p-24 ${inter.className}`}
    >
      <div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex">
        {data ? (
          <>
            <h1>{data.secret}</h1>
            <h2>{data.email}</h2>
          </>
        ) : (
          <p>This isn&apos;t a secret </p>
        )}
      </div>
    </main>
  )
}
```

This will conditionally render either a data object with the fields `secret` and `email` if the user is authenticated, or the text ‘This isn’t a secret’ if they aren’t. The data object comes from a call to our final api endpoint that we need to create, `secure-endpoint.js`:

```jsx
// pages/api/secure-endpoint.js

import jwt from 'jsonwebtoken'

export default function handler(req, res) {
  const { auth } = req.cookies

  if (!auth) {
    return res.status(401).json({ message: 'Unauthorized' })
  }

  try {
    const { email } = jwt.verify(auth, process.env.JWT_SECRET)

    // Now you have the authenticated user's email
    // Do your secure stuff here...

    res.json({ secret: 'This is a secret!', email })
  } catch (error) {
    res.status(401).json({ message: 'Unauthorized' })
  }
}
```

This authorizes the user by verifying with `verify` from `jsonwebtoken` the session token and, if the user is authenticated, passing back an object with a `secret` (‘This is a secret!’) and an `email`. Now if a user fills in their email and clicks on the link, they’ll be sent to the secret page with the `secret` and their `email` showing:

![image4.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/ca4c4a91d3010cf0e8f4e308548af46cb6233c91-1999x1264.png)

That's it! With these routes, you now have a basic magic link authentication system.

## Using Clerk for your magic links

The above code works. It’s also a terrible idea.

We aren’t doing any error handling. We aren’t checking for any edge cases. We’re not overly protective of our JWT token. If an attacker learns your JWT secret, they can create valid tokens and impersonate any user. There’s no rate limiting. The cookie storage isn’t ideal.

Plus we have to have our own email server that is configured to send out a lot of transactional emails (which regular email providers don’t really like as they get punished for spam). And, yeah, we know, our login and authenticated pages aren’t exactly winning any design awards.

Basically, there are a number of issues with rolling your own magic links.

That’s why services like Clerk’s [Next.js authentication](https://clerk.com/nextjs-authentication) exist – to deal with all of the above and make it much easier for developers to implement strong authentication frameworks such as magic links.

We’ll spin up a new Next.js app:

```bash
npx create-next-app@latest magic-links
```

Again, you’ll get the questions. Clerk is written for the latest developments in Next.js, so you can use the App Router.

After that all we need to install is Clerk:

```bash
npm install @clerk/nextjs
```

If we npm run dev now and go to http://localhost:3000 we again get a regular Next.js start page:

![image3.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/4bb435f2579af449d2b3fd21d8e9fef9552cc92f-1999x1264.png)

Before we get to the code, we’ll also want to do some other set up. First, we’ll need our NEXT\_PUBLIC\_CLERK\_PUBLISHABLE\_KEY and our CLERK\_SECRET\_KEY. You can get both of these from your [Dashboard](https://dashboard.clerk.com/~/api-keys).

Add these to an .env file in the root of your project:

```sh
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY = pk_test_xxxx;
CLERK_SECRET_KEY = sk_test_xxxx;
```

We’ll also want to configure our Clerk set up to use magic links. We need to change two settings from the defaults in our dashboard. The first is to choose Email verification link as the authentication factor. To do that, go to **User & Authentication > Email, Phone, Username** in your dashboard:

![CleanShot 2023-06-05 at 15.57.39@2x.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/540c62b637a385ef8cd77f9cdca5044807fbfe6b-3346x2116.png)

Then go to **Contact information** in that subsection and toggle on **Email address** and check **Email Verification Link**:

![CleanShot 2023-06-05 at 15.56.18 2@2x.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/cc5d1162222b94bf1c5be87853f1e248bbdfb9d9-3346x2116.png)

Now we can start with the code. The first step is to wrap our entire Next.js application in the `<ClerkProvider>`:

```tsx
// app/layout.tsx
import './globals.css'
import { Inter } from 'next/font/google'
import { ClerkProvider } from '@clerk/nextjs'

const inter = Inter({ subsets: ['latin'] })

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <ClerkProvider>
      <html lang="en">
        <body className={inter.className}>{children}</body>
      </html>
    </ClerkProvider>
  )
}
```

This is going to provide all we need to pass session and user information to Clerk for the authentication logic. This step is the same for any authentication pattern you are going to use with Clerk in Next.js.

The next step is to use Clerk to protect pages within our application. To do this, we’ll create a file in the `/src` directory. This will use regular expressions to pattern match against the pages you want to protect. Here, we’re going to protect all our pages:

```javascript
//middleware.ts

import { authMiddleware } from '@clerk/nextjs'
export default authMiddleware()
export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
}
```

Now if you load up http://localhost:3000, you’ll be redirected to a login/signup page:

![image9.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/8d71d81b4d43e75cc90dd58eb82a086bbcfac4d8-1999x1264.png)

A user enters their email address here and gets sent a link to click:

![image7.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/b9be271aeb2174a5c010fa2b21b2cfc74dac7d07-1999x965.png)

Clicking on that link sends them back to http://localhost:3000, but now they can access the site again:

![image3.png](https://clerk.com/_media/blog/secure-authentication-nextjs-email-magic-links/4bb435f2579af449d2b3fd21d8e9fef9552cc92f-1999x1264.png)

Much easier (and much better looking signup pages and emails as well!)

## Better security and a user experience with magic links

Magic links can really help you streamline your sign up and sign in processes. They lessen the burden on your users while providing strong security for them and your application.

But implementing them manually puts the burden on your developers. Managing creation and validation of the tokens, sending emails (and maintaining the system to do so), then coding up the right modals, pages, error states, and edge cases is a huge hassle.

It’s worth developers going through and trying this manually just to see how magic links are implemented. But if you are looking for a production-ready option that you can incorporate into your app today, you can use [Clerk](https://clerk.com/).


---

# How We Roll – Chapter 3: Multifactor
URL: https://clerk.com/blog/how-we-roll-multifactor.md
Date: 2023-06-02
Category: Company
Description: How We Roll is a deep-dive into how Clerk implements authentication. This chapter is on something you know and something you have: multifactor authentication!

Welcome to How We Roll! This series is meant to help product owners, developers, and security professionals understand exactly how we implement (or, _roll_) authentication at Clerk.

## Chapter 3: Multifactor

Multifactor authentication, or MFA, is the process of authenticating users in multiple different ways before granting access to their account.

It goes by many names. Technologists seem to have settled on \_multi\_factor authentication because, well, why limit ourselves to two? But _two_ factor authentication is still common and the phrase is used interchangeably.

Within consumer products, though, we've seen the rise of two-_step_ _verification:_

![Chapter 3: Multifactor screenshot](https://clerk.com/_media/blog/how-we-roll-multifactor/53eba8b30ad84278ea863251368d8d3995ca372d-1458x430.png "Google calls the feature \"2-Step Verification\" or 2SV")

Both word substitutions make the concept a little easier to digest, so Clerk has also adopted this language for `<UserProfile/>` component.

Enough about names, though... How We Roll is for technical details, and naming is the easy part! (Hah.)

Just like [passwords](https://clerk.com/blog/how-we-roll-passwords.md), best practices for multifactor authentication have been learned through a history trial-and-error. Let's see how Clerk handles it all!

## Self-serve, out of the box

Clerk provides multifactor authentication out of the box, which means it requires **zero** additional work. How so? The `<UserProfile/>` component includes a self-serve flow for users to configure multifactor authentication:

[View video](https://clerk.com/_media/blog/how-we-roll-multifactor/a41d5f481d46b077c3a063f89bd027a4c8e74f4a-1624x1080.mp4)

Users can choose between one-time passwords sent by SMS (SMS OTP) or time-based one-time passwords (TOTP). Once configured, they also receive backup codes in the event that access to their other factor is lost.

And `<UserProfile/>` works in tandem with `<SignIn/>`, so the next time a user signs in, they will be prompted to authenticate with their second factor. No custom code required!

If preferred, Clerk also provides `useUser()` and `useSignIn()` hooks, which enable developers to build custom flows for configuring multifactor authentication.

## Something you know, something you have

For multifactor authentication, Clerk mandates that each step satisfies a different _factor_, or type of evidence, for authentication. The two factors we offer are:

1. **Something you know –** also called a knowledge factor, is proof that you know something that only you should know, like passwords, security questions, and pins. By extension, it also includes access to another account which is presumed to require a password (like an email account to receive a one-time password, or a Google account).
2. **Something you have –** also called a possession factor, is proof that you are holding a physical device. SMS and time-based one-time passwords are both examples, as are newer strategies like passkeys.

It is critical for Clerk to use one example from each bucket. A one-time password sent by email (email OTP) can be a replacement for a password, but a SMS OTP cannot.

Similarly, if a user with multifactor authentication forgets their password, the "forgot password" flow cannot be used to bypass the second factor. Instead, after the user verifies their email, they will still be asked to provide a possession factor.

If a user with multifactor authentication completely loses access to either factor, Clerk cannot directly help that user regain access to their account. Instead, an application administrator can help facilitate account recovery through the Clerk dashboard.

## Mitigate SIM swaps at the application level or user level

SMS OTP is a controversial topic among security professions, and rightfully so. SMS is susceptible to a social engineering attack called a "SIM swap," where a telephone company is persuaded to issue a SIM card to an attacker for a victim's phone number.

The general consensus is that SMS OTPs add some degree of security, but a targeted attack has a high chance of success. Jack Dorsey [infamously fell victim](https://www.wired.com/story/jack-dorsey-twitter-hacked) to a SIM swap which helped an attacker gain access to his Twitter account.

Many argue that SMS OTP should be discontinued entirely. The challenge is that SMS is ubiquitous and convenient, so users are more likely to configure multifactor when SMS can be used.

At Clerk, we don't believe the answer is not one-size-fits all, so our solution is two-fold:

1. Developers can choose to disable SMS OTP at the application level.
2. Individual users can choose to disable SMS OTP at the user level. Even if a phone number is added to an account, SMS OTP must be explicitly enabled for it to be used as a possession factor.

![Mitigate SIM swaps at the application level or user level screenshot](https://clerk.com/_media/blog/how-we-roll-multifactor/3fe377763fc8afcbdee8eee118573562d27bd121-2022x954.png "Clerk's dashboard allows developers to choose if SMS OTP is enabled")

## Summary

Multifactor authentication is an essential security feature that every application should offer, but it is essential that best practices are followed for knowledge and possession factors. Clerk's components and hooks provide those best practices for multifactor authentication out of the box.

## How We Roll Series Index

- [How We Roll – Chapter 1: Passwords](https://clerk.com/blog/how-we-roll-passwords.md)
- [How We Roll – Chapter 2: Avatars](https://clerk.com/blog/how-we-roll-avatars.md)
- [How We Roll – Chapter 3: Multifactor](https://clerk.com/blog/how-we-roll-multifactor.md)
- [How We Roll – Chapter 4: Email Verification](https://clerk.com/blog/how-we-roll-email-verification.md)
- [How We Roll – Chapter 5: Customization](https://clerk.com/blog/how-we-roll-customization.md)
- [How We Roll – Chapter 6: User Profile](https://clerk.com/blog/how-we-roll-user-profile.md)
- [How We Roll – Chapter 7: JWT Single Sign-On](https://clerk.com/blog/how-we-roll-jwt-sso.md)
- [How We Roll – Chapter 8: Sessions](https://clerk.com/blog/how-we-roll-sessions.md)
- [How We Roll – Chapter 9: Infrastructure](https://clerk.com/blog/how-we-roll-infrastructure.md)
- [How We Roll – Chapter 10: Roundup](https://clerk.com/blog/how-we-roll-roundup.md)


---

# Announcing A New Password Experience
URL: https://clerk.com/blog/a-new-password-experience.md
Date: 2023-05-19
Category: Company
Description: The team has been focused on making a first in class experience for your end users when it comes to passwords. Let's talk about the new features we introduced. 

It's time for an exciting announcement from our end, one that's been brewing for a while. While it may seem like a small step, we believe it's a giant leap toward an unparalleled user experience, especially when it comes to password security.

Our team has been hard at work, making your end users' experience first-in-class. We're thrilled to introduce a suite of new features that will take password management to the next level. Let's dive into the details!

## Password Reset Flow

Who hasn't forgotten a password at least once? Now, with our traditional password reset flow, users can reset their password with a single click. The best part? It ships with our [sign in component](https://clerk.com/docs/authentication/sign-in.md) and syncs perfectly with our [Multi-Factor Authentication (MFA) products](https://clerk.com/docs/authentication/custom-flows/multifactor.md), ensuring all necessary verification steps are complete before users are automatically signed back into your application.

[View video](https://clerk.com/_media/blog/a-new-password-experience/f0369b61307012009f097b7b81457da1cc88b2ce-1869x1081.mp4)

## **Strong Passwords Verification**

In addition to our [HaveIBeenPwned](https://haveibeenpwned.com) integration, we now enable you to set a minimum strength requirement for all new passwords in your application. This added security layer is powered by the password strength estimator [zxcvbn-ts](https://github.com/zxcvbn-ts/zxcvbn).

With its ability to detect commonly used passwords and patterns such as dates, names, and common phrases, zxcvbn-ts ensures that your end users are protected from using weak passwords in your application. Now, stronger password security is not just an option, but a standard.

[View video](https://clerk.com/_media/blog/a-new-password-experience/370dea8f10c5079e821f71c662b4f2611c98b0f5-1697x1081.mp4)

## **Additional Complexity Requirements**

For our [Business plan](https://clerk.com/pricing) users and beyond, we're introducing the ability to enforce specific password requirements like special characters, numbers, and a mix of uppercase and lowercase letters. This will help your users to not just meet, but exceed your standards.

![Clerk dashboard password complexity policy options](https://clerk.com/_media/blog/a-new-password-experience/b7ea47b66fa674b5ccf0537b86492ccb73b2ca36-1696x1698.png)

## **Password Completion Guidance**

To take password requirements one step further, once you set password policies in your Clerk dashboard, you can even opt for users to be alerted to your length or complexity requirements via guidance cues. When users are setting their password, friendly messaging will appear below the input box that indicates the password policies you selected to help them create passwords that are robust and compliant.

[View video](https://clerk.com/_media/blog/a-new-password-experience/e3a9c2a9054a3e14aafdc18e05a782f7438f6778-2054x1080.mp4)

We're excited about these new additions and can't wait for you to experience them. Here's to a better user experience for all! Want to learn more about "how we roll" passwords? Check out our [post](https://clerk.com/blog/how-we-roll-passwords.md) that goes in depth about passwords at Clerk.

Let us know your thoughts on X [@clerk](https://x.com/clerk) or in the [Clerk Community](https://clerk.com/discord) on Discord.
