feat: LINEWORKS Webhook署名検証ロジックを追加

This commit is contained in:
Kenichiro NOGI 2026-09-05 14:37:44 +09:00
parent 20396f465d
commit 66f31d5dee
2 changed files with 51 additions and 0 deletions

View File

@ -0,0 +1,24 @@
const crypto = require("node:crypto");
function normalizeSignature(value) {
return String(value || "").trim().replace(/^sha256=/i, "");
}
function safeEqual(a, b) {
const ab = Buffer.from(String(a), "utf8");
const bb = Buffer.from(String(b), "utf8");
if (ab.length !== bb.length) return false;
return crypto.timingSafeEqual(ab, bb);
}
function verifySignature(rawBody, headerSignature, botSecret) {
const headerSig = normalizeSignature(headerSignature);
if (!headerSig || !botSecret) return false;
const payload = Buffer.isBuffer(rawBody) ? rawBody : Buffer.from(String(rawBody), "utf8");
const expected = crypto.createHmac("sha256", botSecret).update(payload).digest("base64");
return safeEqual(headerSig, expected);
}
module.exports = { verifySignature };

View File

@ -0,0 +1,27 @@
// test/signatureVerify.test.js
const { test } = require("node:test");
const assert = require("node:assert");
const crypto = require("node:crypto");
const { verifySignature } = require("../src/lib/signatureVerify");
test("正しい署名はtrueを返す", () => {
const secret = "test-secret";
const body = JSON.stringify({ hello: "world" });
const signature = crypto.createHmac("sha256", secret).update(body).digest("base64");
assert.strictEqual(verifySignature(body, signature, secret), true);
});
test("sha256=プレフィックス付き署名も検証できる", () => {
const secret = "test-secret";
const body = JSON.stringify({ hello: "world" });
const signature = crypto.createHmac("sha256", secret).update(body).digest("base64");
assert.strictEqual(verifySignature(body, `sha256=${signature}`, secret), true);
});
test("不正な署名はfalseを返す", () => {
assert.strictEqual(verifySignature("body", "invalid-signature", "secret"), false);
});
test("署名ヘッダーが空ならfalseを返す", () => {
assert.strictEqual(verifySignature("body", "", "secret"), false);
});