Issue for validating the hmac for webhook

Solved
windskystar
New Member
2 0 1

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.

 

0 Likes
vix
Shopify Staff
Shopify Staff
535 105 107

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: 

Vix | Developer Support @ 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

0 Likes

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

 

 

Leo Huynh | Software Engineer @ Insights Studio
Email: anhhuynh@insights.is
Personal website: https://leohuynh.dev
0 Likes