Verify a webhook signature
Confirm a delivery really came from Fluveo before you trust it.
Every delivery is signed with HMAC-SHA256 and carries a Stripe-Signature header
(plus an equivalent Fluveo-Signature). Verify it against your endpoint’s
whsec_… secret before parsing the body, and always verify the raw body —
before any JSON parsing re-serializes a byte. SDKs are not supported, so do the
check yourself; it is a few lines in any language. For the full contract, replay
rules, and retry behaviour see Webhooks.
Steps
- Read the raw body as bytes, exactly as received.
- Parse the header.
Stripe-Signaturelooks liket=1769349712,v1=5257a8…. Split on,, then each part on the first=. Take thetvalue (a Unix timestamp) and everyv1value. Ignore other schemes. - Build the signed payload: the
tvalue, a., then the raw body —<t>.<raw body>. - Compute HMAC-SHA256 of the signed payload, keyed with the full endpoint
secret string (including the
whsec_prefix), and hex-encode it in lowercase. - Compare in constant time with each
v1value. Accept if any one matches. - Check the tolerance window. Reject when
tis more than 300 seconds away from your current time, so an old delivery cannot be replayed.
Reject with 400 on any failure, and only then parse the JSON.
Keep handlers idempotent (key on the event id); deliveries can repeat.