Skip to content

Instantly share code, notes, and snippets.

@johnnyman727
Forked from alejoar/arcadia.py
Last active August 10, 2022 13:05
Show Gist options
  • Save johnnyman727/410892197f57f2bf99d499fc7e407369 to your computer and use it in GitHub Desktop.
Save johnnyman727/410892197f57f2bf99d499fc7e407369 to your computer and use it in GitHub Desktop.
Python Webhook signature validation for Arc
import hashlib
import hmac
import time
import starlette
WEBHOOK_SIGNING_KEY = "<YOUR_WEBHOOK_SIGNING_KEY>"
SECONDS_TO_STALE = 300 # 5 minutes
class ArcadiaSignatureException(Exception):
pass
async def validate_webhook_signature(req: starlette.requests.Request):
req_body = await req.body()
now_ts = time.time()
# 1. Extract the timestamp and signatures from the header
webhook_ts = int(req.headers.get("Arc-Webhook-Timestamp", 0))
webhook_signature = req.headers.get("Arc-Webhook-Signature", "")
if not webhook_ts or not webhook_signature:
raise ArcadiaSignatureException
# 2. Prepare the payload string by concatenating the timestamp with the body
payload_to_sign = f"{webhook_ts}.{req_body.decode()}"
# 3. Calculate the Signature using your Arcadia Webhook Secret
signature = hmac.new(
bytes(WEBHOOK_SIGNING_KEY, "utf-8"), msg=bytes(payload_to_sign, "utf-8"), digestmod=hashlib.sha256
).hexdigest()
# 4. If the timestamp is older than the threshold, this may be a replay attack
if abs(now_ts - webhook_ts) > SECONDS_TO_STALE:
raise ArcadiaSignatureException
# 5. If the signatures don't match, this may be a fraudulent webhook
# Be sure to use a constant time string comparison algorithm to prevent timing attacks
if not hmac.compare_digest(signature, webhook_signature):
raise ArcadiaSignatureException
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment