API Gateway × Cognito × IAM認証 完全ガイド 2025年版 - サーバーレス認可の最新実装パターン

API Gateway × Cognito × IAM認証 完全ガイド 2025年版 - サーバーレス認可の最新実装パターン

最終更新日:2025年08月29日公開日:2025年08月29日
益子 竜与志
writer:益子 竜与志
XThreads

API Gatewayを使った認証・認可の実装、皆さんはどのような方式を採用していますか? 2025年現在でも、Cognito User PoolとIdentity Poolを組み合わせたIAM認証パターンは、その堅牢性と柔軟性から多くのプロジェクトで採用される王道のアプローチです。

本記事では、2025年の最新AWS仕様に基づき、コードを一切書かずにサーバーレスなAPI認可を実現する方法と、新たに成熟したHTTP APIを含む選択肢について、実装経験から得た知見を交えて解説します。

API Gateway × Cognito × IAM認証 完全ガイド 2025年版

なぜ今でもこのパターンが有効なのか

AWS のAPI実装において、認証・認可の設計は最も重要な検討事項の一つです。2025年1月現在、AWSの公式ドキュメントでも明記されているように、Cognito User Poolで認証し、Identity PoolでSTS資格情報を取得してAPI GatewayをIAM認可で呼び出すパターンは、依然として推奨される実装方式として健在です。

このアプローチが長年支持される理由は、その「本質的な価値」にあります。単一の認証情報で複数のAWSサービス(S3、DynamoDB、API Gateway等)へアクセスできる統一性と、IAMロールによる細かい権限制御の組み合わせは、エンタープライズレベルのセキュリティ要件を満たすうえで極めて有効です。

2025年における選択肢の整理

REST API vs HTTP API - 適材適所の選択

現在のAPI Gateway実装では、大きく分けて2つの選択肢があります。それぞれの特徴を理解し、要件に応じて選択することが重要です。

REST API + IAM認証(本記事のメインパターン)

REST APIとIAM認証の組み合わせは、AWSリソース全体で統一されたセキュリティモデルを実現したい場合に最適です。特に、API Gatewayのリソースポリシーを活用できる点は大きなメリットです。特定のIPアドレスやVPCエンドポイントからのアクセスのみを許可するなど、多層防御を実現できます。

HTTP API + JWTオーソライザー

HTTP APIのJWTオーソライザーは、よりシンプルなAPIセキュリティを求める場合に適しています。Cognito User PoolのトークンやOIDCプロバイダーのJWTを直接検証でき、スコープベースのアクセス制御が簡潔に実装できます。新規プロダクトで純粋なAPIクライアント間通信を想定している場合、こちらを第一候補として検討する価値があります。

認証フローの最新アップデート

Cognitoのマネージドログインが整備され、従来のHosted UIから進化しました。特に注目すべきは、2024年に発表されたパスキーサポートです。FIDO2準拠のパスキーによるパスワードレス認証が可能になり、ユーザビリティとセキュリティの両立が実現できるようになりました。

ただし、パスキー機能の利用にはCognito Liteプラン以上が必要である点には注意が必要です。プロジェクトの予算とセキュリティ要件のバランスを考慮した選択が求められます。

実装アーキテクチャの詳細解説

全体的なワークフロー

Cognito User PoolとIdentity Poolを組み合わせたAWSサービスアクセスの全体像

実装するワークフローは以下の3ステップから構成されます。

  1. Cognito User Poolで認証トークン(IDトークン)を取得
  2. Cognito Identity PoolにIDトークンを渡し、STS一時認証情報を取得
  3. STS認証情報を使用してSigV4署名を生成し、API Gatewayへリクエスト

このフローの中核にあるのは「IAMロール」です。各ユーザーが適切な権限を持つIAMロールの認証情報を取得することで、きめ細かいアクセス制御を実現します。

IAMロールの設計と実装

IAMロールの設計は、このアーキテクチャの要となる部分です。2025年現在もAWSのベストプラクティスに従い、最小権限の原則を徹底することが重要です。

以下は管理者向けと従業員向けのIAMロール定義例です。

