Skip to content

Instantly share code, notes, and snippets.

@shawncarr
Last active May 25, 2017 12:07
Show Gist options
  • Save shawncarr/9513545 to your computer and use it in GitHub Desktop.
Save shawncarr/9513545 to your computer and use it in GitHub Desktop.
Validating a Mandrill Webhook request for nodejs
var Crypto = require('crypto');
/**
* validates a mandrill webhook request
* @param url string the url that mandrill sent the request to
* @param key string the web hook key from https://mandrillapp.com/settings/webhooks
* @param params array the request's POST parameters i.e. req.params
* @param compareTo string the x-mandrill-signature header value
*/
var validate = function validate(url, key, params, compareTo) {
var data = url;
for(var postKey in params) {
data += postKey;
data += postData[postKey];
}
var signer = Crypto.createHmac('sha1', key);
var signature = signer.update(data).digest('base64');
return compareTo && signature === compareTo;
};
@nuarhu
Copy link

nuarhu commented Dec 4, 2014

You might need to escape the forward slashes in the body. At least the string used by Mandrill as body will have escaped forward slashes.

@gregbarcza
Copy link

postData should be params at line 14

@diorahman
Copy link

In express + body-parser:

'use strict';

const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto');
const server = express();

server.use(bodyParser.urlencoded({extended: true}));

const key = 'your_random_webhook_key';
let url = 'http://your-webhook.com?handler=hello';

server.post('/hook', (req, res) => {
    let keys = Object.body.keys().sort();
    for (let key of keys) {
        url += key + req.body[key];
    }
    let signer = crypto.createHmac('sha1', key);
    let signature = signer.update(url).digest('base64');
    console.log(req.headers['x-mandrill-signature'] === signature);
    res.send(req.headers['x-mandrill-signature'] === signature ? 'Yeay!' : 'Nay!');
});

server.listen(8000 || env.process.PORT);

@teckays
Copy link

teckays commented Feb 13, 2017

One line alternative to this:

let keys = Object.body.keys().sort(); // which should actually be Object.keys(body).sort()
for (let key of keys) {
    url += key + req.body[key];
}

url += Object.keys(body).sort().map(key => ${key}${body[key]})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment