Next-Auth遇JWEDecryptionFailed错误,服务端组件获取Token为null
解决NextAuth中JWEDecryptionFailed解密失败及Token为null的问题
问题详情
在服务端组件中获取Token时返回null,排查发现以下错误:
[next-auth][error][JWT_SESSION_ERROR] decryption operation failed { message: 'decryption operation failed', stack: 'JWEDecryptionFailed: decryption operation failed\n' + ' at gcmDecrypt (webpack-internal:///(rsc)/./node_modules/jose/dist/node/cjs/runtime/decrypt.js:68:15)\n' + ' at decrypt (webpack-internal:///(rsc)/./node_modules/jose/dist/node/cjs/runtime/decrypt.js:91:20)\n' + ' at flattenedDecrypt (webpack-internal:///(rsc)/./node_modules/jose/dist/node/cjs/jwe/flattened/decrypt.js:137:52)\n' + ' at async compactDecrypt (webpack-internal:///(rsc)/./node_modules/jose/dist/node/cjs/jwe/compact/decrypt.js:20:23)\n' + ' at async jwtDecrypt (webpack-internal:///(rsc)/./node_modules/jose/dist/node/cjs/jwt/decrypt.js:10:23)\n' + ' at async Object.decode (webpack-internal:///(rsc)/./node_modules/next-auth/jwt/index.js:44:25)\n' + ' at async Object.session (webpack-internal:///(rsc)/./node_modules/next-auth/core/routes/session.js:25:34)\n' + ' at async AuthHandler (webpack-internal:///(rsc)/./node_modules/next-auth/core/index.js:161:37)\n' + ' at async NextAuthRouteHandler (webpack-internal:///(rsc)/./node_modules/next-auth/next/index.js:50:30)\n' + ' at async NextAuth._args$ (webpack-internal:///(rsc)/./node_modules/next-auth/next/index.js:85:24)\n' + ' at async C:\Users\Rax\Desktop\zurii-hr-panel\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:1:66877', name: 'JWEDecryptionFailed' }
对应的NextAuth配置代码(options.ts):
// https://www.youtube.com/watch?v=w2h54xz6Ndw&t=1721s import type { NextAuthOptions } from 'next-auth' import GoogleProvider from "next-auth/providers/google" import AppleProvider from "next-auth/providers/apple" import CredentialsProvider from 'next-auth/providers/credentials' import NextAuth from 'next-auth/next'; import loginService from "@/services/auth"; export const options: NextAuthOptions = { secret: "123", providers: [ CredentialsProvider({ name: "Credentials", credentials: { email: { label: "Email", type: "email", placeholder: "Email" }, password: { label: "Password:", type: "password", placeholder: "Password" } }, async authorize(credentials) { // This is where you need to retrieve user data // to verify with credentials // Docs: https://next-auth.js.org/configuration/providers/credentials const email = credentials?.email || ""; const password = credentials?.password || ""; let user = await loginService.login(email, password); // modify object user = { token: user.access_token } if (user && user.token) { return user; } else { return null; } } }) ], session: { strategy: "jwt", }, callbacks: { async jwt({ token, user }) { return { ...token, ...user }; }, async session({ session, token }) { session.user = token as any; return session; }, }, pages: { signIn: "/login" } };
添加secret后问题仍未解决。
问题原因
- Secret长度不满足加密要求:你使用的
secret: "123"长度过短,NextAuth依赖的jose库要求JWE解密密钥至少为32字节(256位),短密钥会直接导致解密失败。 - 旧Session缓存干扰:浏览器中可能缓存了之前用无效secret生成的Session Cookie,即使更新了secret,旧Cookie无法解密仍会抛出错误。
解决方案
1. 生成符合要求的安全Secret
执行以下Node.js命令生成32字节的十六进制密钥:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
将生成的字符串替换配置中的secret: "123",同时确保该值与环境变量NEXTAUTH_SECRET保持一致(如果项目中使用环境变量管理配置)。
2. 清除浏览器缓存与Cookie
手动清除当前站点的所有Cookie,或使用浏览器隐私模式测试,避免旧的无效Session影响解密流程。
3. 验证用户数据返回逻辑
在authorize方法中添加日志,确认登录接口返回的access_token有效,且传递给NextAuth的user结构正确:
async authorize(credentials) { const email = credentials?.email || ""; const password = credentials?.password || ""; let user = await loginService.login(email, password); console.log('登录接口返回数据:', user); // 确认access_token存在 user = { token: user.access_token } console.log('传递给NextAuth的用户数据:', user); if (user && user.token) { return user; } else { return null; } }
4. 确保服务端组件获取Session的方式正确
在服务端组件中必须使用getServerSession方法获取Session,示例代码:
import { getServerSession } from "next-auth/next" import { options } from "@/app/api/auth/[...nextauth]/options" export default async function YourServerComponent() { const session = await getServerSession(options) if (session) { console.log('获取到的Token:', session.user.token) } // 其他业务逻辑 }
内容的提问来源于stack exchange,提问作者La Bola Al Riel
相关产品推荐
相关产品推荐

