Verify webhook signatures

import { createHmac, timingSafeEqual } from "node:crypto";

function verifyWebhook(payload: string, signature: string, secret: string): boolean {
  const expected = createHmac("sha256", secret).update(payload).digest("hex");
  const left = Buffer.from(`sha256=${expected}`);
  const right = Buffer.from(signature ?? "");
  if (left.length !== right.length) return false;
  return timingSafeEqual(left, right);
}
Always verify the signature using the raw request body. If you parse JSON first, the signature check can fail.