使用jose验证JWT失败:Next.js/Clerk中间件报错排查
问题原因及解决方案
核心问题有两个:
jwtVerify是异步函数,你没加await
直接把jwtVerify的返回值赋值给decoded,得到的其实是一个Promise对象,这就是你看到Promise日志的原因。RS256算法需要
CryptoKey类型的公钥,你传的是Uint8Array
Clerk的公钥是PEM格式的字符串,不能直接用TextEncoder.encode转成Uint8Array,必须用jose提供的方法把PEM公钥解析成CryptoKey。
修复后的代码:
import { authMiddleware } from "@clerk/nextjs"; import { jwtVerify, importSPKI } from "jose"; export default authMiddleware({ publicRoutes: ["/", "/contact", "/pricing", "/api/webhooks/user", "/api/reviews/add", "/api/user"], // 给afterAuth添加async关键字,支持await调用 async afterAuth (auth, req, evt) { // 获取环境变量中的PEM格式公钥 const publicKeyPem = process.env.CLERK_PUBLIC_KEY; // 将PEM公钥导入为RS256算法对应的CryptoKey const publicKey = await importSPKI(publicKeyPem, "RS256"); // 用await获取jwtVerify的实际解析结果 const decoded = await jwtVerify( "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXYiOiJkdmJfMlpFZkVyUG91dHBuaFptQXZzdk0zMkVadkVhIiwiaWQiOiJjbGllbnRfMlpFZkpieUFQUXRWbVB4Q3R2SER4SE04a2tCIiwicm90YXRpbmdfdG9rZW4iOiJmaWNid25rZDE0aTVpNm5rZzJicjc1ODl5NWZqeGloemloZDk2dnprIn0.qURs213vHtEe_2DTmOVN8jCPCJhQfIIEjWLMIXgIVYs86U1J3P5BV9EHexjvXda416D4wHAFdxUhUzjKj42CNM4TYTrrsXRT4m_fMNq78NrvwMf7ge2tmcSYNf04c7gqInQzJMNiKILZbQXN0yxExZ1lBbPesg-ZCsx5HZ1544-g0yrcZvxu7HkSwIG56C3ITae51rtMj4lpxyYUxdR9MZ0JZ-HH2XlCT_F3BMDUn_IHNXj2IDF6gI-1kx3UWwYZ5uCyTipbsuOwgFCINFA2m8h3IM0jS9KXGLNrixaej9M0uDEcYkxVRvSwNKJfeHmnhJefYEk82192XpmXJDft8Q", publicKey ); console.log(decoded); } }); export const config = { matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"], };
额外注意:
- 确保
process.env.CLERK_PUBLIC_KEY是完整的PEM格式字符串,包含-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----以及中间的公钥内容。
内容的提问来源于stack exchange,提问作者Ethan
相关产品推荐
相关产品推荐

