Adding Clerk Authentication to a NextJS App
Tags: nextjs, clerk, security, typescript
Published: 2024-03-19 20:15:43

I’m the type that needs a realistic project to work on if I’m going to understand a platform.

So I decided that to really learn Clerk,  I want to create user profile pages on the website of my Discord server. Since Clerk has a great suite of components for Next.js apps, I figure why not port over the site to Next at the same time to learn both platforms. The first step was to bootstrap a Next site and get authentication set up so I can have users sign into it.

So here’s a quick guide on how to configure Clerk with a Next app.

## Creating the Clerk Application

Starting over in Clerk, I’m going to create a new project here.  I’m going to just configure Google as my SSO provider so I can sign in with my Google account. All other methods are disabled.

![Creating an application in Clerk](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p8cii6wzc6kk15gq30zg.png)

After the application is created, the variables shown on the following page will be used in the Next project, so note these down for the next section.

![The environment variables to be used in the Next app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xte9edzz8fycikwqsr2a.png)

## Setting up Next

I have a basic Next app set up here, and I’m going to start by installing the Clerk components.

![Installing the Clerk libraries](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/px9wea8iekzu65qi4l2u.png)

I’m going to create a new file named .env.local and put the environment variables from the previous section of this article in there. These env vars will be used by the Clerk libraries to connect up to the application that was created earlier in the article.

![Setting up the environment variables](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rcfn8dks2lfdusu1cmue.png)

Next I’m going to set up the middleware by creating middleware.ts and putting the following code in there. By default, this middleware will protect the entire site so I’ll also need to explicitly specify my public routes. In this case, it’s just the root.

![Adding the auth middleware](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kx92rx42nrmkpr0m3oea.png)

Then I’ll update layout.tsx and wrap the entire app in <ClerkProvider> which will enable security on the app.

![Wrapping the layout in the provider](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z9j8g0oirvq6v9q66414.png)

Then I’ll add the <SignUpButton> component to the home page, which will let me sign in with my Google account.

![Adding the SignUpButton](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jq6yk5pewfzt56yw1dp8.png)

Here is what the rendered version of this looks like.

![The Next app with a Sign up button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zb0jldd4v9rx0j5oi2up.png)

Clicking that will bring me to Clerk’s UI which I can use to perform all of the actions needed to either create an account or sign in with an existing account.

![The Clerk login](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9o81cre4yhvp9rkhqis5.png)

After signing in with my Google account, I’m automatically redirected back to the home page but there’s no indication that I’m signed in. This can be fixed using the useUser hook from Clerk. It can be used to check to see if the user is signed in and display the <UserButton> component instead. Note that this needs to be rendered on the client so I added 'use client' to the page.

![Adding the UserButton to the Next app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9n2worw4z7v29fec3781.png)

Now the home page should show my user profile image that has a menu embedded.

![The Next app with the UserButton](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1abfjqrdz7t0y9pluhmt.png)

## Protecting an API route

Once logged in, Clerk will save a cookie in the browser that has tokens it can use for authentication. These cookies are sent with every backend request. The Clerk libraries also have a set of backend functions that can be used in API routes to make sure that the person signed in is authorized to call those routes. Lets explore how to do this.

The following API route will check to see if the user is signed in and simply echo back their ID in a JSON response. Passing the request (which contains the cookie) into authenticateRequest will both determine if the request is authenticated, as well as provide a helper function to get details about the user.

![The API route that parses the user ID](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sbgd000kx802zdssza1i.png)

Now if I update the front end to simply call this route on page load, you can see in the console of the browser that my Clerk user ID is being sent back to me.

![The Next app with the user ID in the console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fheegnqe6l3igqn16fuv.png)

If I log out and refresh the page, it returns a 404 instead now.

![The Next app with a 401 status in the console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jhnkuhgvx2niyml4s1i2.png)

Let me know if this was helpful, or if there are any other topics you’d like to see covered!