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

FastifyJWT验证URL参数Token报错:request.jwtVerify不是函数

问题:Fastify中使用request.jwtVerify()报错TypeError: request.jwtVerify is not a function

场景背景

通过邮件发送带JWT Token的验证链接,用户点击链接后后端接收GET请求,从URL查询参数中提取Token并验证,完成邮箱确认。但验证时触发错误:TypeError: request.jwtVerify is not a function。

相关代码

1. 生成邮箱验证Token并发送邮件

const emailToken = await reply.jwtSign({}, {
  sub: email,
  expiresIn: '7d'
});

const messageData = {
  from: 'test@mail.com',
  to: 'test@mail.com',
  subject: 'Verificação de E-mail',
  text: `Clique neste link para verificar seu e-mail: ${env.APP_URL}/users/verify/email?token=${emailToken}`,
  html: `<p>Clique neste <a href="${env.APP_URL}/users/verify/email?token=${emailToken}">link</a> para verificar seu e-mail.</p>`
}

// 发送验证邮件
const resMG = await mgClient.messages.create(env.MAILGUN_DOMAIN, messageData);

console.log('Email enviado com sucesso: ', resMG)

2. 接收请求并验证Token的路由代码

import { makeVerifyUserEmailUseCase } from "@/application/factories/user/make-verify-user-email-use-case"
import { FastifyReply, FastifyRequest } from "fastify"
import { z } from "zod"

export default async function verifyUserEmail(request: FastifyRequest, reply: FastifyReply) {
  const verifyUserEmailQuerySchema = z.object({
    token: z.string(),
  })

  const { token } = verifyUserEmailQuerySchema.parse(request.query)
  console.log('TOKEN after parse: ', token)

  try {
    const decodedToken = request.jwtVerify({ token } as any, (error, decodedToken) => {
      if (error) {
        console.log('ERROR!')
        console.error(error)
        return reply.status(401).send('Erro na verificação do token')
      }
      return decodedToken
    })

    console.log('DECODED TOKEN: ', decodedToken)

    const emailToken = (decodedToken as any).sub.email
    console.log(emailToken)
    if ((decodedToken as any) && (decodedToken as any).sub?.email) {
      const verifyUserEmailUseCase = makeVerifyUserEmailUseCase()
      await verifyUserEmailUseCase.execute(emailToken)

      return reply.status(200).send({ message: 'E-mail verificado com sucesso!' })
    }
  } catch (error) {
    console.error(error)
  }

}

3. FastifyJWT插件配置

import fastifyJwt from '@fastify/jwt'

app.register(fastifyJwt, {
  secret: env.JWT_SECRET,
  cookie: {
    cookieName: 'refreshToken',
    signed: false,
  },
  sign: {
    expiresIn: '10m',
  },
})

错误原因

  1. 方法用途误解:request.jwtVerify()是FastifyJWT提供的路由前置验证钩子,用于自动从请求头(Authorization Bearer)或配置的Cookie中提取Token并验证,不支持手动传入Token的调用方式。
  2. 方法名称混淆:直接验证自定义Token的正确方法是request.jwt.verify(),属于request.jwt对象下的方法,而非request.jwtVerify()。

解决方法

1. 使用正确的验证方法

替换request.jwtVerify()为request.jwt.verify(),该方法支持直接传入Token字符串进行验证,返回解码后的内容。

2. 调整为异步Promise写法

避免使用回调,改用async/await处理验证逻辑,更符合代码风格。

3. 修正Token字段获取逻辑

生成Token时sub直接赋值为email,解码后decodedToken.sub即为邮箱地址,无需额外.email取值。

修改后的完整路由代码

import { makeVerifyUserEmailUseCase } from "@/application/factories/user/make-verify-user-email-use-case"
import { FastifyReply, FastifyRequest } from "fastify"
import { z } from "zod"

export default async function verifyUserEmail(request: FastifyRequest, reply: FastifyReply) {
  const verifyUserEmailQuerySchema = z.object({
    token: z.string(),
  })

  const { token } = verifyUserEmailQuerySchema.parse(request.query)

  try {
    // 使用request.jwt.verify()直接验证Token
    const decodedToken = await request.jwt.verify(token)
    
    // 直接从sub获取邮箱
    const userEmail = decodedToken.sub as string
    if (!userEmail) {
      return reply.status(400).send('Token inválido: não contém e-mail')
    }

    const verifyUserEmailUseCase = makeVerifyUserEmailUseCase()
    await verifyUserEmailUseCase.execute(userEmail)

    return reply.status(200).send({ message: 'E-mail verificado com sucesso!' })
  } catch (error) {
    console.error(error)
    return reply.status(401).send('Erro na verificação do token')
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 06:25:42