署名の検証
署名を生成し、両者が一致するかどうかを確認することで検証リクエストの送信元が本物のSkyWayのWebhook機能であることを確かめることができます。
署名は、文字列化したボディと X-SkyWay-Request-Timestamp ヘッダーの値を連結したものに対して、署名用共通鍵を用いてHMAC-SHA256を計算することで生成できます。
またリプレイ攻撃を防止するために必要に応じてタイムスタンプを検証することも可能です。
例 (Node.js)
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifySignature(
signingSecret: string,
body: string,
timestamp: string
signature: string,
opts: { toleranceSeconds?: number }
): boolean {
// 1) タイムスタンプ検証(リプレイ防止)
const tsNum = Number(timestamp);
if (!Number.isFinite(tsNum)) return false;
const ageMs = Math.abs(Date.now() - tsNum * 1000);
if (opts.toleranceSeconds != null && ageMs > opts.toleranceSeconds * 1000) {
return false;
}
// 2) HMAC を計算
const payload = `${body}${String(timestamp)}`;
const expectedHex = createHmac("sha256", signingSecret).update(payload).digest("hex");
// 3) 比較
const expBuf = Buffer.from(expectedHex, "hex");
const recBuf = Buffer.from(receivedHex, "hex");
if (expBuf.length !== recBuf.length) return false;
return timingSafeEqual(expBuf, recBuf);
}重複排除について
同じイベントが重複して通知される可能性があるため、イベント通知の重複が許容できない場合は重複排除の仕組みをお客様側で実装する必要があります。
Webhook機能では、Webhookリクエストを一意に識別するための識別子として、次の3つの値の組み合わせを使用しています。
- appId
- type
- timestamp
完全な重複の排除を行いたい場合はイベントの識別子を3日間保存し、イベントの受信時に内容の比較を行って重複判断をしてください。