Signature
Webhook bodies are signed as timestamp plus request body with HMAC-SHA256. Receivers should reject old timestamps and mismatched signatures before acting on the payload.
- Verify against the raw request body.
- Reject stale timestamps before processing the event.
- Rotate secrets when receiver access changes.
import crypto from "node:crypto";
function verifyWebhook({ rawBody, timestamp, signature, secret }) {
const signed = `${timestamp}.${rawBody}`;
const expected = crypto.createHmac("sha256", secret).update(signed).digest("hex");
const actual = signature.replace(/^sha256=/, "");
return crypto.timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(actual, "hex"));
}