このページは機械翻訳です。英語版がソースであり、より正確または最新の場合があります。 英語で表示

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 リクエストに署名検証が含まれます。

仕組み:

  1. finlight は webhook 送信時にタイムスタンプを生成します
  2. 次のように連結してメッセージを作成します:timestamp + '.' + payload
  3. webhook のシークレットキーを使い、HMAC-SHA256 でメッセージに署名します
  4. 署名とタイムスタンプの両方をヘッダーで送信します

含まれるヘッダー:

X-Webhook-Signature: sha256=computed-signature
X-Webhook-Timestamp: 2024-01-15T10:30:00.000Z

署名アルゴリズム:

message = timestamp + '.' + raw_request_body
signature = HMAC-SHA256(message, webhook_secret)

X-Webhook-Timestamp ヘッダーが存在しない場合、メッセージは生のボディのみになります。結果は一定時間で比較し、タイムスタンプが 5 分より古い配信は拒否してください。

公式クライアントでの検証

すべてのクライアントライブラリには、チェック全体を代行するヘルパーが用意されています:署名の sha256= プレフィックスを受け入れ、一定時間で比較し、5 分のリプレイウィンドウを強制し、解析済みの記事を返します。検証に失敗した場合は例外をスローするかエラーを返します — 必ず 4xx で応答し、ペイロードは決して処理しないでください。

webhook を検証する

import express from 'express'
import { WebhookService } from 'finlight-client'

const app = express()

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const article = WebhookService.constructEvent(
      req.body.toString(),
      req.headers['x-webhook-signature'] as string,
      process.env.WEBHOOK_SECRET!,
      req.headers['x-webhook-timestamp'] as string,
    )

    console.log('New article:', article.title)
    res.sendStatus(200)
  } catch (err) {
    console.error('Webhook verification failed:', err)
    res.sendStatus(400)
  }
})

SECURITY必須ガイドライン

セキュリティのベストプラクティス

タイムスタンプの検証

上記の constructEvent ヘルパーはすでに 5 分のリプレイウィンドウを強制しているため、これが必要なのは署名を手動で検証する場合のみです:

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 テストガイドを確認してください。