Webhook Workflow Verify Integrity Shopify

I am trying to tie a retool workflow trigger to a webhook from Shopify. Within shopify, I can create a bunch of notifications and tie them to webhooks in Retool. Seems to work just fine for my sandbox environment. However, in production I like the idea of leveraging the provided webhook signature which shopify sends out as another layer of security to authenticate the authenticity of the payload. I wouldn't want spoofed orders or shipments triggering production and shipment of goods which haven't been paid for ect. I have seen from other posts that you can access the headers. Shopify also has a reference which shows you some python code implementing this task which I think could be used in Retool. However, I am struggling to test this as workflows really only allow you to simulate JSON bodies. If anybody has a working implementation or any tips it would be appreciated.

It seems like other post are trying to implement examples with Stripe or Xero but I haven't found any functional examples. Yet it does seem possible from what I have read elsewhere.

Example shopify documentation

Hi Laith,

I believe you can access the header properties by referencing {{startTrigger.metadata}} or {{startTrigger.headers}} I can't remember exactly.

The best way to see the headers is to just send a test query/webhook event to your ReTool endpoint and you can check the Run history log and the JSON tab for startTrigger, which should show you everything.

I can see the hmac stuff in the header here... ["startTrigger.data"].headers["x-shopify-hmac-sha256"]. I am not super familiar with encryption, the values don't match because they are hashed? So I basically need to decript the value I see here and compare it to my client secret and then if the value matches return a 200 and continue else return a 401. I am more familiar with Javascipt and the example is in Python. Other posts reference a crypto js menthod of implementing. Here are two relevant threads which reference this concept with no concrete solutions.

Hi Laith,

You're on the right track but yes essentially what you're trying to do here is take the incoming data encrypt it in the SHA256 using a javascript crypto module (just google one) and compare the encrypted string with the one contained in the header. If they match it's valid if they don't match it's not valid.

there is crypto.timingSafeEqual(buffer, buffer);

since you already have both hmac values, you just need to make a couple buffers and call the function:

let computed_hmac = "yaidkm8stuff"
let header_hmac = "youalreadyhavethissoidontneedtoguess"

crypto.timingSafeEqual(Buffer.from(computed_hmac), Buffer.from(header_hmac));

https://nodejs.org/docs/latest-v6.x/api/crypto.html#crypto_crypto_timingsafeequal_a_b

hopefully this gets ya across the finish line. I've never had to do this, so I'm just going off of documentation (I have used crypto js, but not for this and I avoid buffers cause I'm a C/C++ person and "Buffer overflow" errors still give me nightmares lol)

Thanks Guys for the help,
I am still having some trouble and I am not 100% sure why... I took a screenshot of my workflow.

hmacKey just returns the webhook signature string which Shopify provides, not passed through anything, not sure if that is correct. I have imported the cryptojs v4.2 library in the workflow. However, I still have two errors I can't get to go away. The first one is:


I can literally read it and I have copied the path from the ui possibly I need to add a delay or await, but from what I understand timing is very important to watch with anything crypto.
The other error is 'crypto' is not defined. I have the library imported on the workflow level. I don't know where else I might have to initialize crypto to be able to call on the library.