Unable to verify webhooks successfully

Aptimyz
Visitor
3 0 0

I am unable to successfully verify any webhooks. I am doing the following:

 

publicfunctionverifyWebhook($request$secret) {
     $signature = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'];
     $calculated_hmac = base64_encode(hash_hmac('sha256'$request->input(), $secrettrue));
     if($signature != $calculated_hmac) {
          thrownewException('Webhook is not valid');
     }
     returntrue;
}
 
Where $request->input() is the response body and $secret is found below my webhook:
 
All your webhooks will be signed with xxxxx
 
I am sending my webhooks to a web hook catcher, I am then copying the entire body and posting it into Postman (raw body) and I then set a header as:
 
x-shopify-hmac-sha256: xxxxxx
 
I then post to my webapp and as mentioned the calculated hmac value will not match the header value above. I have tried several different webhook requests and I have substituted the key for every possible combination, app_secret, etc.
 
Any ideas?
 
Thanks,
 
Rob.
 
Replies 2 (2)

Aptimyz
Visitor
3 0 0

Alright, I figured it out. The webcatcher had an option to "format json" and "word wrap" which was obviously adding some formatting characters.

Therefore be sure to check that you are testing with the response body in its absolute raw format.

I hope this helps a few others!

Thanks.

theschoolofux
Shopify Partner
10 0 3

Had the same issue. Using request.rawBody instead of request.body helped. Also note that the secret key you should use for verification is not your Shopify API secret key, but the key under Webhooks section in your admin panel (<yourstore>.myshopify.com/admin/settings/notifications) where it says "All your webhooks will be signed with [SHOPIFY_WEBHOOKS_KEY] so you can verify their integrity".

 

import Router from "koa-router";
import koaBodyParser from "koa-bodyparser";
import crypto from "crypto";

...

koaServer.use(koaBodyParser()); 

...

koaRouter.post(
    "/webhooks/<yourwebhook>",
    verifyShopifyWebhooks,
    async (ctx) => {
      try {
        ctx.res.statusCode = 200;
      } catch (error) {
        console.log(`Failed to process webhook: ${error}`);
      }
    }
);

...

async function verifyShopifyWebhooks(ctx, next) {
  const generateHash = crypto
    .createHmac("sha256", process.env.SHOPIFY_WEBHOOKS_KEY)
    .update(ctx.request.rawBody, "utf-8")
    .digest("base64");

  if (generateHash !== shopifyHmac) {
    ctx.throw(401, "Couldn't verify Shopify webhook HMAC");
  } else {
    console.log("Successfully verified Shopify webhook HMAC");
  }
  await next();
}
Sergei Golubev | Devigner @ The School of UX | schoolofux.com