Skip to content

認証ミドルウェアの設計 ― 「チェックする」の深さ

📖この章のキーワード
用語意味なぜ重要か
多層防御(Defense in Depth)複数のチェック層でセキュリティを確保する設計1つの層が突破されても次の層で防ぐ
401 Unauthorized認証の失敗(あなたが誰か分からない)ヘッダーなし、署名不正 等
403 Forbidden権限の不足(誰かは分かったが許可されていない)IP不許可、スコープ不足 等
429 Too Many Requestsレート制限超過秒間・月間の呼び出し上限に達した
スコープAPI キーに付与された操作権限の範囲エンドポイントごとに必要な権限が異なる

Phase 1: 観察

exemplar 認証境界の多層設計を学ぶための主教材です。

LIBOT の Partner API 認証ミドルウェアを改めて見てみましょう。

php
// PartnerApiAuth.php (excerpt)
// Label: exemplar

public function handle(Request $request, Closure $next, string ...$requiredScopes): Response
{
    // 1. 必須ヘッダーの確認
    if (!$this->signatureService->hasRequiredHeaders($request)) {
        return $this->errorResponse('missing_auth_headers', '...', 401);
    }

    // 2. クレデンシャルの検索と有効性チェック
    $credential = PartnerApiCredential::where('key_id', $keyId)->first();
    if (!$credential || !$credential->isUsable()) {
        return $this->errorResponse('invalid_credentials', '...', 401);
    }

    // 3. インテグレーションの有効性チェック
    if (!$credential->integration || !$credential->integration->isActive()) {
        return $this->errorResponse('integration_inactive', '...', 403);
    }

    // 4. IP アドレスチェック
    if (!$credential->isIpAllowed($request->ip())) {
        return $this->errorResponse('ip_not_allowed', '...', 403);
    }

    // 5. HMAC 署名検証
    if (!$this->signatureService->verify($request, $credential)) {
        return $this->errorResponse('invalid_signature', '...', 401);
    }

    // 6. スコープチェック
    if (!empty($requiredScopes) && !$credential->hasAnyScope($requiredScopes)) {
        return $this->errorResponse('insufficient_scope', '...', 403);
    }

    // 7. レート制限(秒間 + 月間クォータ)
    $rateLimitResponse = $this->checkPerSecondRateLimit(...);
    if ($rateLimitResponse) return $rateLimitResponse;    // 429

    return $next($request);
}

7 つのチェックポイント、3 種類の HTTP ステータスコード。


Phase 2: 判断

AI禁止ゾーン

AI に「API 認証ミドルウェアを書いて」と頼むと、こんなコードが返ってきました。

php
public function handle(Request $request, Closure $next)
{
    $apiKey = $request->header('X-API-Key');

    if (!$apiKey || $apiKey !== config('services.api.key')) {
        return response()->json(['error' => 'Unauthorized'], 401);
    }

    return $next($request);
}
  • この AI 生成コードと LIBOT の実装の 違い を全て挙げてください
  • AI 生成コードを 本番で使うリスク は何ですか?
  • LIBOT の実装は なぜこの順序 でチェックしているのでしょうか?

AIに聞く前に、自分の頭で考えてみましょう。

テキストを入力すると有効になります