Webhook は『受け取り側』の設計が9割
Stripe / GitHub / Slack 等の SaaS は Webhook で外部システムにイベントを通知します。本記事では編集部の視点で、Webhook 受信側が押さえるべき設計を公開情報をもとに整理します。キューシステム設計 もご参考に。
署名検証は必須
(1) HMAC-SHA256:本文+secretで署名を生成。(2) X-Hub-Signature 等のヘッダから検証。(3) タイミングセーフな比較:crypto.timingSafeEqual を使う。(4) raw body を保持:JSONパース前のバイト列で検証。(5) 失敗時は 401 を返す:処理に進めない。Webhook URL が漏洩しても、署名検証で攻撃を防げます。
冪等性の担保
(1) event_id を保持:処理済みなら 200 で即返却。(2) DBの UNIQUE 制約:二重実行を弾く。(3) Redis SETNX:短期間の重複対策。(4) 処理タイムアウト:再送される前提で考える。(5) at-least-once 前提:少なくとも1回は届く。イベント駆動アーキテクチャ も合わせて。
再送と DLQ
(1) 非2xx を返すと再送:仕様を確認。(2) 指数バックオフ:1分→5分→1時間→1日。(3) DLQ で隔離:再送失敗を退避。(4) DLQ の監視:件数アラート必須。(5) 手動再投入:Adminツールで処理可能に。
レスポンス時間を短く
(1) 5秒以内に200を返す:多くのSaaSが要求。(2) キューに投入して即返却:重い処理は非同期。(3) 受信→キュー→ワーカーの3段構成。(4) Cold start の影響:サーバーレスは要注意。(5) ロードバランサのタイムアウトも確認。
セキュリティ追加対策
(1) 送信元 IP の許可リスト:可能なら設定。(2) HTTPS 強制:HTTP は禁止。(3) timestamp の検証:再送攻撃対策(5分以内など)。(4) secret のローテーション:定期的に更新。(5) ペイロード上限:DoS 対策で MaxBodySize を設定。認証・認可実践 も合わせて。
失敗しがちなパターン
(1) 署名検証なし:偽イベントで業務処理が走る。(2) 処理が長く5秒オーバー:再送ループに陥る。(3) 冪等性なし:同じ処理が2回走る。(4) raw body を捨てる:署名検証不能に。(5) 失敗時にエラー詳細を返す:情報漏洩。対策は、(1)署名検証必須、(2)即200+非同期処理、(3)event_id 一意化、(4)生バイト保持、(5)エラーは汎用化、です。