Skip to content

Instantly share code, notes, and snippets.

@gavinballard
Last active August 15, 2021 19:04
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save gavinballard/8513270 to your computer and use it in GitHub Desktop.
Save gavinballard/8513270 to your computer and use it in GitHub Desktop.
Python view decorator for the HMAC verification of a Shopify Webhook.
import hashlib, base64, hmac, json, settings
def shopify_webhook(f):
"""
A decorator thats checks and validates a Shopify Webhook request.
"""
def _hmac_is_valid(body, secret, hmac_to_verify):
hash = hmac.new(body, secret, hashlib.sha256)
hmac_calculated = base64.b64encode(hash.digest())
return hmac_calculated == hmac_to_verify
@wraps(f)
def wrapper(request, *args, **kwargs):
# Try to get required headers and decode the body of the request.
try:
webhook_topic = request.META['HTTP_X_SHOPIFY_TOPIC']
webhook_hmac = request.META['HTTP_X_SHOPIFY_HMAC_SHA256']
webhook_data = json.loads(request.body)
except:
return HttpResponseBadRequest()
# Verify the HMAC.
if not _hmac_is_valid(request.body, settings.SHOPIFY_API_SECRET, webhook_hmac):
return HttpResponseForbidden()
# Otherwise, set properties on the request object and return.
request.webhook_topic = webhook_topic
request.webhook_data = webhook_data
return f(request, args, kwargs)
return wrapper
@hironroy
Copy link

hironroy commented Apr 2, 2015

Thanks for the decorator. It's been really helpful. I did find one issue though. on line 9 hmac.new(body, secret, hashlib.sha256) should be hmac.new(secret, body, hashlib.sha256) instead. Other than that, everything worked as expected.

@danpalmer
Copy link

You could use Django's constant time string comparison on line 11 for added security.

@andresdouglas
Copy link

Is anyone else using this library seeing validation failures in the last few days? Seems like there might be a problem on Shopify's end? https://ecommerce.shopify.com/c/shopify-apis-and-technology/t/wrong-calculation-of-products-update-webhook-338062

@RiflerRick
Copy link

Thanks that helped wrt github webhooks

@silvainSayduck
Copy link

Thanks for the fix @hironroy, I was really getting annoyed when it didn't work before I read your comment :)
And of course, thanks @gavinballard for this great snippet, I can confirm that it still works today!

Another small adjustment though, it should be return f(request, *args, **kwargs) instead of return f(request, args, kwargs) on line 30

@AlexanderCollins
Copy link

You could also use the hmac method hmac.compare_digest on line 11; hmac.compare_digest(hmac_calculated, hmac_to_verify).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment