Node.js Signature Verification
const crypto = require("crypto");
function timingSafeEqualString(a, b) {
const aBuf = Buffer.from(a, "utf8");
const bBuf = Buffer.from(b, "utf8");
if (aBuf.length !== bBuf.length) return false;
return crypto.timingSafeEqual(aBuf, bBuf);
}
function verifyPraetoSignature({ rawBody, headers, secret, toleranceSeconds = 300 }) {
const deliveryId = headers["praeto-delivery-id"];
const timestamp = headers["praeto-timestamp"];
const signatureHeader = headers["praeto-signature"];
if (!deliveryId || !timestamp || !signatureHeader) return false;
const timestampMs = Date.parse(timestamp);
if (!Number.isFinite(timestampMs)) return false;
const ageSeconds = Math.abs(Date.now() - timestampMs) / 1000;
if (ageSeconds > toleranceSeconds) return false;
const base = `${deliveryId}.${timestamp}.${rawBody}`;
const expected = "v1=" + crypto
.createHmac("sha256", secret)
.update(base, "utf8")
.digest("hex");
return signatureHeader
.split(",")
.map((part) => part.trim())
.some((candidate) => timingSafeEqualString(candidate, expected));
}