Sendgrid webhook签名验证失败在Node.js中

huangapple go评论60阅读模式
英文:

Sendgrid webhook signature verification failures in node js

问题

I am trying to verify the signature of Sendgrid's webhooks in node.js but I am getting consistent verification failures.
我正在尝试在node.js中验证Sendgrid的Webhooks签名,但我一直得到一致的验证失败。

I have tried using the "Test Integration" feature, "Test emails", but also actual sends but all these options end up with verification failures.
我尝试使用“测试集成”功能、“测试邮件”,甚至实际发送,但所有这些选项都导致了验证失败。

I am using the official helper for node.js, available here: https://github.com/sendgrid/sendgrid-nodejs/blob/main/packages/eventwebhook/src/eventwebhook.js
我正在使用node.js的官方帮助程序,可以在这里找到:https://github.com/sendgrid/sendgrid-nodejs/blob/main/packages/eventwebhook/src/eventwebhook.js

Please note that this code is implemented on a Cloud Function.
请注意,此代码在Cloud Function上实现。

I have tried using the public key directly as well without the initial conversion to ECDSA but no luck there either.
我也尝试直接使用公钥,而不进行初始的ECDSA转换,但结果也没有好转。

Are there any additional steps required to verify the signature? Or anything wrong with the code above...?
还需要其他步骤来验证签名吗?或者上面的代码有什么问题吗...?

Sendgrid webhook签名验证失败在Node.js中
Sendgrid webhook签名验证失败在Node.js中

Thanks
谢谢

英文:

I am trying to verify the signature of Sendgrid's webhooks in node.js but I am getting consistent verification failures.
I have tried using the "Test Integration" feature, "Test emails", but also actual sends but all these options end up with verification failures.

I am using the official helper for node.js, available here: https://github.com/sendgrid/sendgrid-nodejs/blob/main/packages/eventwebhook/src/eventwebhook.js

Please note that this code is implemented on a Cloud Function.

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 });
  });

I have tried using the public key directly as well without the initial conversion to ECDSA but no luck there either.

Are there any additional steps required to verify the signature? Or anything wrong with the code above...?

Sendgrid webhook签名验证失败在Node.js中

Thanks

答案1

得分: 1

I finally had a Eureka moment.

需要传递给函数的有效负载应该是请求的 rawBody,而不是 body

我已经更新了我的代码以反映这一点。

这使它成为我在 Node.js 中看到的唯一可用的示例。

英文:

I finally had a Eureka moment.

The payload that needs to be passed in the function needs to be the rawBody of the request, not the body.

I have updated my code to reflect this.

Which makes it the only working example I have seen in 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);
    }
  });

huangapple
  • 本文由 发表于 2023年5月10日 15:18:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76215848.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定