Webhook 認証 - エンドポイントを保護する
finlight は、webhook の配信を保護するために複数の認証方法を提供します。各 webhook には既定で署名検証が含まれ、セキュリティを強化するための追加認証レイヤーをオプションで利用できます。
finlight は、単独または組み合わせて使用できる 4 つの認証方法をサポートします:
なし追加認証なし
なし
既定の署名検証以外に追加の認証はありません。
使用するタイミング:
- テストおよび開発環境
- 安全なネットワーク内部のエンドポイント
- 署名検証で十分なセキュリティが得られる場合
注: この設定に関係なく、署名検証はすべての webhook リクエストに引き続き含まれます。
FINLIGHT_KEYカスタムヘッダー
X-Finlight-Key ヘッダー
各 webhook リクエストで、カスタムの X-Finlight-Key ヘッダーに API キーを送信します。
構成:
- webhook の設定時に API キーを指定します
- そのキーは
X-Finlight-Keyヘッダーに含まれます
実装: エンドポイントは、受信したヘッダーを検証する必要があります:
const finlightKey = req.headers['x-finlight-key']
if (finlightKey !== 'your-expected-api-key') {
return res.status(401).send('Invalid API key')
}
送信されるヘッダー:
X-Finlight-Key: your-api-key-value
X-Webhook-Signature: sha256=signature
X-Webhook-Timestamp: 2024-01-15T10:30:00.000Z
BASICユーザー名/パスワード
ベーシック認証
ユーザー名/パスワードの資格情報による HTTP ベーシック認証。
構成:
- webhook の設定時にユーザー名とパスワードを設定します
- 資格情報は base64 エンコードされ、
Authorizationヘッダーで送信されます
実装: エンドポイントは標準の HTTP ベーシック認証を受け取ります:
const auth = req.headers.authorization
if (!auth || !auth.startsWith('Basic ')) {
return res.status(401).send('Missing Basic Auth')
}
const credentials = Buffer.from(auth.slice(6), 'base64').toString()
const [username, password] = credentials.split(':')
if (username !== 'expected-user' || password !== 'expected-pass') {
return res.status(401).send('Invalid credentials')
}
送信されるヘッダー:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
X-Webhook-Signature: sha256=signature
X-Webhook-Timestamp: 2024-01-15T10:30:00.000Z
SIGNATURE常に含まれる
署名検証
自動セキュリティ: 選択した認証方法に関係なく、すべての webhook リクエストに署名検証が含まれます。
仕組み:
- finlight は webhook 送信時にタイムスタンプを生成します
- 次のように連結してメッセージを作成します:
timestamp + '.' + payload - webhook のシークレットキーを使い、HMAC-SHA256 でメッセージに署名します
- 署名とタイムスタンプの両方をヘッダーで送信します
含まれるヘッダー:
X-Webhook-Signature: sha256=computed-signature
X-Webhook-Timestamp: 2024-01-15T10:30:00.000Z
署名アルゴリズム:
message = timestamp + '.' + JSON.stringify(payload)
signature = HMAC-SHA256(message, webhook_secret)
SECURITY必須ガイドライン
セキュリティのベストプラクティス
タイムスタンプの検証
リクエストのタイムスタンプを検証して、リプレイ攻撃を防ぎます:
function isTimestampValid(timestamp, toleranceSeconds = 300) {
const now = Date.now()
const requestTime = new Date(timestamp).getTime()
const difference = Math.abs(now - requestTime) / 1000
return difference <= toleranceSeconds
}
資格情報の安全な保管
- 環境変数: すべてのシークレットを環境変数に保管します
- シークレット管理: AWS Secrets Manager、HashiCorp Vault などを使用します
- ハードコードしない: シークレットをバージョン管理にコミットしないでください
- 定期的なローテーション: webhook のシークレットを定期的に更新します
webhook 設定のガイダンスについては、webhook のメインドキュメントを参照してください。包括的なテストについては、webhook テストガイドを確認してください。