Hookdeck
Signature verification overviewAdd signature verificationEdit a signature verificationRemove a signature verification

Signature verification overview

Verifying the original provider's signature before processing webhooks prevents bad actors from taking illegitimate actions on your server.

Hookdeck does verify the provider's signature when verification is enabled for your source. In this case, an x-hookdeck-verified header is set to true to confirm the original request was verified, meaning it is safe to verify just the Hookdeck signature.

It's possible to configure verification with most platforms using our dedicated integrations, or our "configure-your-own" integration that supports generic implementations of Basic Auth, API Keys, and HMAC signature.

Out of the box, Hookdeck supports signature verification and other platform-specific functionality for Twitter, GitHub, Shopify, Stripe, and more. A full list of providers, along with configuration options, lives on the Integrations page.

You can also roll your own integration for any platform that supports verification using HMAC, Basic Auth, or an API key.

How verification work

When a source has verification configured, Hookdeck will verify every incoming request either with HMAC, Basic Auth, or an API key. Requests that do not match the verification are rejected and labeled "Verification Failed" in the request page.

When using integrations, it's safe to skip the original provider's verification step and only verify Hookdeck's header. This saves you time, since you only need to implement a single verification process across multiple providers.

Hookdeck will return a HTTP 401 for the HMAC (expect MD5), API Key, and Basic Auth verification methods and for the Shopify, Zoom, Xero, Twitter integrations. For the other integrations, Hookdeck will return a HTTP 200.

Verify the Hookdeck Signature

By default, Webhooks sent by Hookdeck are verified by calculating a digital signature. Each webhook request includes a x-hookdeck-signature header, generated using the workspace's secret along with the data sent in the request. If the previous secret was rolled with a delay and is still active, a x-hookdeck-signature-2 header is also provided. To verify the request, compute the HMAC digest according to the following algorithm and compare it to the value in the x-hookdeck-signature and x-hookdeck-signature-2 headers. If they match, the webhook was sent from Hookdeck.

To retrieve the signing secret, head over to the secrets tab in the workspace page.

Hookdeck signatures use a SHA-256 algorithm and are base64 encoded.

javascript
app.use(
  express.json({
    // Store the rawBody buffer on the request
    verify: (req, res, buf) => {
      req.rawBody = buf;
    },
  })
);

app.post('/webhook', async (req, res) => {
  //Extract x-hookdeck-signature and x-hookdeck-signature-2 headers from the request
  const hmacHeader = req.get('x-hookdeck-signature');
  const hmacHeader2 = req.get('x-hookdeck-signature-2');

  //Create a hash based on the parsed body
  const hash = crypto.createHmac('sha256', secret).update(req.rawBody).digest('base64');

  // Compare the created hash with the value of the x-hookdeck-signature and x-hookdeck-signature-2 headers
  if (hash === hmacHeader || hash === hmacHeader2) {
    console.log('Webhook is originating from Hookdeck');
    res.sendStatus(200);
  } else {
    console.log('Signature is invalid, rejected');
    res.sendStatus(403);
  }
});

Customize destination authentication strategy

There are several reasons why you may want to customize the authentication strategy sent by Hookdeck to your destinations. Maybe you have your own authentication strategy you'd like to use instead of Hookdeck's SHA-256 signature. Or maybe you're routing requests to another service which requires a different authentication mechanism.

Regardless, you can customize this authentication in your destination configuration.

Destination authentication