api
authentication
ai_generated
true
Webhook signature verification fails despite correct secret key
ID: api/webhook-hmac-raw-body-mismatch
92%Fix Rate
90%Confidence
3Evidence
2023-01-01First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| any | active | — | — | — |
Root Cause
Webhook HMAC signatures are computed over raw request body bytes. JSON.stringify(parsed) != original bytes due to key ordering, whitespace, and Unicode escaping differences.
genericWorkarounds
-
95% success Capture raw body before JSON parsing in Express
app.use('/webhook', express.raw({type: 'application/json'})); // req.body is Buffer -
92% success In Flask, use request.get_data() not request.json
raw_body = request.get_data(); sig = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
-
90% success Use timing-safe comparison for HMAC verification
crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(received))
Dead Ends
Common approaches that don't work:
-
Compute HMAC over JSON.stringify(req.body)
95% fail
JSON.stringify produces different bytes than the original payload. Signature will never match.
-
Use bodyParser.json() before webhook route in Express
90% fail
bodyParser consumes the raw body stream. The original bytes are gone by handler time.