本ページは、AWS に関する個人の勉強および勉強会で使用することを目的に、AWS ドキュメントなどを参照し作成しておりますが、記載の誤り等が含まれる場合がございます。

最新の情報については、AWS 公式ドキュメントをご参照ください。

Amazon Cognito は、ウェブおよびモバイルアプリケーションに認証、認可、およびユーザー管理機能を追加するためのサービスです。ユーザーは、ユーザー名とパスワードを使用して直接サインインするか、Facebook、Amazon、Google、Apple などのサードパーティーを通じてサインインすることができます。

1.1. 公式ドキュメント

Amazon Cognitoを理解する公式ドキュメントは次のとおりです。

Amazon Cognito サービス概要

Amazon Cognito ドキュメント

Amazon Cognito よくある質問

Amazon Cognito の料金

1.2. 学習リソース

「Amazon Cognito」をグラレコで解説|builders.flash

【AWS Black Belt Online Seminar】Amazon Cognito(YouTube)(59:18)

blackbelt

1.3. ワークショップ

Amazon Cognito Workshop

Cognito API ハンズオン

Simplify web app authentication: A guide to AD FS federation with Amazon Cognito user pools

SAML for Your Serverless JavaScript Application

Implementing passwordless email authentication with Amazon Cognito

SaaS AuthN/Z Workshop

1.4. 導入のメリット

Cognito の主な利点は以下の通りです:

2.1 Cognito の主な機能

Amazon Cognito は主に2つのコンポーネントで構成されています:

  1. ユーザープール: ユーザーディレクトリを提供し、サインアップ/サインイン機能を実装するためのもの
  2. ID プール: ユーザーに対して一時的なAWS認証情報を提供し、特定のAWSリソースへのアクセスを許可するためのもの

cognito_overview

この2つを組み合わせることで、認証されたユーザーにアプリケーションやAWSリソースへのアクセス権を付与する仕組みを構築できます。

2.2 ユーザープール

ユーザープールは、Amazon Cognitoのユーザーディレクトリです。ユーザープールを使用すると、ユーザーはAmazon Cognitoを通じて、またはサードパーティーIDプロバイダー(IdP)を通じてウェブやモバイルアプリにサインインできます。

cognito_user_pool

ユーザープールの主な特徴は以下の通りです:

2.2.1. ユーザープール機能プラン

2024年11月22日 Amazon Cognito 新しい機能ティア Essentials と Plus のお知らせ

Cognitoユーザープールに機能と料金の異なる3つのプラン(Lite / Essentials / Plus)が追加されました。

詳細は、公式のプラン比較を確認してください。

cognito-plan

次に、料金比較と特徴は次のとおりです。

料金範囲 (MAU)

Lite

Essentials

Plus

無料利用枠

10,000

10,000

なし

10,001~100,000

USD 0.0055

USD 0.015

USD 0.02

100,001~1,000,000

USD 0.0046

1,000,001 ~ 10,000,000

USD 0.00325

10,000,000 超

USD 0.0025

Liteプランでは従来の「高度なセキュリティ機能」が追加コストで利用できます。

料金範囲 (MAU)

MAU あたりの料金

最初の 50,000

USD 0.050

次の 50,000

USD 0.035

次の 90 万

USD 0.020

次の 900 万

USD 0.015

10,00 万超

USD 0.010

既存ユーザープールと、Liteのコスト比較

無料MAUが50,000から10,000に引き下げられていますので、コスト増となります。 「高度なセキュリティ機能」を使用しておらず、MAU 10,000以下というのであれば、コスト増の影響を受けません。

before-lite-comparison

「高度なセキュリティ機能」を使用した場合の比較:MAU 500万まで

MAU 500万までを比較してみます。最初は Essensials < Plus < Lite = 既存 となっていますが、MAU 350万を超えたあたりで、Plusのほうが既存+ASFよりコストが高くなり始めます。

allplan-comparison-mau5m

