1. Svix公式ライブラリによる検証(推奨)
公式ライブラリを使うと、署名とタイムスタンプの検証を一括で行えます。- Python
- Node.js
- Java
- Kotlin
2. 自前での署名検証(Manual Verification)
ヘッダーとシークレットキーを用いて、受け取ったペイロードが正当なものかを自前で検証します。必要なもの
- HTTPヘッダー(
webhook-id,webhook-timestamp,webhook-signature)webhook-id: Webhookメッセージの一意な識別子。すべてのメッセージ間で一意だが、同じWebhookが再送信された場合(以前の送信が失敗した場合など)は同じ識別子が使用されるwebhook-timestamp: エポック(UNIX時間)からの経過秒数で表されたタイムスタンプwebhook-signature: Base64でエンコードされた署名のリスト(スペースで区切られた複数の署名を含む場合がある)
- Webhookシークレットキー(Frictio管理画面で発行)
- payload(リクエストボディ)
手順
1. 署名対象コンテンツの構築
署名に使用されるコンテンツは、id・timestamp・payloadをピリオド(.)で連結したものです。
body はリクエストの生(raw)ボディを指します。
署名は非常に敏感で、body がわずかにでも変更されると署名は完全に異なるものになります。
そのため、署名を検証する前に body を一切変更しないことが重要です。
2. 期待される署名の算出
Webhookの署名にはHMAC(ハッシュベースのメッセージ認証コード)とSHA-256を使用しています。 署名の検証を行うには、signedContent を、署名シークレットのBase64部分をキーとして使い、HMAC-SHA256で署名(ハッシュ)します。
署名シークレットが whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw の場合、実際の秘密鍵として使うのは whsec_ の後ろの部分(MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw)です。
webhook-signature ヘッダー内に含まれるいずれかの署名と一致している必要があります。
webhook-signature ヘッダーは、スペース区切りで並んだ複数の署名とそのバージョン識別子で構成されています。通常は1つだけですが、複数の署名が含まれる場合もあります。
v1,)と区切り文字を取り除いてください。
また、署名の比較にはタイミング攻撃(timing attack)を防ぐために、定数時間(constant-time)で文字列を比較する方法の使用が推奨されます。
タイムスタンプの検証
各リクエストの試行時刻をwebhook-timestamp ヘッダーに含めて送信します。
このタイムスタンプを自身のシステムの現在時刻と比較し、許容範囲内(過去5分以内)にあることを確認してください。
これはリプレイ攻撃(replay attack)を防ぐためです。
署名の検証例
以下は、実装が正しく行われているか確認するために使える検証用の例です。 なお、この例ではタイムスタンプが古いため、検証に失敗する可能性があることに注意してください。- 署名の照合:
v1,プレフィックスを取り除いた値と、計算した署名(computed_signature)を比較し、一致すればOKです - タイムスタンプの検証:
webhook-timestampが過去5分以内であるかを確認します