Verifying the signature
Check that every notice comes from Closeford.
Compute the HMAC-SHA256 of the timestamp and the raw body with your signing secret, and compare it with the X-Webhook-Signature header before accepting the notice.
import crypto from "node:crypto";
// raw = the request body as received (string), before JSON.parse
export function verify(raw, headers, secret) {
const ts = headers["x-webhook-timestamp"];
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(`${ts}.${raw}`)
.digest("hex");
const got = headers["x-webhook-signature"] ?? "";
return got.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}