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

使用NextAuth(4.24.6)+SIWE(2.0.5)验证签名时出现Cannot read properties of undefined (reading 'verifyMessage')错误求助

NextAuth(4.24.6)+SIWE(2.0.5)验证签名时出现Cannot read properties of undefined (reading 'verifyMessage')错误求助

我来帮你分析和解决这个问题,这个报错本质是SIWE在服务端执行签名验证时,找不到所需的签名校验方法导致的,结合你的代码和环境,我整理了几个关键修复点:

问题根源

SIWE v2版本的verify方法依赖以太坊工具库(比如ethers或viem)提供的verifyMessage函数来完成签名验证,但在Next.js 14的App Router(RSC环境)中,服务端默认不会自动加载这些依赖,而且你当前的代码还有几个小细节没处理到位。

具体解决方案

1. 安装并引入以太坊工具库

首先安装ethers(你也可以用viem,用法类似):

npm install ethers
# 或者 yarn add ethers

2. 修正NextAuth授权逻辑里的验证代码

修改你的[...nextauth]/route.js,重点解决三个问题:显式传入验证函数、正确获取signature、修正CSRF Token的获取方式,完整代码如下:

import NextAuth from 'next-auth'
import CredentialsProvider from 'next-auth/providers/credentials'
import { getCsrfToken } from 'next-auth/react'
import { SiweMessage } from 'siwe'
import { ethers } from "ethers"; // 新增引入ethers

const handler = NextAuth({
  secret: process.env.NEXTAUTH_SECRET,
  session: {
    strategy:'jwt'
  },
  providers: [
    CredentialsProvider({
      name: 'Credentials',
      id: 'credentials',
      credentials: {
        message: {
          label: "Message",
          type: "text",
          placeholder: "0x0",
        },
        signature: {
          label: "Signature",
          type: "text",
          placeholder: "0x0",
        },
      },
      async authorize(credentials, req) {
        try {
          if (!process.env.NEXTAUTH_URL) {
            throw 'NEXTAUTH_URL is not set'
          }
          
          // 先校验传入的参数是否存在
          const rawMessage = credentials?.message;
          const signature = credentials?.signature;
          if (!rawMessage || !signature) return null;
          
          const siwe = new SiweMessage(JSON.parse(rawMessage));
          const nextAuthUrl = new URL(process.env.NEXTAUTH_URL);
          
          // 校验domain是否匹配
          if (siwe.domain !== nextAuthUrl.host) {
            return null;
          }
          
          // 修正CSRF Token的获取方式
          const nonce = await getCsrfToken({ req });
          if (siwe.nonce !== nonce) {
            return null;
          }
          
          console.log('reached here');
          
          // 显式传入ethers的verifyMessage方法,解决找不到函数的问题
          const result = await siwe.verify({
            signature,
            verifyMessage: ethers.verifyMessage
          });
          
          console.log('result: ', result);
          
          if (result.success) {
            return {
              id: siwe.address,
            };
          }
          return null;
        } catch (e) {
          // 新增错误日志,方便调试
          console.error('授权过程出错:', e);
          return null;
        }
      },
    }),
  ],
  callbacks: {
    async session({ session, token }) {
      session.address = token.sub;
      session.user.name = token.sub;
      return session;
    },
  },
})

export { handler as GET, handler as POST }

3. 额外调试建议

  • 确认NEXTAUTH_URL环境变量和前端的window.location.host完全一致(比如本地开发是http://localhost:3000)
  • 在前端的Authenticate函数里,打印message.prepareMessage()和signature,确保内容格式正确
  • 保留后端的错误日志,方便后续排查其他潜在问题

备注:内容来源于stack exchange,提问作者Saju Sajadh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 08:18:15