Jason
Jason

Reputation: 41

Can't verify webhook Node.js

I'm attempting to verify a webhook signature from Patreon using Node.js. Here is my code:

const crypto = require("crypto");

...

function validateJsonWebhook(request) {
  const secret = SECRET_KEY_GIVEN_BY_PATREON;

  const hash = crypto.createHmac("md5", secret)
      .update(JSON.stringify(request.body))
      .digest("hex");

  if (request.header("x-patreon-signature") === hash) {
    return true;
  } else {
    return false;
  }
}

Patreon webhooks use MD5 - see https://docs.patreon.com/#webhooks.

I've verified the secret key multiple times so I know that's not the issue.

Both "request.header("x-patreon-signature")" and "hash" are returning the correct format (i.e. they're both a 32 digit letter-number combination) but they're just not matching.

Any idea about what's going on?

Upvotes: 1

Views: 734

Answers (1)

Jason
Jason

Reputation: 41

So @gaiazov's comment led me to do some Googling which led me to the first two comments on Stripe verify web-hook signature HMAC sha254 HAPI.js by Karl Reid which led me to https://github.com/stripe/stripe-node/issues/331#issuecomment-314917167.

For anyone who finds this in the future: DON'T use JSON.stringify(request.body) - use request.rawBody instead, as the signature is calculated based on the raw JSON. I feel like this should be emphasized in Patreon's documentation, as all the examples I found used the code I originally posted. My new, working code is as follows (I cleaned up the "if (request.header("x-patreon-signature") === hash)" part at the end):

const crypto = require("crypto");

...

function validateJsonWebhook(request) {
  // Secret key given by Patreon.
  const secret = patreonSecret;

  const hash = crypto.createHmac("md5", secret)
      .update(request.rawBody)
      .digest("hex");

  return (request.header("x-patreon-signature") === hash);
}

Upvotes: 3

Related Questions