Topics covering webhook creation & management, event handling, Pub/Sub, and Eventbridge, in Shopify apps.
Hey :),
im trying to veryfiy webhooks in my nodejs app. but it just doesnt work, here is my code :
app.use(shopify.config.webhooks.path, async (req, res, next) => { if (!req.body) { return res.status(401).send("Couldn't verify incomming Webhook request!"); } const hmac = req.headers["x-shopify-hmac-sha256"]; const genHash = crypto .createHmac("sha256", process.env.SHOPIFY_API_SECRET) .update(JSON.stringify(req.body), "utf8", "hex") .digest("base64"); console.log(hmac); console.log(genHash); if (genHash !== hmac) { return res.status(401).send("Couldn't verify incomming Webhook request!"); } next(); });
Please help meee
Solved! Go to the solution
This is an accepted solution.
Hi Harelk1015,
Your code seems to be on the right track for verifying Shopify webhooks in a Node.js app. However, there are a few common pitfalls and nuances to be aware of:
1. Raw Body Parsing: Shopify's HMAC verification requires the raw request body. If you're using a body parser middleware like express.json(), it will parse the body before your webhook verification code gets to it. You need to capture the raw body before it's parsed.
2. Buffered Raw Body: Instead of using JSON.stringify(req.body), you should use the raw buffered body for the HMAC calculation.
3. Middleware Order: Ensure that your webhook verification middleware is placed before any body parsing middleware in your Express app.
Here's a revised version of your code, capturing the raw body and using it for verification:
const bodyParser = require('body-parser');
// Middleware to capture raw body
app.use(shopify.config.webhooks.path, bodyParser.raw({ type: 'application/json' }), async (req, res, next) => {
const hmac = req.headers["x-shopify-hmac-sha256"];
const genHash = crypto
.createHmac("sha256", process.env.SHOPIFY_API_SECRET)
.update(req.body, "utf8", "hex")
.digest("base64");
console.log(hmac);
console.log(genHash);
if (genHash !== hmac) {
return res.status(401).send("Couldn't verify incoming Webhook request!");
}
// Now, if you want to use the parsed body later in your app, you can parse it here:
req.body = JSON.parse(req.body);
next();
});
Hope this helps!
Liam | Developer Advocate @ Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
This is an accepted solution.
Hi Harelk1015,
Your code seems to be on the right track for verifying Shopify webhooks in a Node.js app. However, there are a few common pitfalls and nuances to be aware of:
1. Raw Body Parsing: Shopify's HMAC verification requires the raw request body. If you're using a body parser middleware like express.json(), it will parse the body before your webhook verification code gets to it. You need to capture the raw body before it's parsed.
2. Buffered Raw Body: Instead of using JSON.stringify(req.body), you should use the raw buffered body for the HMAC calculation.
3. Middleware Order: Ensure that your webhook verification middleware is placed before any body parsing middleware in your Express app.
Here's a revised version of your code, capturing the raw body and using it for verification:
const bodyParser = require('body-parser');
// Middleware to capture raw body
app.use(shopify.config.webhooks.path, bodyParser.raw({ type: 'application/json' }), async (req, res, next) => {
const hmac = req.headers["x-shopify-hmac-sha256"];
const genHash = crypto
.createHmac("sha256", process.env.SHOPIFY_API_SECRET)
.update(req.body, "utf8", "hex")
.digest("base64");
console.log(hmac);
console.log(genHash);
if (genHash !== hmac) {
return res.status(401).send("Couldn't verify incoming Webhook request!");
}
// Now, if you want to use the parsed body later in your app, you can parse it here:
req.body = JSON.parse(req.body);
next();
});
Hope this helps!
Liam | Developer Advocate @ Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
OMG, thanks so much ahahahhaha.
finally the recived hmac and the one that im generating matching! i love it thank you a lot!
I do still see this in the console, that does that mean ?
2023-08-08 15:32:50 │ backend │ [shopify-api/INFO] Receiving webhook request
2023-08-08 15:32:50 │ backend │ [shopify-app/ERROR] Failed to process webhook: Error: No body was received when processing webhook
hi, this code works to get the raw body. But still the generated hash and the one in the header doesnt match. The secret key is fetched from the "API Credentails -> API secret key"?
You are right, they really dont match, did you solve it ?? 😞
Yes i'm also stuck on verification of hmac
did you solve maybe ?
Failed to process webhook: Error: No body was received when processing webhook --> this error happens because you parse the object instead of string.
At the end of solution, there is a line of code to parse the JSON, my guess is you parse the JSON twice because I did it before. You should delete that row and it should solve the error. I attached the code that I mentioned.
const hmac = _.get(req, 'headers.x-shopify-hmac-sha256', '');
I applied your code. But when I compare hmac from header and general hash from SHOPIFY_API_SECRET (From API key and secret key), they really not match