「高度なセキュリティ機能」を使用した場合の比較:MAU 5,000万まで

次に、MAU 5,000万までを比較してみます。1000万を超えたところでは、Plus > Lite=既存 > Essentials となっています。 さらにMAU 2,500万を超えたあたりで、EssentialsがLiteを追い抜き、Plus > Essentials > Lite=既存 となるようです。 allplan-comparison

この結果を見ると、「高度なセキュリティ機能」がすべて必要なければ、MAU 2,500万まではEssentialsを選択することでコストが抑えられます。 MAU 2,500万以上の場合は、コストをしっかり算出し、適切な機能プランを選択するとよいでしょう。

2.2.2. サインアップとサインインのカスタマイズ

Amazon Cognito では、サインアップとサインインのプロセスを以下のようにカスタマイズできます:

2.2.3. 認証フロー

Amazon Cognito ユーザープールは、複数の認証フローをサポートしています:

  1. 選択ベースの認証(ALLOW_USER_AUTH):サインイン時に認証タイプ(ワンタイムパスワード、生体認証デバイスとセキュリティキー、MFA によるパスワードベースのサインインなど)を選択する
  2. ユーザーパスワード認証(ALLOW_USER_PASSWORD_AUTH):最も一般的なフローで、ユーザー名とパスワードによる認証 認証時にはパスワードを平文で送信する。
      {
    "AuthFlow": "USER_PASSWORD_AUTH",
    "AuthParameters": { 
        "USERNAME" : "testuser",
        "PASSWORD" : "Example1234!"
      },
      "ClientId": "1example23456789"
      }
    
  3. 安全なリモートパスワード認証(ALLOW_USER_SRP_AUTH):サーバー側の認証操作でユーザー名とパスワードによる認証 パスワードをハッシュ化して送信する。ALLOW_USER_PASSWORD_AUTHよりもセキュア。
    {
      "AuthFlow": "USER_PASSWORD_AUTH",
      "AuthParameters": { 
          "USERNAME" : "testuser",
          "SRP_A" : "g^a"
      },
      "ClientId": "1example23456789"
    }
    
  4. カスタム認証フロー(ALLOW_CUSTOM_AUTH):Lambda トリガーを使用したカスタム認証チャレンジのフロー
  5. 管理者認証フロー(ALLOW_ADMIN_USER_PASSWORD_AUTH):AWS Admin API を使用したバックエンドサービスからの認証
  6. 更新トークン認証フロー(ALLOW_REFRESH_TOKEN_AUTH):既存の認証済みセッションから更新トークンを使用した認証

2.2.4. トリガー

ユーザープールは Lambda 関数をトリガーとして関連付け、認証フローや登録プロセスをカスタマイズできます。主なトリガーには以下のようなものがあります:

参考:開発者ガイド>Lambda トリガーの使用

2.2.5. ユーザープールのセキュリティ機能

ユーザープールには、以下のようなセキュリティ機能が含まれています:

2.2.6. ホストされた UI

Amazon Cognito は、カスタマイズ可能なホスト型のウェブUIを提供しています。これにより、アプリケーションは独自のサインインページを構築することなく、すぐに認証機能を利用できます。

ホストされた UI の主な特徴:

Liteプランでは、従来のクラシックUIのみが利用できます。

hosted-ui-classic-branding

Essentials以上のプランでは、ブランドデザイナーによるマネージドログインのカスタマイズが可能です。

managed-login-brandingdesigner

2.2.7. トークンの種類と管理

Amazon Cognito は認証後に以下の種類のトークンを発行します:

ID トークン

アクセストークン

更新トークン

トークンの有効期限と更新

トークンの有効期限はユーザープールの設定で定義できます:

トークンの更新フローは以下の通りです:

  1. 更新トークンをAPIに送信
  2. 新しいIDトークンとアクセストークンを受け取る
  3. 必要に応じて更新トークンも更新される

2.3. ID プール

