HMAC-SHA256 signature of the body together with a timestamp, comparison with hmac.compare_digest (constant time), rejection if the timestamp is old (replay protection), idempotent processing using the event id, a fast 2xx response and processing in Celery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # ====================================================================== # Q: How do you secure webhooks (incoming and outgoing)? # # HMAC-SHA256 signature of the body together with a timestamp, comparison with # hmac.compare_digest (constant time), rejection if the timestamp is old (replay # protection), idempotent processing using the event id, a fast 2xx response and # processing in Celery. # ====================================================================== def verify(request, secret: bytes) -> bool: ts = request.headers['X-Timestamp'] if abs(time.time() - int(ts)) > 300: return False expected = hmac.new(secret, ts.encode() + b'.' + request.body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, request.headers['X-Signature']) |