Reputation: 181
From Patreon documentation:
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.
This is how I have tried to verify the message in my Express
server:
import express from 'express';
import CryptoJS from 'crypto-js';
const router = express();
router.post('/webhook', function (req, res) {
const secret = 'Secret from https://www.patreon.com/portal/registration/register-webhooks';
console.log(CryptoJS.HmacMD5(req.body, secret).toString(CryptoJS.enc.Hex))
console.log(CryptoJS.HmacMD5(JSON.stringify(req.body), secret).toString(CryptoJS.enc.Hex))
const wordArray = CryptoJS.enc.Utf8.parse(req.body)
const hexString = CryptoJS.enc.Hex.stringify(wordArray);
console.log(CryptoJS.HmacMD5(hexString, secret).toString(CryptoJS.enc.Hex))
res.send();
});
But all these results that I am logging are not the same compared to the X-Patreon-Signature
value that I am getting from the header.
Upvotes: 2
Views: 742
Reputation: 548
Make sure your secret is correct in your code first then go ahead and create a new file that uses crypto to hash payloads.
I started with making a hashing module file with the funtion ComputeHash. This function takes a secret and payload for arguments:
const crypto = require('crypto');
/**
* @return {string}
*/
exports.ComputeHash = function (secret, payload)
{
// string to be hashed
const str = JSON.stringify(payload);
// create a md5 hasher
const md5Hasher = crypto.createHmac("md5", secret);
// hash the string
// and set the output format
const hash = md5Hasher.update(str).digest("hex");
return(hash);
};
Now this is how it should be Implemented to work with patreon in your API file:
DO note: in order to verify, you have to compare the SIGNATURE and HASH variables. If those are equal, it's verified.
I would suggest to implement this with middleware, but for demonstational purposes I've done it like this.
const Hasher = require('./../modules/Hasher');
//more code
.post('/', async (req, res) => {
try {
const secret = config.token;
const signature = req.headers["x-patreon-signature"];
const Hash = Hasher.ComputeHash(secret, req.body);
console.log(signature);
console.log(Hash);
const verified = (signature === Hash);
} catch (e) {
res.status(401);
res.end();
}
// more code
Upvotes: 2