Why jwt.verify Doesn’t Work with NextAuth.js Session Tokens
See how NextAuth.js encrypts session tokens, why a signed-token verifier cannot decode them, and how to read them with the library’s helpers.
Updated:
In the modern web development landscape, securing user authentication is paramount. Many developers turn to JSON Web Tokens (JWT) for their stateless, compact, and secure nature. When integrating authentication in a Next.js application, next-auth is a popular choice due to its simplicity and rich feature set.
However, a common stumbling block arises when developers try to use jwt.verify directly with tokens issued by next-auth. This article explores why this approach doesn’t work and how to handle JWTs correctly within a next-auth setup.
How NextAuth.js v4 Handles Session Tokens
With the JWT session strategy, NextAuth.js v4 encrypts session tokens by default. The token is a JWE, and v4 derives its encryption key from the configured secret using HKDF. A signed JWT is usually a JWS. jsonwebtoken.verify() verifies a JWS signature, so it cannot decrypt this session token.
Read the Token with the NextAuth.js Helper
For a Next.js Pages Router API route, use the helper from the same NextAuth.js version that issued the token. Set NEXTAUTH_SECRET in the server environment.
import { getToken } from "next-auth/jwt";
export default async function handler(req, res) {
const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });
if (!token) {
return res.status(401).json({ error: "Unauthorized" });
}
return res.status(200).json({ authenticated: true });
}
When you already have the raw token in a server-side script, use the library’s decoder:
import { decode } from "next-auth/jwt";
const token = process.env.NEXTAUTH_JWT;
const secret = process.env.NEXTAUTH_SECRET;
if (!token || !secret) throw new Error("Missing token or secret");
const payload = await decode({ token, secret });
These examples apply to the default JWT session strategy in v4. Match any custom decoder configured by the app. An OAuth provider’s access token is a separate credential and follows the provider’s validation rules.
Conclusion
Choose the decoder that matches the token’s issuer and format. For a NextAuth.js session token, use the library’s server-side helper so the application handles the token the same way it did when it issued it.