Webhook HMAC verification is widely implemented and widely misunderstood. It proves the payload was signed by someone with the app secret — not that the payload is fresh, not that it hasn't been seen before, and not that the app secret hasn't been compromised. Understanding what HMAC proves is as important as implementing it.
Key Analysis
HMAC-SHA256 verification establishes: this payload was signed with the correct app secret. It does NOT establish: this payload is recent, this payload hasn\'t been processed before, or the app secret hasn\'t been stolen.
Replay attacks use a valid, previously-signed payload to trigger actions again. Defence: timestamp validation (reject webhooks more than 5 minutes old) combined with deduplication (reject message IDs already processed).
Rate limiting is a security control, not just a performance control: a flood of webhook requests can exhaust processing capacity, triggering silent failures that an attacker can exploit.
Risk Signals
Webhook handlers that process any validly-signed payload regardless of timestamp.
No deduplication of webhook message IDs — making replay attacks trivially effective.
Webhook endpoint with no rate limiting — vulnerable to amplification attacks.
Action Items
Add timestamp validation alongside HMAC verification: reject webhooks with a timestamp more than 5 minutes old.
Combine deduplication (INSERT IGNORE on message ID) with HMAC verification for full replay protection.
Rate limit webhook endpoints at the Nginx layer, separate from application-level rate limiting.