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

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
P
Proofpoint News Feed
宝玉的分享
宝玉的分享
人人都是产品经理
人人都是产品经理
博客园_首页
爱范儿
爱范儿
博客园 - 叶小钗
aimingoo的专栏
aimingoo的专栏
S
SegmentFault 最新的问题
MyScale Blog
MyScale Blog
阮一峰的网络日志
阮一峰的网络日志
IT之家
IT之家
Microsoft Security Blog
Microsoft Security Blog
Blog — PlanetScale
Blog — PlanetScale
博客园 - 【当耐特】
Y
Y Combinator Blog
量子位
博客园 - 三生石上(FineUI控件)
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
The Blog of Author Tim Ferriss
月光博客
月光博客
有赞技术团队
有赞技术团队
Apple Machine Learning Research
Apple Machine Learning Research
A
About on SuperTechFans

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 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) How do I add authentication to a Next.js app? 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 handle JWT verification in Next.js?
Brian Morrison II · 2025-10-16 · via Clerk Blog

In this article, you’ll learn what JWTs are and how to verify them in a Next.js application. Code samples are also provided to demonstrate how to access the JWTs transmitted through a cookie or a request header.

Summary:

  • JWTs are specially crafted, cryptographically signed tokens that are used to identify users or systems making requests.
  • JWTs can be signed using symmetric or asymmetric cryptography, with the latter being more secure while supporting distributed systems.
  • They are verified by extracting the value from the request and checking the signature using a shared secret or public key, which allows the receiving server to trust the encoded claims.

What Is a JWT?

A JSON Web Token (JWT) is a compact, specially crafted string used to represent a user, session, or other principal. JWTs are cryptographically signed, and that signature is used to confidently identify the party making a request.

A JWT is structured into three distinct segments, each separated by a period to indicate where one part ends and another begins. Each segment is base64 encoded before being joined to create the final token. The following diagram shows what a JWT looks like, along with each segment being color-coded:

Color-coded diagram showing the different segments of a JWT.

The header contains information to help the receiving system understand the token's purpose. This includes the type (typically set to jwt) and the algorithm used to generate the signature.

Claims

The claims are the primary payload of the JWT and contain information about the party for which the JWT was created. The following list outlines claims that are standard across most JWTs:

  • Subject (sub) - Identifies who the JWT was created for. Often this is the username or user ID.
  • Issuer (iss) - Who created the JWT
  • Expiration (exp) - The epoch timestamp for when the JWT expires
  • Issued at (iat) - The timestamp for when the JWT was created
  • Not before (nbf) - A timestamp to restrict use of the JWT before a specific moment
  • Audience (aud) - The designated audience for the JWT

Not all of these claims are required. The following snippet shows the claims from the Clerk token shown in the image above:

You can also add any arbitrary JSON-compliant data to a JWT. Say, for example, you are using sub as the user ID but also want to encode the username, you can create a username claim and simply store it the JWT claims before signing.

Signature

The signature is the result of combining the base64 encoded versions of the header and claims, and using the specified algorithm to generate a cryptographic signature. This signature is used to ensure that the JWT has not been tampered with, which is how the receiving system can be confident in the JWT's authenticity.

How JWT verification uses cryptography

There are two cryptographic methods by which JWTs are created: symmetric and asymmetric.

When symmetric encryption is used, the server uses a shared secret for encrypting and decrypting the token. When a JWT is received by the server, it uses that secret to verify that the signature of the JWT is valid. If either the header or claims have been tampered with, then the signature verification will fail. When using symmetric encryption, any server that needs to verify JWTs would need a copy of the secret.

Asymmetric encryption uses public key cryptography which involves two keys: a public key that can be shared with anyone and a private key that should be secured as you would secure a password. The private key is capable of creating and verifying signatures, whereas the public key is only capable of verifying signatures against a pre-existing payload. With both keys, the signature is verified with the same logic as described in the previous section.

With asymmetric encryption, only the public key is used to verify the signature. All servers would need a copy of this key, but since the public key can only verify signatures and not create signatures, it is a much more secure method of verifying signatures.

How are JWTs created?

In a typical web application, users will start by submitting their credentials (e.g., username and password). When the server receives these credentials, it will verify them with the database to ensure the user record is found and the provided information matches what's stored. The server will then create a JWT and send it back to the client, often by setting it in a cookie but the server can also provide it in a response body and leave it up to the client to store for later use.

The following sequence diagram demonstrates this flow visually:

  1. The client sends the user's credentials to the server
  2. The server checks the credentials with the database
  3. The database responds to the server to confirm the user record exists and credentials match
  4. The server uses the private key to create a JWT and sends it back to the client

JWT authorization sequence diagram.

Verifying JWTs in a Next.js app

JWTs are verified on each request to a server. When the server receives a request and the accompanying JWT, it will use the public key to verify the signature of the JWT. The verification also checks various claims encoded within the JWT such as the iat, nbf, and exp values to ensure the token is not being used outside of its designated window. If the server is able to verify the signature, it can trust the data encoded within the JWT.

Since the public key can be cached on the receiving server, communicating with additional auth servers or databases is not required.

The following snippets demonstrate how to verify a JWT using the jose library in a Next.js application. In these scenarios, the public key is stored in the JWT_PUBLIC_KEY environment variable. Here is an example of that key:

Cookies

Cookies are small bits of data stored in a web browser that are automatically transmitted to servers that match the domain for which they were created when a request is sent. This snippet shows how to parse and verify the JWT from the token cookie:

Cookies are often considered the most secure method since you can restrict JavaScript from accessing the value of cookies, limiting what can potentially exfiltrate a user's token for impersonation.

Request headers are a popular way to transmit JWTs and can be used across domains; however, since the client needs to manually add the header to each request, JavaScript needs to be able to access the value of the JWT. The most common header to transmit a JWT with is the Authorization header with a value formatted as Bearer {TOKEN}.

Using fetch to make a request to an API route would be similar to the following:

The JWT in the header would be verified in the route handler like so:

Using the Authorization header is common practice but you can transmit a JWT in any header that makes sense for your application.

Other methods

The methods above are the most common and secure methods of transmitting a JWT, but ultimately, any way that the token can be transmitted from a client to the server will work, provided the server expects it. Alternate methods you may encounter are as a path or query parameter in a URL, however, these approaches are typically not recommended as they pose potential security risks by exposing tokens via logging platforms or in the browser history.

Conclusion

This article covered what JWTs are, how they are created, and how to verify them in a Next.js application. Clerk handles this entire process for you in only a few lines of code, while going beyond simple JWT verification by providing a full user management suite. This includes social sign-in with popular providers, multi-tenancy with RBAC, and even a billing solution for SaaS platforms that need to provide subscriptions.