Created
October 25, 2018 19:38
-
-
Save gjesse/3ee37b2031e8e29ea96a3c4677f480d2 to your computer and use it in GitHub Desktop.
lithium hmac example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// get the crypto-js lib for hashing | |
var crypto = require('crypto-js'); | |
// get and check the validity of the api key | |
var apiKey = req.headers['x-auth-apikey']; | |
if (apiKey !== "<your expected api key>") { | |
console.log("invalid api key provided") | |
res.status(401).end(); | |
return; | |
} | |
// regex for removing the port section from the host header | |
var portTrim = /:\d+$/; | |
// get the host from headers without the port | |
var host = req.headers['host'].replace(portTrim, "") | |
// get the provided timestamp header | |
var ts = req.headers['x-auth-timestamp']; | |
// get the expected signature | |
var sig = req.headers['x-auth-signature-v2']; | |
// calculate header portion of the fingerprint | |
var headerFingerprint = getHeaderFingerprint(req.headers); | |
// construct the fingerprint | |
var fingerprint = [ts, req.method, host + req.url, req.rawBody, headerSig].join('|'); | |
// hash our fingerprint with our secret | |
var hahs = crypto.HmacSHA256(fingerprint, secret); | |
// convert to a base64 encoded string | |
var calculatedSig = crypto.enc.Base64.stringify(hash); | |
// make sure our signatures match | |
if (sig !== calculatedSig) { | |
console.log("provided sig: %s. calculated sig: %s", sig, calculatedSig); | |
console.log("signatures do not match!") | |
res.status(401).end(); | |
return; | |
} | |
// finally check the timestamp | |
var now = Date.now() | |
if (Math.abs(now - ts) > 60000) { | |
console.log("time drift is too much - rejecting") | |
res.status(401).end(); | |
return; | |
} | |
// extract relevant headers and construct a fingerprint header string | |
function getHeaderFingerprint(headers) { | |
// holder array for matching headers | |
var smmHeaders = []; | |
// loop through all the provided headers | |
for (var key in headers) { | |
var element = headers[key]; | |
// filter in only x-smm-* keys | |
if (key.startsWith("x-smm-")) { | |
// your framework may represent multiple header values as a list - if so this will be a little different | |
// loop over each element for the header | |
element.split(",").forEach(part => { | |
// push any found elements on to the array | |
smmHeaders.push(":" + key + ":" + part.trim()); | |
}) | |
} | |
} | |
// sort all headers alphabetically | |
smmHeaders.sort(); | |
// return a : separated string | |
return smmHeaders.join("") | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment