Skip to content

Webhook Signature Verification

Securing inbound webhooks is critical to prevent attackers from spoofing events.

The Mechanic

We use HMAC-SHA256. The sender (e.g. Stripe) includes a header Stripe-Signature containing a timestamp and a signature. We calculate the expected signature using a shared secret and compare.

Configuration

In settings.py:

DJANGO_AUTOMATE = {
    # ...
    "WEBHOOKS": {
        "stripe": {
            "secret": "whsec_...",
            "header": "Stripe-Signature",
            "algorithm": "hmac-sha256",
        }
    }
}

How it works internally

The WebhookIngestor view: 1. Looks up the secret for the source. 2. Computes hmac.new(secret, payload, sha256). 3. Compares with the header. 4. Rejects with 401 Unauthorized if mismatch.

Best Practices

  • Rotation: Support multiple secrets (list) during rotation.
  • Timestamp: Verify the timestamp is within tolerance (e.g. 5 mins) to prevent replay attacks.