Solved

HTTP POST for redact-shop-data webhook failing HMAC validation?

few_meaning
Shopify Partner
20 3 2

During app review I received the feedback:

App must verify the authenticity of the request from Shopify.
Your app's HTTPS webhook endpoints must validate the HMAC digest of each request, and return an HTTP 401 (Unauthorized) response when rejecting a request that has an invalid digest.

I am now observing HTTP POSTs to my redact-shop-data endpoint that contain no query string and are failing HMAC validation because they contain no HMAC query parameter. Is this expected/some kind of testing? I want to make sure I'm not missing GDPR-sensitive requests due to a bug/confusion.

Accepted Solution (1)

few_meaning
Shopify Partner
20 3 2

This is an accepted solution.

I've logged some of these requests and they appear to be valid, as far as I can tell. It looks like the HMAC is present as a header value rather than a query parameter.

 

The Shopify article that one follows during the "build a Shopify app tutorial", https://shopify.dev/apps/auth/oauth#verification, says:

For each request, you must remove the hmac entry from the query string and process it through an HMAC-SHA256 hash function.

Turns out that elsewhere, https://shopify.dev/apps/webhooks/configuration/https#verify-a-webhook says:

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.

Sigh. So it's exactly as I feared, I've been explicitly 401-ing valid GDPR webhook requests. This feels like it should be more obvious and would be helped significantly if it could be tested.

View solution in original post

Replies 6 (6)

few_meaning
Shopify Partner
20 3 2

This is an accepted solution.

I've logged some of these requests and they appear to be valid, as far as I can tell. It looks like the HMAC is present as a header value rather than a query parameter.

 

The Shopify article that one follows during the "build a Shopify app tutorial", https://shopify.dev/apps/auth/oauth#verification, says:

For each request, you must remove the hmac entry from the query string and process it through an HMAC-SHA256 hash function.

Turns out that elsewhere, https://shopify.dev/apps/webhooks/configuration/https#verify-a-webhook says:

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.

Sigh. So it's exactly as I feared, I've been explicitly 401-ing valid GDPR webhook requests. This feels like it should be more obvious and would be helped significantly if it could be tested.

fpierrat
Shopify Partner
5 0 0

Regarding the fetch_stock.json webhook, following doc is very-very-very approximative: https://shopify.dev/apps/webhooks/configuration/https#verify-a-webhook

- the sample code relies on the request body (php://input) to be HMAC-ed, but there's no request body, it's not even a post request (php://input is simply empty).

- you should instead use the get parameters (sort them alphabetically then http_build_query() them worked for me)

- it could be nice too, if this doc called the key with the same name as the admin interface page where the keys are available (you have an "admin API access token", an "API key" and an "API secret key" in the page, whereas the doc mentions a "client secret").

Hoping this little comment could spare to someone the hours I lost on this...

Anglia
Tourist
5 0 2

We also encounter such problems. Have you solved them? How to solve this problem?

few_meaning
Shopify Partner
20 3 2

If you encounter this problem it's likely you're not correctly validating the HMAC.

 

So for webhooks, there's a header that contains the HMAC value and for all other requests it's a query parameter that must be stripped before validating.

Ginky
Visitor
3 0 0

Nerver can help me

Ginky
Visitor
3 0 0
Nerver can help