ID プールを使用すると、ユーザーに AWS サービスへのアクセスを許可するための一時的な AWS 認証情報を取得できます。ID プールはユーザープールと連携して動作し、認証されたユーザーに特定の AWS リソースへのアクセス権を付与します。

2.3.1. ID プールの仕組み

ID プールの認証フローは以下の通りです:

  1. ユーザーがIDP(ユーザープールまたは外部プロバイダー)で認証
  2. 認証後、IDPからトークンを受け取る
  3. このトークンをID プールに提示
  4. IDプールが一時クレデンシャルを要求
  5. 生成された一時クレデンシャルをIDプールが受領
  6. ID プールが一時的なAWS認証情報を提供
  7. これらの認証情報を使用してAWSリソースにアクセス

cognito_id_pool

2.3.2. 認証プロバイダー

ID プールは以下のような様々な認証プロバイダー(IDP)をサポートしています:

2.3.3. IAM ロールの設定

ID プールは IAM ロールと連携して動作します。主に以下の2種類のロールを設定できます:

さらに、ユーザー属性に基づいてロールを選択するための「ロールベースのアクセス制御」を実装することができます。これにより、ユーザーの所属グループなどに基づいて異なるレベルのアクセス権を付与できます。

詳細は、Cognito開発者ガイドのIAMロールを参照してください。

2.4. Cognito Sync から AppSync への移行

Cognito Syncとは、アプリケーションに関連するユーザーデータをデバイス間で同期できる機能で、一人のユーザーが複数デバイスを保持している場合にデバイス間でデータを同期します。最大 1 MB のキーと値のペアを保存できるデータセットに保存され、ユーザー ID ごとに最大 20 個のデータセットを持つことができます。これらのデータをローカルに保持し、デバイスがオフラインの場合でもデータを利用できるようにします。

しかし、Cognito Sync は古いサービスで、現在は高機能なAWS AppSync への移行が推奨されています。

AppSync の主な利点:

2.5. Cognito の料金体系

Amazon Cognito の料金は以下の要素に基づきます:

Amazon Cognito 料金ページで最新の料金情報を確認することができます。

基本的な料金構造:

2.6. Cognito のクォータ

Amazon Cognito には以下のようなサービスクォータがあります:

ユーザープール:

ID プール:

クォータの詳細と引き上げ方法については、Amazon Cognito サービスクォータを参照してください。

①Webアプリケーションでの一般的な実装パターン

Amplify ライブラリを使用したReact/Vue.jsなどでの実装したフロントエンドでCognitoによる認証を行い、認証情報を使って、API Gatewayを呼び出す実装例です。 API Gateway のオーソライザーにCognitoを設定します。

web_pattern

②静的ウェブサイトへの認証機能実装パターン

CloudFront 経由でS3の静的ウェブサイトを配信している場合に、認証機能を付与する実装例です。 Lambda@EdgeによってCognito認証を行います。

こちらの方法のサンプルはGitHubのawslabs/cognito-at-edgeにあります。

cloudfront-s3-pattern

③サーバーレス認証パターン

①と②を組み合わせたパターンで、認証部分をフロントエンドで実装せずに、Lambda@EdgeでCognito認証を行います。ログイン画面は「CognitoのホストされたUIを使用」を使用することができます。

serverless-pattern

GitHub>aws-samples/cdk-cognito-idp

AWS CDK を使用してCognitoリソースをデプロイする例:

このCDKスタックでは、以下のCognitoリソースを作成しています:

  1. ユーザープール - ユーザー登録と認証のためのディレクトリ
  2. ユーザープールクライアント - アプリケーションがユーザープールにアクセスするための設定
  3. IDプール - 認証されたユーザーにAWSリソースへのアクセスを提供

実装例:CognitoユーザープールとIDプール作成のCDKコード(クリックしてください)

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
  aws_cognito as cognito 
} from 'aws-cdk-lib';

