feat: add HMAC webhook signature verification utilities
This commit is contained in:
40
src/lib/signature.js
Normal file
40
src/lib/signature.js
Normal file
@@ -0,0 +1,40 @@
|
||||
"use strict";
|
||||
|
||||
const crypto = require("node:crypto");
|
||||
|
||||
function hmacSHA256Hex(payload, secret) {
|
||||
return crypto
|
||||
.createHmac("sha256", secret)
|
||||
.update(payload, "utf8")
|
||||
.digest("hex");
|
||||
}
|
||||
|
||||
function verifySignature({ payload, secret, signature }) {
|
||||
if (!secret) {
|
||||
throw new Error("webhook_secret_required");
|
||||
}
|
||||
|
||||
if (!signature) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const normalized = signature.startsWith("sha256=")
|
||||
? signature.slice("sha256=".length)
|
||||
: signature;
|
||||
|
||||
const expected = hmacSHA256Hex(payload, secret);
|
||||
|
||||
const expectedBuf = Buffer.from(expected, "hex");
|
||||
const givenBuf = Buffer.from(normalized, "hex");
|
||||
|
||||
if (expectedBuf.length !== givenBuf.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return crypto.timingSafeEqual(expectedBuf, givenBuf);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hmacSHA256Hex,
|
||||
verifySignature,
|
||||
};
|
||||
Reference in New Issue
Block a user