Files

19 lines
1.3 KiB
TypeScript

import assert from "node:assert/strict";
import { createHmac } from "node:crypto";
import { test } from "node:test";
import { standardWebhookMatches, webhookSecretHash, webhookSecretMatches } from "../lib/webhook";
test("verifies path secrets using a constant-time hash comparison", () => {
const secret = "path-secret"; assert.equal(webhookSecretMatches(secret, webhookSecretHash(secret)), true); assert.equal(webhookSecretMatches("wrong", webhookSecretHash(secret)), false); assert.equal(webhookSecretMatches(secret, null), false);
});
test("accepts only fresh v1 standard webhooks with an exact body signature", () => {
const secret = "signing-secret", id = "event-1", timestamp = String(Math.floor(Date.now() / 1000)), body = '{"type":"memo.updated"}';
const signature = createHmac("sha256", secret).update(`${id}.${timestamp}.${body}`).digest("base64");
assert.equal(standardWebhookMatches(secret, id, timestamp, `v1,${signature}`, body), true);
assert.equal(standardWebhookMatches(secret, id, timestamp, `v1,${signature}`, "{}"), false);
assert.equal(standardWebhookMatches(secret, id, "not-a-time", `v1,${signature}`, body), false);
assert.equal(standardWebhookMatches(secret, id, timestamp, `v2,${signature}`, body), false);
assert.equal(standardWebhookMatches(secret, id, String(Math.floor(Date.now() / 1000) - 301), `v1,${signature}`, body), false);
});