Skip to content

Latest commit

 

History

History
53 lines (44 loc) · 2.35 KB

event-webhook.md

File metadata and controls

53 lines (44 loc) · 2.35 KB

First, follow the guide to set up signature verification for event webhooks

Note: It is important that the body of the request is verified raw (as a Buffer or string), not after it was parsed as json.
If you are using express.json() or bodyParser.json() you will need to exclude the webhook path from it (one way to do it is using express-unless).

An example of a server to process incoming event webhooks:

const bodyParser = require("body-parser"); // With Express 4.16+ you do not need this and can use express.json() and express.raw() instead
const unless = require('express-unless');
const express = require('express');
const functions = require("firebase-functions");
const app = express();

const {EventWebhook, EventWebhookHeader} = require('@sendgrid/eventwebhook');

const verifyRequest = function (publicKey, payload, signature, timestamp) {
  const eventWebhook = new EventWebhook();
  const ecPublicKey = eventWebhook.convertPublicKeyToECDSA(publicKey);
  return eventWebhook.verifySignature(ecPublicKey, payload, signature, timestamp);
}

// Exclude the webhook path from any json parsing
const json_parser = bodyParser.json();
json_parser.unless = unless;
app.use(json_parser.unless({ path: ["/sendgrid/webhook"]}));

app.post("/sendgrid/webhook",
  // parse req.body as a Buffer
  bodyParser.raw({ type: 'application/json' }),
  async (req, resp) => {
    try {
      const key = '<your_public_key>';
      // Alternatively, you can get your key from your firebase function cloud config
      // const key = getConfig().sendgrid.webhook_verification_key;

      const signature = req.get(EventWebhookHeader.SIGNATURE());
      const timestamp = req.get(EventWebhookHeader.TIMESTAMP());

      // Be sure to _not_ remove any leading/trailing whitespace characters (e.g., '\r\n').
      const requestBody = req.body;
      // Alternatively, if using firebase cloud functions, remove the middleware and use:
      // const requestBody = (req as functions.https.Request).rawBody;

      if (verifyRequest(key, requestBody, signature, timestamp)) {
        resp.sendStatus(204);
      } else {
        resp.sendStatus(403);
      }
    } catch (error) {
      resp.status(500).send(error);
    }
})