惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
爱范儿
爱范儿
宝玉的分享
宝玉的分享
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - Franky
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 三生石上(FineUI控件)
人人都是产品经理
人人都是产品经理
阮一峰的网络日志
阮一峰的网络日志
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
博客园 - 聂微东
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
博客园 - 叶小钗
WordPress大学
WordPress大学
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
小众软件
小众软件
博客园 - 司徒正美
博客园 - 【当耐特】
IT之家
IT之家

Clerk Blog

Going to production with Clerk Deploy Clerk Init: The fastest way to start a new project Introducing Clerk CLI Middleware-based route protection bypass Postmortem: Clerk System Outage (March 10, 2026) Clerk for the AI era Add API Key support to your SaaS in minutes Postmortem: Clerk System Outage (February 19, 2026) Using Clerk in a React Native app Postmortem: DNS Provider Outage (February 10, 2026) How do I implement passkeys in Next.js? Clerk ranked #4 fastest-growing software vendor on Ramp’s December 2025 list How do I handle JWT verification in Next.js? Committing to Agent Identity: Clerk raises $50m Series C from Menlo and Anthropic’s Anthology Fund What is the best way to handle authentication in Next.js App Router? Postmortem: Database Incident (September 14–18, 2025) Introducing Free Trials in Clerk Billing Postmortem: August 28, 2025 - elevated API latency and errors Introducing Mosaic: Bring Your Brand to Every Authentication Flow Multi-tenant authentication: What you need to know (and how Clerk helps) What are the risks and challenges of multi-tenancy? Resilience in Practice: Regional Failover at Clerk Build a Cross-Platform B2B App with Clerk, Expo, and Supabase Highlights from the MiduDev/Clerk Hackathon Add multi-tenancy to an app built with Clerk, Lovable, and Supabase How to build an AI coding rules app with Clerk, Lovable, and Supabase How to Build Multi-Tenant Authentication with Clerk Choosing the right SaaS architecture: Multi-Tenant vs. Single-Tenant Postmortem: June 26, 2025 service outage How to Design a Multi-Tenant SaaS Architecture
How do I add authentication to a Next.js app?
Brian Morrison II · 2025-09-15 · via Clerk Blog

Authentication is core to building any multi-user product, and it's important to get it right from the start.

There are a number of methods you can use when adding authentication into a product, and Next.js has its own paradigms to consider. Understanding the Next.js authentication strategies available is key to knowing which is best for your application, and properly implementing it is the next challenge.

In this article you'll learn about the most common authentication strategies, as well as how to add JWT authentication to a Next.js application.

Next.js authentication strategies: Choosing the right approach

There are many strategies to select from when planning your approach to authentication. The most common approaches are session token authentication, JWT-based authentication, and OAuth. Let's touch on how each of these compare.

Session tokens

Session token authentication is the oldest on this list but is still widely used today. When a user signs into an application using session token authentication, the backend service will verify the user's credentials against the database and, assuming they are valid, create an entity called a "session". Each session has some commonly tracked attributes stored such as the user it's associated with, when it was created, when it expires, and its status (valid, expired, etc). The session identifier is sent back to the user's device to be used with subsequent network requests.

The most common method of storing the session ID client-side is in a browser cookie so the ID is sent with future network requests automatically. When received by the server, the session is cross-referenced with the user for which it was created so that the server knows who is making the request and can apply security appropriately.

JWT

JSON Web Tokens (JWTs) are specially formatted strings that contain embedded information about a particular user or session and are cryptographically signed by the server. When a user signs in, the server will validate the user's credentials just like with session token authentication but instead of creating a session record (commonly in a database table), the details are encoded into a JWT and signed before being sent back to the client. The JWT is also sent with each request but since it contains the user and/or session details, the server does not have to look up those in the database. The server can simply verify the JWT signature is valid and can trust the encoded details if it is.

This has some benefits and drawbacks. One of the primary benefits is the speed by which requests are validated as no datastore lookups are required. Since verification is mostly performed on the receiving server, this also makes JWT authentication more scalable than session token authentication. As long as a server has a cached version of the signing secret (or public key in asymmetric signing configurations), that server can verify the JWTs authenticity.

The primary drawback is the lack of control if a JWT is leaked to an unauthorized party. Since all of the session information is embedded with the token and the verification process does not require any additional checks with a central datastore, there is no standard way to invalidate tokens once they've been signed and sent out.

OAuth

OAuth is a standard that allows a user to authenticate with one system and access multiple services using a single account. If you've ever signed into a web application with a Google or Apple account, you've used OAuth. In a typical configuration, the service provider (SP) will redirect users attempting to sign in to an identity provider (IdP) to supply their credentials and create a session. Once authenticated, the user's device will receive a code that can be provided to the SP, which will communicate with the IdP to verify the code, create the JWT, and send it back to the user.

This flow (known as the "Authorization Code Grant") describes how the SP and IdP work together to create the session and is only one of many flows that are part of the OAuth spec.

How to implement Next.js authentication with JWT tokens

Now that you have a solid understanding of some common authentication strategies, let's learn how to manually implement Next.js authentication using JWT tokens. To do this, you'll step through the following:

  • Configure a SQLite database to store user records
  • Set up public/private keys to sign and validate JWTs in a helper
  • Create sign-up and sign-in pages
  • Configure a Sign out button
  • Show claims from the JWT within a server-rendered page

To follow along, you'll need the following:

  • A general understanding of React, and ideally experience with Next.js
  • Node.js installed on your workstation

You'll use the supplied starter repository that is a Next.js application preconfigured with SQLite, a few shadcn/ui components, and a dashboard page with some dummy data. Through this guide, you'll create the sign-up page, sign-in page, sign-out button, and you'll configure the middleware to enforce authentication on the /dashboard route.

Upon signing in, the middleware will parse the JWT (stored as a cookie) to determine the user's authentication status. Server actions will be used throughout the various authentication functions.

The following dependencies are also pre-installed:

  • bcrypt to salt and hash user passwords before storing them in the database.
  • jose to create and validate JWTs

Before moving on, clone the start branch of this repository: clerk/nextjs-jwt-auth-demo. Once cloned, open the project in your code editor of choice and run pnpm install to install the dependencies.

Creating the SQLite and JWT helpers

You'll start by creating a helper file that lets the application interact with the SQLite database. The helper will create the connection, create the users table if it does not yet exist, and return a connection object to the caller. The table needed to support user authentication contains only three columns:

  • id is the unique identifier for the user
  • username is their username
  • password_hash is the salted and hashed representation of their password

Create the src/lib/db.ts and populate it with the following:

src/lib/db.ts

Next, you'll create the JWT helper file that contains the configuration for jose as well as the createToken function to generate a new JWT for the user and parseToken which verifies the token's validity and returns the claims (the data encoded within JWTs) to the caller if it is.

Create the src/lib/jwt.ts file and add the following:

src/lib/jwt.ts

Notice in the above code that the JWT_PRIVATE_KEY and JWT_PUBLIC_KEY are being referenced from the environment variables. To set this up, run the following command in your terminal to generate a key pair and set them in the .env.local file:

Inspecting the .env.local file will look similar to the following (albeit with a larger value for each variable):

.env.local

Building the sign-up flow

Before users can sign-in and use the application, they'll need a way to sign-up first. Create the src/app/actions.ts file to store the server actions required to sign-up. This configuration will check if a record with that username exists (responding with an error if found), creates the JWT and stores it as a cookie, and redirects the user to the /dashboard route.

src/app/actions.ts

Now create the src/app/sign-up/page.tsx file to store the sign-up form used to create an account:

src/app/sign-up/page.tsx

You can now start the application with npm run dev, access it using the provided URL, and navigate to the /sign-up route to create a user. After creating a user, you'll be redirected to the /dashboard route.

Configure sign-out

Since the JWT is stored in a cookie with the httpOnly flag, client-side JavaScript will not be able to access it, so you'll need to configure a server action to clear the cookie. Update the actions.ts file and append the signOut function as shown below:

src/app/actions.ts

Next, create a Sign Out button component at src/components/SignOutButton.tsx and paste in the following:

src/components/SignOutButton.tsx

Then you'll need to update the Navigation component to check if the user is logged in and render the button if they are. Since it is a server-rendered component, you can use the next/headers package to access the request cookies and the parseToken function to verify the user is signed in.

Update the src/components/Navigation.tsx file as follows:

src/components/Navigation.tsx

Now access the application in your browser once again and click the Sign out button in the navigation. You'll be redirected if you are on the /dashboard page and the navigation bar will update to show the Sign in and Sign up links.

Configure the sign-in page and actions

Now that sign-up and sign-out are working, you'll need a way for existing users to sign-in. Update the actions.ts file once again and append the following actions:

src/app/actions.ts

Then create the src/app/sign-in/page.tsx file to display the sign-in form:

src/app/sign-in/page.tsx

In the application, navigate to the /sign-in route and use the credentials you created earlier to sign-in and access the /dashboard route once again.

Protecting routes with Next.js authentication middleware

As of now, even unauthenticated users can access /dashboard if they enter the path in their browser. Next.js authentication middleware can be configured to intercept inbound requests and check the cookies to ensure a user is signed-in before allowing them to access protected routes. Furthermore, the middleware can also be configured to redirect unauthenticated users to /sign-in if they attempt to access /dashboard.

Create the src/middleware.ts file and populate it like so to achieve this protection:

src/middleware.ts

Display user information on the Dashboard page (optional)

Since the /dashboard route is protected by our Next.js authentication system, any users that can access it will have already signed in, meaning the information in the JWT can be trusted. The next/headers package can be used in page content just like in the Navigation.tsx component to parse details about the authenticated user and render the details on the page.

To do this, update src/app/dashboard/page.tsx as follows to display the user's username in the page header:

src/app/dashboard/page.tsx

Accessing the /dashboard page will now show the username in the welcome message!

Now what?

You now have a functional system that allows users to sign up and sign in to this demo app, however there are a number of missing, critical user management features:

  • Email address verification
  • Password reset functionality
  • Advanced attack protection and rate limiting
  • Session management and refresh tokens
  • Multi-factor authentication
  • Social login providers

These are just to name a few of the gaps. Production-ready authentication in Next.js goes well beyond basic JWT implementation, and this is where Clerk's Next.js authentication solution comes in.

Why choose Clerk for Next.js authentication?

Clerk is a complete user management platform that allows developers to add enterprise-grade Next.js authentication into their applications as quickly as possible. With Next.js applications, this can be done in just a few lines of code.

Once implemented, you'll automatically gain all of the features listed above along with many more such as:

  • One-click social authentication (Google, GitHub, Apple, etc.)
  • Simple multi-tenancy for B2B applications (including custom RBAC)
  • Subscription management with Clerk Billing
  • Advanced security features that protect against bots, brute force attacks, and abuse
  • Pre-built UI components that can be configured to match your application's design

Get started with production-ready Next.js authentication

If you're ready to implement a robust Next.js authentication solution for your Next.js application, check out our Next.js quickstart guide to learn how to get authentication added to your application in as little as 2 minutes. You'll have a complete, secure, and scalable authentication system without the complexity of building and maintaining it yourself.