export class CognitoStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // ユーザープールの作成
    const userPool = new cognito.UserPool(this, 'MyUserPool', {
      userPoolName: 'my-user-pool', // ユーザープール名
      selfSignUpEnabled: true, // セルフサービスのサインアップ設定
      signInAliases: { // サインインエイリアス。ユーザープルに登録する属性
        email: true,
        username: false
      },
      autoVerify: {
        email: true
      },
      standardAttributes: {
        email: {
          required: true,
          mutable: true
        }
      },
      customAttributes: { // カスタム属性
        'family_name_kana': new cognito.StringAttribute({ minLen: 1, maxLen: 256, mutable: true }),
        'given_name_kana': new cognito.StringAttribute({ minLen: 1, maxLen: 256, mutable: true }),
      },
      passwordPolicy: { // パスワードポリシー
        minLength: 16,  // パスワード文字列長
        requireLowercase: true, // 小文字
        requireUppercase: true, // 大文字
        requireDigits: true, // 数字
        requireSymbols: true, // 記号
        temporaryPasswordValidityDays: Duration.days(3), // 一時パスワードが有効な日数
      },
      lambdaTriggers: { // トリガー
        preSignUp: '', // サインアップ前の Lambda トリガー
        postConfirmation: '', // 確認後の Lambda トリガー
        preAuthentication: '', // 認証前の Lambda トリガー
        postAuthentication: '', // 認証後の Lambda トリガー
        // チャレンジの Lambda トリガー
        defineAuthChallenge: '',
        createAuthChallenge: '',
        verifyAuthChallengeResponse: '',

        preTokenGeneration: '', // トークン生成前の Lambda トリガー
        userMigration: '', // ユーザー移行のトリガー
        customMessage: '', // カスタムメッセージのトリガー

        // カスタム送信者のトリガー
        customEmailSender: '',
        customSmsSender: '',
      },
      accountRecovery: cognito.AccountRecovery.EMAIL_ONLY, // ユーザーアカウントの復旧設定
      email: cognito.UserPoolEmail.withCognito('support@example.com'),
      /*
      email: cognito.UserPoolEmail.withSES({ // SES で送信する場合
        fromEmail: 'noreply@example.com',
        fromName: 'Awesome App',
        replyTo: 'support@example.com',
        sesVerifiedDomain: 'example.com',
      }),
      */
    });

    // ユーザープールクライアントの作成
    const userPoolClient = new cognito.UserPoolClient(this, 'MyUserPoolClient', {
      userPool,
      authFlows: {
        userPassword: true,
        userSrp: true
      },
      oAuth: {
        flows: {
          authorizationCodeGrant: true
        },
        scopes: [
          cognito.OAuthScope.EMAIL,
          cognito.OAuthScope.OPENID,
          cognito.OAuthScope.PROFILE
        ],
        callbackUrls: ['https://example.com/callback'],
        logoutUrls: ['https://example.com/'],
      },
    });

    // IDプールの作成
    const identityPool = new cognito.CfnIdentityPool(this, 'MyIdentityPool', {
      identityPoolName: 'my-identity-pool',
      allowUnauthenticatedIdentities: false,
      cognitoIdentityProviders: [{
        clientId: userPoolClient.userPoolClientId,
        providerName: userPool.userPoolProviderName
      }]
    });

    // 出力
    new cdk.CfnOutput(this, 'UserPoolId', {
      value: userPool.userPoolId
    });

    new cdk.CfnOutput(this, 'UserPoolClientId', {
      value: userPoolClient.userPoolClientId
    });

    new cdk.CfnOutput(this, 'IdentityPoolId', {
      value: identityPool.ref
    });
  }
}

4.1. ロギングとモニタリング

4.2. セキュリティ

Amazon Cognito は、アプリケーション向けの認証・認可サービスとして以下の価値を提供します:

アプリケーションの認証機能を実装する際は、Cognitoを検討してみてください。特に複数の認証方法をサポートしたり、AWSリソースへの安全なアクセスを提供したりする場合に威力を発揮します。