Next.js Authentication

Easily add secure, beautiful, and fast authentication to Next.js with Clerk.

Overview

Clerk is the easiest way to add secure, beautiful, and fast authentication to your Next.js application. Clerk provides an NPM library tailored specifically to Next.js authentication, with helpers for React pages, API routes, server-side rendering, and edge middleware.This guide shows how to install and use Clerk to solve the most common Next.js authentication challenges.

πŸ‘‰Β Live demo

πŸ‘©β€πŸ’» Looking for a quickstart? Check out the Clerk + Nextjs starter repo

Installation

Before you start

You need to create a Clerk Application in your Clerk Dashboard. For more information, check out our Set up your application guide.

Create a Next.js application

Start by creating a new Next.js application with the npx CLI:

npx create-next-app@latest

If you wish to use TypeScript, just add --typescript to the command above. Clerk is written in TypeScript, so it works out of the box without any extra configuration.

Need more help? The Next.js documentation goes into more detail about creating applications.

Install Clerk's SDK

Once you have a Next.js application ready, you need to install Clerk's Next.js SDK. This gives you access to our prebuilt components and hooks for React, as well as our helpers for Next.js API routes, server-side rendering, and edge middleware.

1
# Navigate to your application's root directory
2
cd yourapp
3
4
# Install the clerk/nextjs package
5
npm install @clerk/nextjs

Now, we need to set three environment variables for Clerk's SDK. Go to the API Keys page and start by copying the Frontend API key. Then, add it a .env.local file in your application root, with the name NEXT_PUBLIC_CLERK_FRONTEND_API:

1
# Replace [frontend-api-key] with your actual Frontend API key
2
echo "NEXT_PUBLIC_CLERK_FRONTEND_API=[frontend-api-key]" >> .env.local

Next, go back to the API Keys page and copy the Backend API key. Then, add it in the same .env.local file, with the name CLERK_API_KEY:

1
# Replace [backend-api-key] with your actual Backend API key
2
echo "CLERK_API_KEY=[backend-api-key]" >> .env.local

Finally, go back to the API Keys page and copy the JWT verification key. Again, add it in the sameΒ .env.local file, with the name CLERK_JWT_KEY:

1
# Replace [jwt-verification-key] with your actual JWT Verification key
2
echo "CLERK_JWT_KEY=[jwt-verification-key]" >> .env.local

Install <ClerkProvider />

Clerk requires your React application to be wrapped in the <ClerkProvider/> component. In Next.js, this is done in pages/_app.js.

1
import { ClerkProvider } from '@clerk/nextjs';
2
3
function MyApp({ Component, pageProps }) {
4
return (
5
<ClerkProvider {...pageProps} >
6
<Component {...pageProps} />
7
</ClerkProvider>
8
);
9
}
10
11
export default MyApp;

Notice the {...pageProps} part - that's what makes all the SSR magic possible.

That's all! πŸŽ‰

To run your app, start the development server and navigate to https://localhost:3000

npm run dev

Clerk is installed, but you still have configure your application to use authentication. Read on to learn how to protect pages, API routes, and more.

Protecting pages

Using Control Components

After installing Clerk, the most common next step is to restrict page access to signed in users.The easiest way to accomplish this is to leverage our flexible Control Components:

  • ​<SignedIn/>: Renders its children only when a user is signed in.
  • ​<SignedOut/>: Renders its children only when there's no active user.
  • ​<RedirectToSignIn/>: Triggers a redirect to the sign in page.

The following example shows you how to compose our flexible Control Components to build authentication flows that match your needs. Please note that you don't need to use any additional APIs, everything shown below is just Javascript.

1
import { ClerkProvider, SignedIn, SignedOut, RedirectToSignIn } from '@clerk/nextjs';
2
import { useRouter } from 'next/router';
3
4
// List pages you want to be publicly accessible, or leave empty if
5
// every page requires authentication. Use this naming strategy:
6
// "/" for pages/index.js
7
// "/foo" for pages/foo/index.js
8
// "/foo/bar" for pages/foo/bar.js
9
// "/foo/[...bar]" for pages/foo/[...bar].js
10
const publicPages = [];
11
12
function MyApp({ Component, pageProps }) {
13
// Get the pathname
14
const { pathname } = useRouter();
15
16
// Check if the current route matches a public page
17
const isPublicPage = publicPages.includes(pathname);
18
19
// If the current route is listed as public, render it directly
20
// Otherwise, use Clerk to require authentication
21
return (
22
<ClerkProvider>
23
{isPublicPage ? (
24
<Component {...pageProps} />
25
) : (
26
<>
27
<SignedIn>
28
<Component {...pageProps} />
29
</SignedIn>
30
<SignedOut>
31
<RedirectToSignIn />
32
</SignedOut>
33
</>
34
)}
35
</ClerkProvider>
36
);
37
}
38
39
export default MyApp;

Visit http://localhost:3000 to see your page. The home "/" page is not listed in the publicPages array, so you'll immediately get redirected to the Clerk Hosted Sign In page.

Using getServerSideProps (SSR)

You can also leverage the SSR capabilities of Clerk and NextJS to redirect unauthenticated users to a sign in page during SSR - even before the components render on the client side.

Next.js uses special export named getServerSideProps to enable server-side rendering. The withServerSideAuth Clerk helper provides access to the auth state.

1
import { withServerSideAuth } from "@clerk/nextjs/ssr";
2
3
export const getServerSideProps = withServerSideAuth(({ req, resolvedUrl }) => {
4
const { sessionId } = req.auth;
5
6
if (!sessionId) {
7
return { redirect: { destination: "/sign-in?redirect_url=" + resolvedUrl } };
8
}
9
10
return { props: {} };
11
});

This snippets redirects unauthenticated visitors to the sign in page. Notice that we also added a redirect_url query param - Clerk will redirect the user back to the original destination after a successful sign in flow.

Using a _middleware function (Edge)

Alternatively, if you're using Edge Functions you can restrict access to a page using the Clerk edge middleware auth helper as shown below:

1
import { withEdgeMiddlewareAuth } from "@clerk/nextjs/edge-middleware";
2
import { NextResponse } from "next/server";
3
4
export default withEdgeMiddlewareAuth((request) => {
5
const { sessionId } = request.auth;
6
7
if (!sessionId) {
8
const destination = request.nextUrl.href;
9
const url = request.nextUrl.clone();
10
url.pathname = "/sign-in";
11
url.searchParams.set("redirect_url", destination);
12
return NextResponse.redirect(url);
13
}
14
15
return NextResponse.next();
16
});
17

This snippets redirects unauthenticated visitors to the sign in page. Notice that we also added a redirect_url query param - Clerk will redirect the user back to the original destination after a successful sign in flow.

A great use case for the above middleware is restricting access to entire paths, eg: /protected-pages/* . Let's say you have the following file structure, and you want to restrict access to the whole /protected-page directory:

pages/
β”œβ”€ protected-pages/
β”‚ β”œβ”€ _middleware.tsx
β”‚ β”œβ”€ user/
β”‚ β”‚ β”œβ”€ profile/
β”‚ β”‚ β”‚ β”œβ”€ password.tsx
β”‚ β”‚ β”œβ”€ index.tsx
index.tsx
_app.tsx

Simply create a _middleware.tsx file under protected-pages/ and paste the middleware from the snippet.

Accessing authentication data

Clerk is the only provider that seamlessly authenticates users across all four Next.js contexts:

  1. Pages
  2. getServerProps
  3. API routes
  4. Edge middleware

Each context has access to Clerk's auth singleton, which contains the data necessary for authentication and data loading:

  • userId: The ID of the active user, or null when signed out. In data-loaders, this is often the only piece of information needed to securely retrieve the data associated with a request.
  • sessionId: The ID of the active session, or null when signed out. This is primarily used in audit logs to enable device-level granularity instead of user-level.
  • getToken({ template?: string; }): Retrieves a signed JWT that is structured according to the corresponding JWT template in your dashboard. If no template parameter is provided, a default Clerk session JWT is returned.

Page authentication

In Next.js pages, the useAuth hook retrieves the auth singleton from within your React components.

1
import { useAuth } from '@clerk/nextjs';
2
3
const Page = () => {
4
const { isLoaded, userId, sessionId, getToken } = useAuth();
5
6
// Handle these cases in case the user signs out while on the page.
7
if (!isLoaded || !userId) {
8
return null;
9
}
10
11
return <div>Hello, {userId}</div>;
12
};

API routes authentication

In API routes, the withAuth helper adds the auth singleton to the request object.

1
import { withAuth } from "@clerk/nextjs/api";
2
3
export default withAuth(async (req, res) => {
4
const { userId, sessionId, getToken } = req.auth;
5
const supabaseToken = await getToken({ template: 'supabase' });
6
// Load any data your application needs for the API route
7
return { data: {} };
8
});
9

Server-side rendering (SSR) authentication

Next.js uses special export named getServerSideProps to enable server-side rendering. The withServerSideAuthhelper adds the auth singleton to the request object.

1
import { withServerSideAuth } from "@clerk/nextjs/ssr";
2
3
export const getServerSideProps = withServerSideAuth(async ({ req }) => {
4
const { userId, sessionId, getToken } = req.auth;
5
const hasuraToken = await getToken({ template: 'hasura' });
6
// Load any data your application needs and pass to props
7
return { props: {} };
8
});
9
10
export default MyPage(){
11
return ...;
12
}

Edge middleware authentication

In edge middleware, the withEdgeMiddlewareAuth helper injects the auth property to the request object.

1
import { withEdgeMiddlewareAuth } from "@clerk/nextjs/edge-middleware";
2
3
export default withEdgeMiddlewareAuth(async req => {
4
const { userId, sessionId, getToken } = req.auth;
5
const supabaseToken = await getToken({ template: 'supabase' });
6
7
// Run your middleware
8
9
// Complete response
10
return NextResponse.next();
11
});

Enabling full server side rendering

To make auth as fast as possible, Clerk uses short-lived stateless JWT tokens by default, requiring no network requests.

If desired, Clerk’s complete User objects can also be retrieved during SSR. Since these objects require network requests to retrieve, so you need to explicitly enable server-side user fetching by passing a flag to the data-loader:

1
import { withServerSideAuth } from "@clerk/nextjs/ssr";
2
3
export const getServerSideProps = withServerSideAuth({ loadUser: true });
4
5
// or, if you also need a custom getServerSideProps handler:
6
export const getServerSideProps = withServerSideAuth(
7
({ req }) => {
8
const { userId } = req.auth;
9
// fetch data
10
return { props: { yourData: "here" } };
11
},
12
{ loadUser: true }
13
);

Next steps

You now have a working Next.js + Clerk app. Going forward, you can:

Β© 2022 Clerk. All rights reserved.