"""Verify a Fintray Extract webhook before trusting it. Fintray-Signature: t=,v1=." + raw body)> Use the raw request body, exactly as received — not re-serialized JSON. """ import hashlib import hmac import time def verify(secret: str, raw_body: bytes, signature_header: str, tolerance_seconds: int = 300) -> bool: try: parts = dict(item.split("=", 1) for item in signature_header.split(",")) timestamp = int(parts["t"]) except (ValueError, KeyError): return False if abs(time.time() - timestamp) > tolerance_seconds: return False # too old: a replay expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, parts.get("v1", "")) # Flask, for example: # # @app.post("/fintray/webhook") # def fintray_webhook(): # if not verify(os.environ["FINTRAY_WHSEC"], request.get_data(), request.headers["Fintray-Signature"]): # abort(400) # event = request.get_json() # fetch_and_store(event["data"]["id"]) # GET /v1/documents/{id} with your key # return "", 204