Topics covering webhook creation & management, event handling, Pub/Sub, and Eventbridge, in Shopify apps.
Hi.
I am working on a Shopify app which will send an order notification to my app when an order is placed in the Shopify store. I was able to create the Webhooks (orders/create topic) through API.
I need to validate the hmac with the secret key associated with the Webhooks. What I can't figure out is that when I create a Webhooks through API, how would I validate the hmac without asking a user to provide us with his/her secret key?
I'd like to automate a whole process(registering Webhooks(order and products) when a user installs my Shopify app) so that a Shopify store owner does. not have to manually enter anything for us.
The reason is that when I manually create a Webhooks in my Shopify testing store, I see a message 'All your webhooks will be signed with 41c81bc7184c43a6xxxxxxxxxxxxxxxxx so you can verify their integrity And I can use this secret key to validate the hmac which is part of the request header.
But I am not sure how I can validate hmac for Webhooks created through the API. I believe that Webhooks created through API are not showing up a Shopify setting/notification page, so obviously, there is no secret key associated with it.
I am not sure if I clarify my issue enough.
Solved! Go to the solution
This is an accepted solution.
Hi @windskystar
The webhooks created through the API will not display in the admin, that is intended behavior. Webhooks created through the API by a Shopify App are verified by calculating a digital signature. Each webhook request includes a base64-encoded X-Shopify-Hmac-SHA256 header, which is generated using the app's shared secret along with the data sent in the request.
You can read more on this here:
To learn more visit the Shopify Help Center or the Community Blog.
This is an accepted solution.
Hi @windskystar
The webhooks created through the API will not display in the admin, that is intended behavior. Webhooks created through the API by a Shopify App are verified by calculating a digital signature. Each webhook request includes a base64-encoded X-Shopify-Hmac-SHA256 header, which is generated using the app's shared secret along with the data sent in the request.
You can read more on this here:
To learn more visit the Shopify Help Center or the Community Blog.
For those who are looking for code example, this is my implementation in Node.js (I'm using Koa.js - for Express it almost the same)
const crypto = require('crypto') // Built-in module of Node.js
const Router = require('koa-router')
const router = new Router({ prefix: '/webhooks' })
// Middleware to verify all webhooks call from Shopify
async function verifyShopifyWebhooks(ctx, next) {
const topic = ctx.request.headers['x-shopify-topic']
const shop = ctx.request.headers['x-shopify-shop-domain']
const hmac = ctx.request.headers['x-shopify-hmac-sha256']
if (!hmac || !shop || !topic) {
return ctx.throw(401, "Webhook must originate from Shopify!")
}
const genHash = crypto
.createHmac('sha256', process.env.SHOPIFY_API_SECRET)
.update(JSON.stringify(ctx.request.body))
.digest('base64')
if (genHash !== hmac) {
ctx.throw(401, "Couldn't verify incomming Webhook request!")
}
await next()
}
router.use(verifyShopifyWebhooks)
// Here go all your webhooks API handlers
router.post("/customers/data_request", async (ctx) => {
ctx.status = 200
ctx.body = "Webhook processed!"
})
module.exports = router
It's worth pointing out that SHOPIFY_API_SECRET is not the API secret key, but the one that you can find in <yourstore>.myshopify.com/admin/settings/notifications page under Webhooks section that says "All your webhooks will be signed with <key> so you can verify their identity."
Is that so?
Super helpful, thanks Leo! I'll post my Sveltekit solution when I get approved
its not matching the hash