node js中的Sendgrid webhook签名验证失败

rxztt3cl  于 2023-05-17  发布在  Node.js
关注(0)|答案(1)|浏览(523)

我试图在node.js中验证Sendgrid的webhooks的签名,但我得到了一致的验证失败。我试过使用“测试集成”功能,“测试电子邮件”,但也实际发送,但所有这些选项最终与验证失败。
我正在使用node.js的官方帮助程序,可以在这里找到:https://github.com/sendgrid/sendgrid-nodejs/blob/main/packages/eventwebhook/src/eventwebhook.js
请注意,此代码是在云函数上实现的。

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

export const handleSendGridWebhookEvents = functions
  .region(...fb.REGIONS)
  .https.onRequest(async (req, resp) => {

    const signature =
      (req.get("x-twilio-email-event-webhook-signature") as string) ??
      "";
    const timestamp =
      (req.get("x-twilio-email-event-webhook-timestamp") as string) ??
      "";

    if (!signature || !timestamp) {
      resp.json({
        error: "Webhook handler failed",
      });
      throw new Error("Sendgrid headers missing");
    }

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

    try {
      const ecdsaPublicKey = verify.convertPublicKeyToECDSA(publicKey);
      const isVerified = verify.verifySignature(
        ecdsaPublicKey,
        payload,
        signature,
        timestamp
      );
      console.log({ isVerified }); // Always returns false
      resp.status(200);
    } catch (e) {
      throw e;
    }
    resp.json({ received: true });
  });

我也试过直接使用公钥,而没有初始转换为ECDSA,但也没有成功。
是否需要任何其他步骤来验证签名?上面的代码有什么问题吗?

谢谢

bsxbgnwa

bsxbgnwa1#

我终于有了一个“Eureka ”的时刻。
需要在函数中传递的有效负载需要是请求的rawBody,而不是body
我已经更新了我的代码来反映这一点。
这使得它成为我在Node.js中看到的唯一一个工作示例。

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

export const handleSendGridWebhookEvents = functions
  .region(...fb.REGIONS)
  .https.onRequest(async (req, resp) => {

    const signature =
      (req.get("x-twilio-email-event-webhook-signature") as string) ??
      "";
    const timestamp =
      (req.get("x-twilio-email-event-webhook-timestamp") as string) ??
      "";

    if (!signature || !timestamp) {
      resp.json({
        error: "Webhook handler failed",
      });
      throw new Error("Sendgrid headers missing");
    }

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

    try {
      const ecdsaPublicKey = verify.convertPublicKeyToECDSA(publicKey);
      const isVerified = verify.verifySignature(
        ecdsaPublicKey,
        payload,
        signature,
        timestamp
      );
      console.log({ isVerified }); // Yes!
      resp.send({ received: true }).status(200);
    } catch (e) {
      throw e;
      resp
        .send({
          error: "Webhook handler failed.",
        })
        .status(500);
    }
  });

相关问题