You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Next-Auth、Next.js和Vercel时遇JsonWebTokenError: invalid signature错误

JWT令牌验证失败(仅Vercel生产环境异常,开发环境正常)

我在API请求中遇到JWT令牌无法验证的问题,具体情况如下:

  • 已从next-auth的session.user.accessToken获取令牌,并在请求头中携带authorization字段
  • 其他采用相同JWT验证逻辑的项目运行正常
  • 仅在Vercel部署的生产环境出现错误,开发环境完全正常
  • 已尝试重新登录,问题依旧
  • Next-Auth使用的NEXTAUTH_SECRET与JWT工具函数使用的SECRET_KEY为不同密钥,且生产/开发环境的密钥保持一致

相关代码

Next-Auth配置

export const options: NextAuthOptions = {
  adapter: PrismaAdapter(prisma),
  providers: [
    CredentialsProvider({
      id: "credentials",
      name: "Credentials",
      type: "credentials",
      credentials: {
        email: {label: "email", type:"email", placeholder: "name@example.com"},
        password: {label: "password", type: "password", placeholder:"password"}
      },
      async authorize(credentials) {
        const res = await fetch(envCheck()+"/api/login", {
          method:"POST",
          headers: {
            "Content-Type": "application/json",
          },
          body:JSON.stringify({
            email: credentials?.email,
            password: credentials?.password,
          })
        });
        console.log("response from authorize",res); // Will show you the status
        if(res.status === 200) {
          const user = res.json();
          return user;
        } else {
          throw new Error(""+res.status);
        }
      },
    })
  ],
  secret: process.env.NEXTAUTH_SECRET,
  session: {
    strategy: "jwt",
    maxAge: 30 * 24 * 60 * 60,
  },
  pages: {
    signIn: '/auth',
    signOut: '/'
  },
  callbacks: {
    async jwt({token, user, trigger, session}) {
      if(trigger === "update") {
        return {...token, ...session.user}
      }
      return({...token, ...user})
    },
    async session({session, token}) {
      session.user = token as any;
      return session;
    }
  }
}

JWT工具函数

interface SignOption {
  expiresIn?: string | number;

}

const DEFAULT_SIGN_OPTION: SignOption = {
  expiresIn: "1h"
}

export function signJwtAccessToken(payload: JwtPayload, options?:SignOption) {
  const secret_key = process.env.SECRET_KEY;
  const token = jwt.sign(payload, secret_key!, options);

  return token;
}

export function verifyJwt(token:string) {
  try {
    const secret_key = process.env.SECRET_KEY;
    const decoded = jwt.verify(token, secret_key!);
    
    return decoded as JwtPayload;
  } catch (error) {
    console.error(error);
    return null;
  }
}

API请求示例

const response = await fetch(envCheck()+`/api/user/${session?.user.id}/gym`, {
  headers:{
    "authorization": session.user.accessToken,
  },
});

令牌验证逻辑

const accessToken = request.headers.get("authorization")
if(!accessToken || !verifyJwt(accessToken)) {
  return NextResponse.json("401");
};

内容的提问来源于stack exchange,提问作者marcellobonini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:22:31