Topic: hmac
-
The Standard Webhooks spec versus Shopify's HMAC header and GitLab's shared-secret token
The Standard Webhooks specification defines webhook-id, webhook-timestamp and webhook-signature headers, a whsec_-prefixed base64 secret whose decoded bytes are the HMAC key, and a v1,<base64> signature over "{id}.{timestamp}.{payload}"; GitLab's signing tokens (GitLab 19.0, generally available in 19.1) implement exactly this. Shopify instead sends a base64 HMAC of the raw body in X-Shopify-Hmac-SHA256, and GitLab's older X-Gitlab-Token is a plain shared secret, not an HMAC at all.
-
Verifying Slack request signatures: X-Slack-Signature, the 5-minute replay window and the 3-second rule
Slack signs requests as v0=<hex HMAC-SHA256> of the string "v0:{timestamp}:{raw body}" in the X-Slack-Signature header, paired with X-Slack-Request-Timestamp, which Slack's own example rejects once it differs from local time by more than five minutes. Slash commands and interactive payloads must additionally be acknowledged within three seconds, before any slow processing.
-
Verifying Stripe webhook signatures: Stripe-Signature, timestamp tolerance and secret rotation
Stripe sends a Stripe-Signature header shaped like t=<timestamp>,v1=<hex signature>, computed as HMAC-SHA256 over the string "{timestamp}.{raw body}" keyed with the whole whsec_ endpoint secret. Stripe's libraries reject signatures whose timestamp is more than five minutes (300 seconds) old by default, and while a rolled secret is kept alive (up to 24 hours) the header carries one v1 value per active secret.
-
Verifying GitHub webhook signatures: X-Hub-Signature-256, timing-safe comparison and delivery IDs
GitHub signs every webhook delivery with HMAC-SHA256 over the raw request body and sends it as sha256=<hex digest> in the X-Hub-Signature-256 header. A receiver must recompute that digest from the exact bytes received, compare it with a constant-time function, and use X-GitHub-Delivery to recognise redelivered events; the older X-Hub-Signature (HMAC-SHA1) is kept only for compatibility.
-
The raw-body trap: why JSON body parsers break webhook signature verification
HMAC-based webhook signatures are computed over the exact bytes the provider sent; any JSON middleware that parses, reorders or re-serialises the body before your handler sees it changes those bytes and invalidates the signature. Express, FastAPI, Flask, Django and Go each need a specific way to capture the untouched body ahead of, or instead of, normal parsing.
Machine-readable: JSON