Mandatory webhook sends a GET instead of POST

Solved

Mandatory webhook sends a GET instead of POST

sergey-fiteo
Shopify Partner
4 1 2

Hey gang,

 

I set up the end point to handle mandatory webhooks.

 

However, my app gets rejected with: 

 

  1. 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. Learn more about securing mandatory GDPR webhooks

I do have the verification in place, but it works on custom webhooks (e.g. products/update).

 

I checked the logs on my web server and found this:

 

[2022-06-12 22:38:27 +0000] - (sanic.access)[INFO][103.161.250.10:16896]: GET <url> 405 789

 

I received it when i create a customer in my Dev store and then submitted a request for customer data.

 

I am puzzled as to why this is a GET request and not a POST.  According to the docs, mandatory webhooks are POST.

 

Here's one of the end points for the mandatory webhook + the verification method:

 

 

 

 

openapi.post("/webhook/shop/redact", strict_slashes=False)
@openapi.summary("Requests to delete shop data")
@openapi.body({"application/json":ShopRedact})
async def handle_shop_redact(request: request) -> response:
    # verify webhook
    verified = verify_webhook(request.body, request.headers.get('X-Shopify-Hmac-SHA256'))
    if not verified:
        raise SanicException(status_code=401)
    
    print("Received request to delete shop data: {} ", json.loads(request.body))
    return js(status=200, body={"message": "Request received"})

# following code is from Shopify's example: https://shopify.dev/apps/webhooks/configuration/https#verify-a-webhook
def verify_webhook(data, hmac_header):
    
    if hmac_header == None:
        return False

    API_SECRET_KEY = "7ae25d6aee942fbb2d2fef2d592a5eb9"
    digest = hmac.new(
        API_SECRET_KEY.encode("utf-8"), data, digestmod=hashlib.sha256
    ).digest()
    computed_hmac = base64.b64encode(digest)

    return hmac.compare_digest(computed_hmac, hmac_header.encode("utf-8"))

 

 

 

 

What am i doing wrong?  

Accepted Solution (1)

sergey-fiteo
Shopify Partner
4 1 2

This is an accepted solution.

it turns out that the mandatory webhook handling MUST be in the app itself.  The section in the Setup screen says to provide end points, but it doesn't clarify that they can't be end points outside of the app.  once i moved the handling of those mandatory webhooks to the app, using https://github.com/Shopify/shopify-node-api/issues/256 as guidance, everything worked. 

View solution in original post

Replies 2 (2)

sergey-fiteo
Shopify Partner
4 1 2

to clarify, i implemented the handling of mandatory webhooks outside of the app, in the external API.  but now i am thinking it needs to be done inside the app, just like a non-mandatory webhook such as product/updates.  is that the case?

sergey-fiteo
Shopify Partner
4 1 2

This is an accepted solution.

it turns out that the mandatory webhook handling MUST be in the app itself.  The section in the Setup screen says to provide end points, but it doesn't clarify that they can't be end points outside of the app.  once i moved the handling of those mandatory webhooks to the app, using https://github.com/Shopify/shopify-node-api/issues/256 as guidance, everything worked.