Cannot verify webhook HMAC in Koa

Solved
Paul91
Tourist
8 1 2

I am trying to verify my api secret for webhook requests in my Shopify app, but simply cannot get the two HMAC on the request and my token digest to match. Here is my code:

 

const verifyShopifyHook = ctx => {
  const { query } = ctx;
  const { hmac: _hmac, signature: _signature, ...map } = query;

  const orderedMap = Object.keys(map)
    .sort((value1, value2) => value1.localeCompare(value2))
    .reduce((accum, key) => {
      accum[key] = map[key];
      return accum;
    }, {});
  const message = querystring.stringify(orderedMap);

  let digest = crypto

    .createHmac("sha256", process.env.SHOPIFY_API_SECRET_KEY)
    .update(message, "utf8")
    .digest("base64");

  return digest === ctx.headers["x-shopify-hmac-sha256"];
};

I am definitely using the right tokens. Can anyone see what I am doing wrong?

0 Likes
SBD_
Shopify Staff
Shopify Staff
1044 141 186

Hey @Paul91,

 

I had an issue with this recently - the trick was to use the raw body (before it's turned into a string) or escape the backslashes.

 

More info: https://community.shopify.com/c/Shopify-APIs-SDKs/Can-t-verify-Webhooks-in-Node-js-serverless-AWS-la...

 

Let me know how you go.

Paul91
Tourist
8 1 2

This is an accepted solution.

Yep, the addition of rawBody ended up being the ticket. Here is my final implementation if anyone else runs across this:
 
const verifyShopifyHook = ctx => {
  const { headers, request } = ctx;
  const { "x-shopify-hmac-sha256": hmac } = headers;
  const { rawBody } = request;

  const digest = crypto
    .createHmac("SHA256", process.env.SHOPIFY_API_SECRET_KEY)
    .update(new Buffer(rawBody, "utf8"))
    .digest("base64");

  return safeCompare(digest, hmac);
};
Anonymous
Not applicable
1632 0 0

How I can use your function within the api?

0 Likes