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

如何在Node.js中使用jose验证Firebase会话Cookie(JWT)

使用jose包验证Firebase会话Cookie

需求背景

我目前使用Firebase的verifySessionCookie方法验证会话Cookie,代码能正常工作:

export async function getDecodedSessionCookie() {
  // 获取sessionCookie
  const sessionCookie = cookies().get("sessionCookie")
  if (sessionCookie === undefined) return null

  // 验证Cookie但不检查是否已撤销,不确定这是否有安全风险,但这样会增加显著延迟
  return (
    adminAuth
      .verifySessionCookie(sessionCookie.value, false)

      // 验证通过则返回解码后的Claims
      .then((decodedClaims) => {
        return decodedClaims
      })
      .catch((e) => console.log("error", e))
  )
}

但这个方法速度极慢,而且无法在Vercel Edge Runtime中执行。我打算参考官方文档和Python示例,使用jose包(也可接受其他Node.js包)来验证JWT格式的会话Cookie。

已尝试方案

我对这个主题了解有限,以下是我的尝试代码:

export async function getDecodedSessionCookie2() {
  // 如果Cookie不存在或无效则返回null
  const sessionCookie = cookies().get("sessionCookie")
  if (sessionCookie === undefined) return null

  // 解码头部(这一步能正常工作)
  const header = jose.decodeProtectedHeader(sessionCookie.value)
  console.log("header", header)

  // 解码Cookie(这一步能正常工作)
  const sessionCookieDecoded = jose.decodeJwt(sessionCookie.value)
  console.log("sessionCookieDecoded", sessionCookieDecoded)

  // 创建远程密钥集(此处报错:JSON Web Key Set malformed)
  const JWKS = jose.createRemoteJWKSet(
    new URL(
      "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com"
    )
  )
  const keyset = await JWKS()
  console.log("keyset", keyset)

  // 后续代码从未执行到这里
  const audience = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID
  const issuer = `https://securetoken.google.com/${audience}`

  // 后续代码从未执行到这里
  const { payload, protectedHeader } = await jose.jwtVerify(
    sessionCookie.value,
    JWKS,
    {
      issuer,
      audience,
    }
  )
  console.log("protectedHeader", protectedHeader)
  console.log("payload", payload)

  // 不确定这一步是否需要?
  // const x509 = certificates["7cf7f8727091e4c77aa995db60743b7dd2bb70b5"]
  // const ecPublicKey = await jose.importX509(x509, algorithm)

  return sessionCookieDecoded
}

我认为需要用createRemoteJWKSet创建远程密钥集,但这一步始终报错,导致后续验证无法进行。

补充说明

  1. Firebase令牌的头部应包含kid字段:
    • 生产环境中我看到kid: lk02Aw,但这个值和公开密钥不匹配;
    • 使用Auth Emulator本地开发时,kid字段不存在。
  2. 想了解公开证书是否会频繁变更?

更新记录

  • 借助jose包作者的指导,我已经解决了上述错误,完成令牌验证后会更新完整细节。
  • 我了解到Google公开密钥每12小时轮换一次。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:24:52