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

Node.js中SendGrid Webhook签名验证持续失败问题排查

解决SendGrid Webhook签名验证失败问题

你的代码存在两个核心问题导致验证始终失败,以下是针对性修复方案:

1. 使用原始请求体而非解析后的对象

Firebase Cloud Function会自动将JSON请求体解析为JavaScript对象,但SendGrid的签名是基于原始UTF-8编码的请求体字符串生成的。解析再序列化后的字符串,会和原始payload的格式(比如键的顺序、空格、引号格式)产生差异,直接导致签名验证不通过。

必须获取原始请求体字符串进行验证:Cloud Function的req对象提供rawBody属性,直接转换为UTF-8字符串即可。

2. 公钥格式校验

确保环境变量SENDGRID_WEBHOOK_PK中的公钥是完整的PEM格式:

-----BEGIN PUBLIC KEY-----
你的公钥内容
-----END PUBLIC KEY-----

不要遗漏首尾的标记,也不要包含多余的换行或空格。

修正后的完整代码

import * as functions from "firebase-functions";
import { EventWebhook } from "@sendgrid/eventwebhook";

export const handleSendGridWebhookEvents = functions
  .region(...fb.REGIONS)
  .https.onRequest(async (req, resp) => {
    // 获取原始请求体字符串
    const rawPayload = req.rawBody.toString("utf8");
    const signature = req.get("x-twilio-email-event-webhook-signature") || "";
    const timestamp = req.get("x-twilio-email-event-webhook-timestamp") || "";

    if (!signature || !timestamp) {
      resp.status(400).json({ error: "Missing required SendGrid headers" });
      return;
    }

    const verify = new EventWebhook();
    const publicKey = process.env.SENDGRID_WEBHOOK_PK;

    if (!publicKey) {
      resp.status(500).json({ error: "SendGrid public key not configured" });
      return;
    }

    try {
      const ecdsaPublicKey = verify.convertPublicKeyToECDSA(publicKey);
      // 用原始请求体执行验证
      const isVerified = verify.verifySignature(
        ecdsaPublicKey,
        rawPayload,
        signature,
        timestamp
      );

      if (!isVerified) {
        resp.status(403).json({ error: "Signature verification failed" });
        return;
      }

      // 验证通过后再解析请求体处理事件
      const payload = JSON.parse(rawPayload);
      console.log("Validated events:", payload);
      resp.status(200).json({ received: true, verified: true });
    } catch (e) {
      console.error("Verification error:", e);
      resp.status(500).json({ error: "Webhook verification failed" });
    }
  });

额外检查项

  • 确认SendGrid控制台配置的Webhook URL和你的Cloud Function URL完全一致(必须是HTTPS)
  • 测试时查看Cloud Function日志,排查是否有公钥格式错误、环境变量未加载等异常
  • 使用SendGrid「Test Integration」工具测试时,确保请求未被中间代理篡改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 12:50:32