Skip to content

Instantly share code, notes, and snippets.

@josh-authy
Last active August 13, 2017 14:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save josh-authy/72952c62521480f3dd710dcbad0d8c42 to your computer and use it in GitHub Desktop.
Save josh-authy/72952c62521480f3dd710dcbad0d8c42 to your computer and use it in GitHub Desktop.
HMAC Verification with Node.js
var qs = require('qs');
var crypto = require('crypto');
/**
* @param {http request} req
* @param {!string} apiKey
* @return {Boolean} True if verified
*/
function verifyCallback(req, apiKey) {
var url = req.headers['x-forwarded-proto'] + "://" + req.hostname + req.url;
var method = req.method;
var params = req.body;
// Sort the params.
var sorted_params = qs.stringify(params, { arrayFormat: 'brackets' }).split("&").sort(sortByPropertyOnly).join("&").replace(/%20/g, '+');
var nonce = req.headers["x-authy-signature-nonce"];
var data = nonce + "|" + method + "|" + url + "|" + sorted_params;
var computed_sig = crypto.createHmac('sha256', apiKey).update(data).digest('base64');
var sig = req.headers["x-authy-signature"];
return sig == computed_sig;
}
/**
* Sort by property only.
* Normal JS sort parses the entire string so a stringified array value like 'events=zzzz'
* would be moved after 'events=aaaa'.
*
* Instead we split tokenize the string around the '=' value and only sort alphabetically
* by the property.
*
* @param {string} x
* @param {string} y
* @returns {number}
*/
function sortByPropertyOnly(x, y){
var xx = x.split("=");
var yy = y.split("=");
if (xx < yy) {
return -1;
}
if (xx > yy) {
return 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment