@code-nl/shopify-hmac
Version:
Shopify HMAC lib to verify Shopify calls
68 lines (53 loc) • 1.67 kB
JavaScript
;
const querystring = require("querystring");
const { hmacTimingSafeEqual, getHmacFromString } = require("./hmac");
/**
* Get the request object translated into a string as of Shopify would have signed it.
*
* @param {Object} request The request object
* @return {String} The query string as it would have been signed by Shopify
*/
exports.getSignableMessage = (request) => {
// clone the query object
const map = Object.assign({}, request.query);
// leave out the hmac itself
delete map.hmac;
// get the querystring as a string
const message = querystring.stringify(map);
return message;
};
/**
* Generate a signature based on request query.
*
* @param {Object} request The request object
* @param {String} secret API Secret
* @return {String} Generated HMAC
*/
exports.generate = (request, secret) => {
// get a signable message
const message = module.exports.getSignableMessage(request);
// generate hmac based on the message
const generatedHmac = getHmacFromString(message, secret, "hex");
return generatedHmac;
};
/**
* Verify request is from Shopify.
* HMAC verification based on the query string that is transmitted.
*
* @param {Object} request The request object
* @param {String} secret API Secret
* @return {Bool}
*/
exports.verify = (request, secret) => {
// get included hmac
const { hmac } = request.query;
// guard: hmac is a required property
if (typeof hmac !== "string" || !hmac) {
return false;
}
// generate HMAC
const generatedHmac = module.exports.generate(request, secret);
// verify
const valid = hmacTimingSafeEqual(hmac, generatedHmac);
return valid;
};