I am developing an application to handle patron web hooks and process event based on new pledges, updates and deletes. I created a webhook and when I try to test it, it always fails.
My application is on Node, Express 4. I followed your documentation to on signature validation
Blockquote where the message signature is the HEX digest of the message body HMAC signed (with MD5) using your webhook’s secret viewable on the webhooks page. You can use this to verify us as the sender of the message.
I validated the code using a test webhook, and it seemed to work perfectly. You are correct that you need to call JSON.stringify. Can you clarify what you mean by testing it from “application settings”?
Without that Express won’t parse the body of the POST request – which will result in the signature validation failing. The code you’ve provided works for me, too, when body-parser is included with the json parser chosen. you can try it here:
Edit: this code was updated on May 31st, 2018, to fix a bug: parsing the input as JSON and then turning it back into a string can cause some encoding issues which will cause signature verification to fail sometimes.
Hey, I have a similiar problem.
Using this code the hash check is always false:
let webhookSecret = 'SECRET_FOR_WEBHOOK';
let data = JSON.stringify(req.body);
const hash = crypto.createHmac('md5', webhookSecret).update(data).digest('hex');
let msg = 'Webhook received, signature validation status: ' + (req.get('X-Patreon-Signature') === hash);
console.log(msg, req.get('X-Patreon-Signature'), hash, req.get('X-Patreon-Event'));
Express.js 4.16.3
body-parser 1.18.2
And yes I do app.use(bodyParser.json());
Data seems also fine if I look at it, but the check fails all the time. Any hints? Is this supposed to fail via the Send test webhook? Would appreciate it.
Edited on May 31st 2018: the issue experienced in this thread, and discussed below, was due to encoding. Please see the note in post #4.
The example code should (and does) verify successfully when using the example webhooks provided by Patreon, I’ve just tried it now and confirmed that for each of the events (pledges:create, pledges:update, pledges:delete).
The request body and webhook secret must be character-for-character accurate, so any trailing spaces or newlines will cause verification to fail. Additionally, each webhook secret is unique to the webhook URL, ensure that you’re using the correct webhook secret – and make sure it’s the webhook secret not your client secret.
You can follow these steps to use the example code with glitch:
That allows you to confirm that the example code works, and that the issue is somewhere in your application. I’d expect it’s an issue with your webhook secret not being correct, otherwise it’s probably to do with how you’re obtaining the request body.
Scratch all that. I think this is the problem: X-Patreon-Signature is a header, not a parameter. You’re using get which (I guess, I’m not an express developer) means parameter not header, so you need to do req.header instead.
Edit: nevermind, req.get is the right method for fetching a header value in Express 4, what an odd method name choice: Express 4.x - API Reference. So, my original suggestions apply.
Thanks for the fast reply! I did the glitch example and even there: it shows false for every event. I can even provide screenshots if you would like. I checked the secret multiple times. And again,. the data looked fine there, only the hash check is false. Should I post you the example maybe?
req.get() and req.header() are pretty much the same so that’s probably not it.
That’s really strange, perhaps there’s an issue with the secrets that Patreon is providing you? That’s all that really makes sense to me right now if the code is working for me with my webhook secrets, but isn’t working for you with yours. Unfortunately I’m just another user of the platform so I wouldn’t be able to debug any issues like that for you.
Feel free to post the full example, I’ll take a look. My best guess for debugging would be to simply print out all of the values involved and compare them to what is expected because I expect the issue is with the values somewhere. If you don’t mind using PHP to test, my Patreon PHP library has unit tests for signature verification so you could use that to verify whether the issue is with the values or the code I guess.
I think we’ve ruled out the code as the issue, although I’m not primarily a Javascript developer so I could be missing something.
This forum is monitored by the Patreon platform team. As far as I know they are here during the week, so they’ll probably be along in the morning to provide input. Sorry I couldn’t help further!
Thank you. Well, there is probably something wrong with my secrets which seems super weird honestly. Let’s hope some dev stops by here. oauth is working decently for me in combination with auth0. Only the webhook is behaving weird. I mean it works, data-wise, but It’s probably not a good idea to not check the signature.
Hi Xzandro, in fact you must not do JSON.stringify() or use the req.body at all for the hmac.
The string you want to test is the raw body and using JSON.stringify() on the parsed JSON body is not gonna reproduce the same exact string as the original body. A single change byte and the signatures are no going to match.
You need to apply the hmac to req.rawBody. If req.rawBody is not present or not set, you might need to use body-parser and/or raw-body.
However req.body inside the update doesn’t work. As noted above JSON.stringify() while correcting the “Data argument must box one of type string…” error, does NOT match the expected signature.
I don’t want to change how my server handles all requests either, this is the only endpoint which requires the raw body.
So… turns out that because I’m using bodyParser it causes all manner of issues with this type of endpoint being able to calculate properly… It has taken me hours but I found a post by Scott Dixon which has the solution.
Basically the solution is… for the route that needs it only, add an app.use()before the app.use(bodyParer.json()) line.