技術解説 · 出典付きの回答

Webhook署名の検証

Webhook署名の検証とは、受信側が届いたHTTPリクエストに付与された暗号署名を検証するセキュリティ上の処理です。これにより、ペイロードが信頼できるプロバイダーから送信されたもので、配送中に改変されていないことを確認できます。

定義

Webhook署名の検証は、Webhookイベントの送信元を認証するための仕組みです。ResendやSendGridなどのプロバイダーは、メールイベントの通知を送信する際、秘密鍵で署名したペイロードのハッシュを含めます。受信サーバーは同じ秘密鍵を使ってハッシュを再計算し、リクエストヘッダーで提供された署名と比較します。

処理の流れ

プロバイダーは、共有の秘密情報とリクエストボディを使ってHMACハッシュを生成します。このハッシュはヘッダーで送信され、ヘッダー名はX-Signatureなどであることが多いです。受信側は生のリクエストボディと署名ヘッダーを取得します。そして共有の秘密情報を使って自分でHMACハッシュを計算します。計算したハッシュがヘッダーの値と一致すれば、リクエストは本物です。一致しない場合、リクエストは不正なものとして拒否されます。

送信者にとっての重要性

検証を行わないと、WebhookのURLを知っている者なら誰でもサーバーに偽のデータを送信できます。その結果、配信済みのメールをバウンスとして記録するなど、データベースが誤って更新されるおそれがあります。検証を実装することでなりすまし攻撃を防ぎ、アプリケーションがメール基盤によって発生した正当なイベントにのみ反応するようにできます。

運用上の注意

よくある間違いは、署名を検証する前にリクエストボディをJSONオブジェクトに変換してしまうことです。JSONパーサーは空白やキーの順序を変えることがあるため、結果の文字列がプロバイダーの使った元のペイロードと一致しなくなる場合があります。検証の失敗を避けるため、HMACの計算には必ず解析前の生のリクエストボディを使ってください。

実装例

Node.js環境では、開発者はcryptoモジュールを使い、プロバイダーの秘密情報で生のボディのHMAC SHA-256ハッシュを作成します。この結果を、タイミング攻撃を防ぐための定数時間比較関数を使って署名ヘッダーと比較します。SendHQは https://sendhq.cc/tools で無料ツールを提供しており、Webhookの設定に先立って行うことの多い、さまざまなメール設定の管理に役立ちます。

よく寄せられる質問

秘密鍵が漏えいした場合はどうなりますか?

秘密鍵が漏えいすると、攻撃者は偽のリクエストに署名でき、サーバーはそれを有効なものとして受け入れてしまいます。すぐにプロバイダーのダッシュボードで秘密鍵をローテーションし、サーバーの環境変数を更新する必要があります。

HTTPSを使えば署名の検証は不要ですか?

いいえ。HTTPSは転送中のデータを暗号化し、サーバーの身元を検証しますが、リクエストを送信している特定のクライアントが許可されたメールプロバイダーであることまでは検証しません。

単純なAPIキーではなくHMACを使うのはなぜですか?

HMAC署名は、メッセージの内容が改ざんされていないことを証明します。ヘッダーに含めた固定のAPIキーで証明できるのは送信者がキーを知っていることだけで、ペイロードが改変されていないことまでは証明できません。

一次情報源