# 管理者向けロール
AuthenticatedAdminRole:
  Type: AWS::IAM::Role
  Properties:
    RoleName: "example-cognito-apigateway-AuthenticatedAdminRole"
    AssumeRolePolicyDocument:
      Version: "2012-10-17"
      Statement:
        - Action: sts:AssumeRoleWithWebIdentity
          Effect: Allow
          Principal:
            Federated: cognito-identity.amazonaws.com
          Condition:
            StringEquals:
              cognito-identity.amazonaws.com:aud: !Ref CognitoIDPool
            ForAnyValue:StringLike:
              cognito-identity.amazonaws.com:amr: authenticated
    Policies:
      - PolicyName: "admin-api-access-policy"
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Sid: APIGatewayAdminAccess
              Effect: Allow
              Action:
                - execute-api:Invoke
              Resource:
                - !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/${Stage}/GET/admin/*
                - !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/${Stage}/POST/admin/*
                - !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/${Stage}/PUT/admin/*
                - !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/${Stage}/DELETE/admin/*

# 従業員向けロール
AuthenticatedStaffRole:
  Type: AWS::IAM::Role
  Properties:
    RoleName: "example-cognito-apigateway-AuthenticatedStaffRole"
    AssumeRolePolicyDocument:
      Version: "2012-10-17"
      Statement:
        - Action: sts:AssumeRoleWithWebIdentity
          Effect: Allow
          Principal:
            Federated: cognito-identity.amazonaws.com
          Condition:
            StringEquals:
              cognito-identity.amazonaws.com:aud: !Ref CognitoIDPool
            ForAnyValue:StringLike:
              cognito-identity.amazonaws.com:amr: authenticated
    Policies:
      - PolicyName: "staff-api-access-policy"
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Sid: APIGatewayStaffAccess
              Effect: Allow
              Action:
                - execute-api:Invoke
              Resource:
                - !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/${Stage}/GET/staff/*

注目すべき点は、信頼ポリシー(AssumeRolePolicyDocument)の条件設定です。cognito-identity.amazonaws.com:audでIdentity Pool IDを指定し、cognito-identity.amazonaws.com:amrで認証済みユーザーのみを許可しています。これはAWSの公式ドキュメントでも推奨される設定パターンです。

Cognito User Poolグループの活用

Cognito User Poolのグループ機能は、ユーザーとIAMロールのマッピングを実現する重要な要素です。各グループにIAMロールを紐付けることで、認証トークンにcognito:rolescognito:preferred_roleのクレームが含まれるようになります。

UserPoolAdministratorGroup:
  Type: AWS::Cognito::UserPoolGroup
  Properties:
    Description: "管理者グループ"
    GroupName: Admin
    Precedence: 1
    UserPoolId: !Ref CognitoUserPool
    RoleArn: !GetAtt AuthenticatedAdminRole.Arn

UserPoolStaffGroup:
  Type: AWS::Cognito::UserPoolGroup
  Properties:
    Description: "従業員グループ"
    GroupName: Staff
    Precedence: 2
    UserPoolId: !Ref CognitoUserPool
    RoleArn: !GetAtt AuthenticatedStaffRole.Arn

Precedenceの値は、ユーザーが複数のグループに所属している場合の優先順位を決定します。値が小さいほど優先度が高く、cognito:preferred_roleとして選択されます。

Identity PoolのRoleMappings設定の重要性

Identity Poolの設定で最も重要なのは、RoleMappingsのType設定です。Type: Tokenを指定することで、IDトークンに含まれるcognito:rolescognito:preferred_roleクレームを自動的に解釈し、適切なIAMロールを選択します。

IdentityPoolRoleAttachment:
  Type: AWS::Cognito::IdentityPoolRoleAttachment
  Properties:
    IdentityPoolId: !Ref CognitoIDPool
    Roles:
      "authenticated": !GetAtt CognitoIdentityPoolAuthenticatedRole.Arn
    RoleMappings:
      CognitoUserPool:
        AmbiguousRoleResolution: AuthenticatedRole
        IdentityProvider: !Sub cognito-idp.${AWS::Region}.amazonaws.com/${CognitoUserPool}:${CognitoUserPoolClient}
        Type: Token  # ここが重要!

Type: Tokenの設定により、完全にサーバーレスな環境でユーザーグループに基づいたIAMロールの自動割り当てが実現できます。これは、Lambda関数などでカスタムロジックを実装することなく、AWS管理のサービスのみで認可を実現できる優れたアプローチです。

API Gatewayのセキュリティ強化

リソースポリシーによる多層防御

REST APIの大きな利点の一つは、リソースポリシーを設定できることです。IAM認証と組み合わせることで、多層防御を実現できます。

ApiGatewayResourcePolicy:
  Type: AWS::ApiGateway::RestApi
  Properties:
    Policy:
      Version: '2012-10-17'
      Statement:
        - Effect: Allow
          Principal: '*'
          Action: 'execute-api:Invoke'
          Resource: 'execute-api:/*'
          Condition:
            IpAddress:
              aws:SourceIp:
                - '10.0.0.0/8'  # 社内ネットワーク
                - '172.16.0.0/12'  # VPC内部
        - Effect: Deny
          Principal: '*'
          Action: 'execute-api:Invoke'
          Resource: 'execute-api:/*'
          Condition:
            IpAddress:
              aws:SourceIp:
                - '192.168.1.100'  # 特定のブロックIP

リソースポリシーは、IAM認証の前段階で適用されるため、不正なアクセスを早期に遮断できます。ただし、HTTP APIではリソースポリシーがサポートされていないため、この機能が必要な場合はREST APIを選択する必要があります。

TLS 1.3によるセキュリティ強化

2024年2月にAPI GatewayがTLS 1.3をサポートしたことで、より高速で安全な通信が可能になりました。既存のAPIでもTLS 1.3を有効にすることで、セキュリティとパフォーマンスの両面で改善が期待できます。

Lambda統合時の実装上の注意点

IAM認証時のコンテキスト情報

IAM認証を使用した場合、Lambda関数で取得できる情報には制限があります。公式ドキュメントによると、JWTトークンの内容は直接取得できませんが、$context.identity変数を通じて以下の情報にアクセスできます。

interface APIGatewayRequestContext {
  identity: {
    cognitoIdentityPoolId: string;
    accountId: string;
    cognitoIdentityId: string;
    caller: string;
    sourceIp: string;
    principalOrgId: string;
    accessKey: string;
    cognitoAuthenticationType: "authenticated";
    cognitoAuthenticationProvider: string; // ここにUser PoolのsubIDが含まれる
    userArn: string;
    userAgent: string;
    user: string;
  };
}

特に重要なのはcognitoAuthenticationProviderフィールドです。このフィールドにはcognito-idp.{region}.amazonaws.com/{userPoolId}:CognitoSignIn:{sub}という形式で情報が格納され、ユーザーのsubIDを取得できます。

// Lambda関数でのユーザー特定例
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
  const authProvider = event.requestContext.identity?.cognitoAuthenticationProvider;

  if (authProvider) {
    // cognitoAuthenticationProviderからsubを抽出
    const subMatch = authProvider.match(/:CognitoSignIn:(.+)$/);
    const userSub = subMatch ? subMatch[1] : null;

    if (userSub) {
      // userSubを使用してユーザー固有の処理を実行
      console.log(`User Sub: ${userSub}`);
    }
  }

  return {
    statusCode: 200,
    body: JSON.stringify({ message: "Success" })
  };
};

ユーザー属性が必要な場合の対処法

IAM認証では詳細なユーザー属性(メールアドレス、カスタム属性など)を取得できないため、これらの情報が必要な場合は以下の選択肢を検討する必要があります。

以下の方法でユーザー属性を取得できます。

  • Lambda内でCognito User PoolのAdminGetUserAPIを呼び出す
  • DynamoDBなどの外部データストアにユーザー情報をキャッシュする
  • HTTP API + JWTオーソライザーに切り替える(JWTトークンから直接属性を取得可能)

実装時のベストプラクティス

最小権限の原則の徹底

IAMポリシーのResource指定では、ワイルドカードの使用を最小限に抑えることが重要です。以下は推奨される段階的なアプローチです。

# BAD: 過度に広範な権限
Resource:
  - !Sub arn:aws:execute-api:*:*:*/*/*

# BETTER: API IDとステージを特定
Resource:
  - !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/${Stage}/*

# BEST: メソッドとパスも特定
Resource:
  - !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/${Stage}/GET/admin/users
  - !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/${Stage}/POST/admin/users

Identity Poolロールの適切な設定

Identity Pool用のロールには、必要最小限の権限のみを付与します。よくある誤りは、cognito-identity:*のような広範な権限を付与してしまうことです。

# 推奨される最小権限の設定
CognitoIdentityPoolAuthenticatedRole:
  Type: AWS::IAM::Role
  Properties:
    Policies:
      - PolicyName: "minimal-cognito-access"
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Sid: MinimalCognitoAccess
              Effect: Allow
              Action:
                - cognito-identity:GetCredentialsForIdentity
                - cognito-identity:GetId
              Resource: !Sub arn:aws:cognito-identity:${AWS::Region}:${AWS::AccountId}:identitypool/${CognitoIDPool}

エラーハンドリングとモニタリング

API Gatewayの認証エラーは、適切にログ記録し、モニタリングすることが重要です。CloudWatch Logsと連携し、認証失敗パターンを分析できるようにしましょう。

ApiGatewayLogGroup:
  Type: AWS::Logs::LogGroup
  Properties:
    LogGroupName: !Sub /aws/apigateway/${ApiGatewayRestApi}
    RetentionInDays: 30

ApiGatewayAccountConfig:
  Type: AWS::ApiGateway::Account
  Properties:
    CloudWatchRoleArn: !GetAtt ApiGatewayCloudWatchRole.Arn

ApiGatewayDeployment:
  Type: AWS::ApiGateway::Deployment
  Properties:
    RestApiId: !Ref ApiGatewayRestApi
    StageName: !Ref Stage
    StageDescription:
      AccessLogSetting:
        DestinationArn: !GetAtt ApiGatewayLogGroup.Arn
        Format: '$context.requestId $context.identity.sourceIp $context.identity.userArn $context.requestTime $context.httpMethod $context.routeKey $context.status $context.error.message $context.error.messageString'
      MethodSettings:
        - ResourcePath: '/*'
          HttpMethod: '*'
          LoggingLevel: INFO
          DataTraceEnabled: true
          MetricsEnabled: true

2025年における選択判断フロー

プロジェクトに最適な認証方式を選択するため、以下の判断基準を参考にしてください。

REST API + IAM認証を選ぶべきケース

以下の要件がある場合は、REST API + IAM認証が適しています。

  • AWS内の複数サービス(S3、DynamoDB等)で統一された認証を使いたい
  • リソースポリシーによるIP制限やVPCエンドポイント制限が必要
  • 既存のAWSインフラと密接に統合したい
  • 細かいIAMロールベースの権限管理が必要

HTTP API + JWTオーソライザーを選ぶべきケース

以下の要件がある場合は、HTTP API + JWTオーソライザーが適しています。

  • シンプルなスコープベースの認可で十分
  • レイテンシを最小化したい(HTTP APIは一般的に高速)
  • コスト最適化を重視(HTTP APIは料金が安い)
  • 外部のOIDCプロバイダーと連携したい

ハイブリッドアプローチの検討

実際のプロジェクトでは、両方のアプローチを組み合わせることも有効です。例えば、パブリックAPIはHTTP API + JWTオーソライザーで実装し、管理APIはREST API + IAM認証で実装するという使い分けが考えられます。

トラブルシューティングガイド

よくある実装ミス

実装時によく遭遇する問題と、その解決方法をまとめました。

RoleMappingsのType設定ミス

Type: TokenType: Rulesと間違えると、グループベースのロール自動割り当てが機能しません。必ずType: Tokenを指定し、AmbiguousRoleResolutionも適切に設定してください。

信頼ポリシーの条件設定漏れ

IAMロールの信頼ポリシーで、Identity Pool IDの条件チェックを忘れると、セキュリティホールになる可能性があります。必ずcognito-identity.amazonaws.com:audでIdentity Pool IDを検証してください。

API実行権限のResource指定ミス

execute-api:InvokeのResourceで、ステージやメソッドの指定を間違えると、403エラーが発生します。ARN形式を正確に記述することが重要です。

デバッグ手法

問題の切り分けには、以下のアプローチが有効です。

  1. CloudWatch Logsで認証フローの各段階をトレース
  2. AWS CLIでSTS AssumeRoleWithWebIdentityを直接実行して検証
  3. API GatewayのテストコンソールでIAM認証をシミュレート

まとめと今後の展望

2025年現在でも、Cognito User Pool、Identity Pool、IAM認証を組み合わせたAPI Gatewayの認証パターンは、その堅牢性と柔軟性から有効な選択肢です。特に、AWSエコシステム全体で統一されたセキュリティモデルを構築したい場合には、このアプローチが最適解となることが多いでしょう。

一方で、HTTP API + JWTオーソライザーという新しい選択肢も成熟し、よりシンプルなユースケースでは第一選択となる場合も増えています。プロジェクトの要件を正確に把握し、適切な技術選択を行うことが、成功への鍵となります。

今後は、パスキー認証やマネージドログインのさらなる進化により、よりユーザーフレンドリーかつセキュアな認証体験が実現されることが期待されます。技術の進化を見据えながら、現時点でのベストプラクティスを実装していくことが、持続可能なシステム構築につながるのではないでしょうか。

Careerバナーconsultingバナー