はじめに
本記事では、以下についてまとめます。
- Amazon Cognito について
- 使用方法 (デモ)
Amazon Cognito について
概要
ドキュメントには以下の通り記載されていますが、
簡潔に言うと、認証・認可・ユーザー管理 機能を提供するサービス です。
Amazon Cognito はウェブアプリとモバイルアプリ用のアイデンティティプラットフォームです。これは、OAuth 2.0 アクセストークンと AWS 認証情報のための、ユーザーディレクトリであり、認証サーバーであり、認可サービスです。Amazon Cognito を使用すると、組み込みのユーザーディレクトリ、エンタープライズディレクトリ、Google や Facebook などのコンシューマー ID プロバイダーからユーザーを認証および認可できます。
イメージ像
Cognito といっても、2 つのコンポーネントに分けられます。そのイメージ像が以下の通りです。

- それぞれ役割が異なり独立しています
- 必ず連携して使わなければならないというものではありませんので、単独で使うことも、連携して使うことも可能です
User pool
User pool = 認証サーバー と考えてください。
User pool では認証用のエンドポイントを公開し、アプリからはそのエンドポイントを利用することで、アプリ利用ユーザーの認証を実施する形となります。
結局のところ、最終的に User pool はアプリに対して JWTトークン を発行しているだけです。

肝心の User pool の中身ですが、設定可能項目の全体像は以下の通りです。
設定項目が多いので、順を追ってみていきましょう。


初回作成時
本質的なところではないですが、User pool の作成時の流れを記載します。(ここが以外にわかりにくいので)
Cognito サービスページで「ユーザープールを作成」をクリックします。

まずアプリケーションを定義します。詳細は後述します。
ここは後からでも追加変更できます。

こちらは、ユーザープール内で定義したアプリケーションへの サインイン 及び サインアップ 時に必要な情報を設定します。
- こちらは後から変更ができません
- また、ユーザープール内で定義するアプリケーション全てに関わる設定となるため注意
こちらは先程定義したアプリケーションにてサインイン成功時にリダイレクトされるURLを指定します。
ここは後からでも変更できます。

作成されたユーザープール名は、最初はランダムで割り当てられますが変更できます。



プラン
ユーザープールにはプランがあります。
プランによって、使用できる機能が異なります。詳細は以下の記事を参考にしてください。
マネジメントコンソールで作成した場合、デフォルトは エッセンシャル となります。
プランは後からでも変更することが可能です。



アプリケーションクライアント
ユーザープールを利用するウェブアプリ・モバイルアプリにおけるユーザーの認証情報やフローを定義するものです。ざっと以下の設定をします。
- クライアントシークレット有無
- 認証フロー
- トークン有効期限
- 認証に使う属性 (
emailやaddress等) に対する R/W 権限 - マネージドログインページ設定
アプリにとっては、ユーザープールを利用する入口みたいなものです。
アプリはこの入口を使って、ユーザープールへの認証やトークン取得を実施します。
なので、 アプリ:アプリケーションクライアント = 1:1 の関係です。
アプリケーションクライアントがあって初めてユーザープールが使えると言うことですね。
アプリケーションクライアント自体は、ユーザープール内に複数作成することは可能です。

- タイプの違いと、認証フローについては 番外編 にまとめてます
ユーザー管理
こちら で、アプリはアプリケーションクライアントを入口として、その情報を使って認証やトークンを取得すると記載しました。
アプリケーションクライアントの設定項目の一つとして IDプロバイダー を設定する箇所があるのですが、デフォルトでは Cognito ユーザープールディレクトリ となっています。
ユーザー管理 に表示されているユーザーは、この Cognito ユーザープールディレクトリ で管理されているユーザーとなります。登録されているユーザーが、アプリを利用できるユーザーということになります。

ユーザー自体は、管理者が追加することも、ユーザー自身がサインアップ時に登録することも可能です。
また、IdP はアプリケーションクライアントの設定を変更することで、外部 IdP とすることも可能です。
認証方法
ここでは、以下の設定を実施します。
- ユーザー登録した際に、ユーザーに送信するメッセージの設定
- ユーザー登録時のパスワードポリシー
- パスキー設定
- 本設定は、ユーザープールで管理しているアプリケーションクライアント全部に適用されます
- 厳密には、M2M認証以外のマネージドログインを利用する場合です
サインイン
こちらはユーザーがアプリにサインインする際に必要な属性や方式を設定します。


- 本設定は、ユーザープールで管理しているアプリケーションクライアント全部に適用されます
- 厳密には、M2M認証以外のマネージドログインを利用する場合です
サインアップ
こちらはユーザーがアプリにサインアップ(ユーザー登録)する際に必要な属性や方式を設定します。

- 本設定は、ユーザープールで管理しているアプリケーションクライアント全部に適用されます
- 厳密には、M2M認証以外のマネージドログインを利用する場合です
外部 IdP
外部 IdP を登録できます。
登録した後、アプリケーションクライアント側で指定することで、Cognito ユーザープールディレクトリ にユーザーを登録せずとも、ユーザー認証することが可能です。

サポートされているサードパーティや、SMAL 及び OIDC に準拠する製品なら連携が可能です。

Lambda トリガー
特定のタイミングで Lambda を呼び出しアクションを実行することが可能となります。


- 本設定は、ユーザープールで管理しているアプリケーションクライアント全部に適用されます
セキュリティ機能
本項目では、以下の機能を有効化することができます
- WAF WebACL の適用
- 脅威保護
- ユーザーアクティビティログ取得
ブランディング
ここでは、マネージドログインのドメイン設定と、ユーザーへの送信メッセージテンプレートの変更が可能です。



ID pool (Identity pool)
ID pool = 認可サーバー と考えてください。
何に対する認可かというと、AWSサービスへのAPIコールに対する認可です。
付与する権限の実態は IAM ロール で、ユーザーには一時的なクレデンシャルを付与します。
設定次第ですが、認証されたユーザー or 匿名ユーザー に対して認可することが可能です。
イメージは以下のとおりです。
認証が必要な場合は、別途 連携する IdP が必要になります。

設定項目について順を追ってみていきましょう。
初回作成時
本質的なところではないですが、ID pool の作成時の流れを記載します。
Cognito サービスページで「IDプールを作成」をクリックします。

作成する ID pool にて、認証ユーザー or 匿名ユーザー アクセスを許可するかを設定します。
もちろん両方有効にすることは可能です。

認証されたアクセス を選択した場合は、連携する IdP を選択する必要があります。

- 作成後に、上記のアクセス権限設定は変更することが可能です
続いて、認証ユーザー 及び 匿名ユーザー に割り当てる IAM ロールを設定します。


- 後から変更も可能です
- また、認証ユーザーに関しては、後述しますが、ルールベースで対象のIAM ロールを振り分けることも可能です
続いて、今回は 認証ユーザーに対する認可も有効としているので、連携する IdP を選択します。
このタイミングではスキップすることも可能です。
ロール設定 及び アクセスコントロール属性 については後述します。

最後に、作成する ID pool 名と、基本認証有無 を選択します。

- 後から変更も可能です
作成された IAM ロール
自動で作成された IAM ロールは以下の通りです。
信頼ポリシーに関しては、作成した ID pool が AWS STS に対しての権限取得ができるようになっています。違いとしては、Condition句の ForAnyValue:StringLike が authenticated or unauthenticated になっている点です。
アタッチされたポリシーに関しては、どちらも同じで、ID pool からクレデンシャルを取得する権限が付与されています。
これが最小権限となっているため、このIAM ロールに、ユーザーに付与したい権限のIAM ポリシーをアタッチしてく形になります。
より詳細は以下ドキュメントを参照ください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "ap-northeast-1:d1bd489e-583f-4a51-943d-21097ddd9493"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cognito-identity:GetCredentialsForIdentity"
],
"Resource": [
"*"
]
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "ap-northeast-1:d1bd489e-583f-4a51-943d-21097ddd9493"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "unauthenticated"
}
}
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cognito-identity:GetCredentialsForIdentity"
],
"Resource": [
"*"
]
}
]
}
- 匿名ユーザーがアクセス可能なAWS サービスは制限されています
認証ユーザーへの IAM ロール振り分けルール
クレームの値に応じて、割り当てる IAM ロールを変えることが可能です。

プッシュ同期
こちらは、ID pool に何らかの変更が加わった際に、 Amazon SNS へ通知を push する設定です。


- こちらは Amazon Cognito Sync の機能であり、現在では AWS AppSync の利用が推奨されています
Cognito ストリーム
こちらは、ID pool に何らかの変更が加わった際に、 Amazon Kinesis Data Streams に送信する設定です。


- こちらは Amazon Cognito Sync の機能であり、現在では AWS AppSync の利用が推奨されています
Cognito イベント
こちらは、ID pool にて特定のイベントが発生した場合に、Lambda を呼び出す設定です。


- こちらは Amazon Cognito Sync の機能であり、現在では AWS AppSync の利用が推奨されています
使用方法(デモ) - ID pool
検証構成
検証構成図は以下の通りです。
呼び出すユーザーを SPA アプリケーションに見立てて検証していきます。
- 環境構築コードは以下 GitHub にあげてますので、よかったら覗いてみてください
実践
匿名ユーザー
匿名ユーザーの場合は、ID pool から直接一時クレデンシャルを発行します。
まず以下のコマンドを実行して、ID pool から一意な Identity ID を取得します。
$ ID_POOL_ID=対象IDPoolのID
$ IDENTITY_ID=$(aws cognito-identity get-id \
--identity-pool-id ${ID_POOL_ID} \
--query "IdentityId" \
--output text)
続いて取得した Identity ID を使って、一時クレデンシャルを取得します。
$ CREDENTIALS=$(aws cognito-identity get-credentials-for-identity \
--identity-id ${IDENTITY_ID} \
--query "Credentials")
CREDENTIALS 変数に、アクセスキーID/シークレットアクセスキー/セッショントークン が json形式で格納されているため、環境変数に代入します。
$ AWS_ACCESS_KEY_ID=$(echo ${CREDENTIALS} | jq -r .AccessKeyId)
$ AWS_SECRET_ACCESS_KEY=$(echo ${CREDENTIALS} | jq -r .SecretKey)
$ AWS_SESSION_TOKEN=$(echo ${CREDENTIALS} | jq -r .SessionToken)
$ export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
$ export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
$ export AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN
実際に権限情報を以下のコマンドで確認します。
意図した通り、匿名ユーザー用IAMロールを AssumeRole しているのがわかります。
$ aws sts get-caller-identity
{
"UserId": "AROA5TDDJNWS4R2ZZAAM7:CognitoIdentityCredentials",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/iam-role-anonymous-user/CognitoIdentityCredentials"
}
- 割愛しますが、上記IAMロールには AWS管理ポリシーの
AmazonS3ReadOnlyAccessがアタッチされており、問題なくS3を get することができました
認証ユーザー
認証ユーザーの場合は、まず ID pool が連携している IdP にて認証をする必要があります。
今回は、User pool を IdP としているため、ユーザー認証を実施します。
が、今回の構成上まだ仮パスワードを変更していないので、以下のコマンドでPW変更含めて実施していきます。
$ CLIENT_ID=アプリケーションクライアントID
$ USER_EMAIL=認証ユーザーEMAILアドレス
$ TMP_PW=認証ユーザーPW
$ RESPONSE=$(aws cognito-idp initiate-auth \
--client-id ${CLIENT_ID} \
--auth-flow USER_PASSWORD_AUTH \
--auth-parameters "USERNAME=${USER_EMAIL},PASSWORD=${TMP_PW}")
$ CHALLENGE_NAME=$(echo ${RESPONSE} | jq -r .ChallengeName)
$ SESSION=$(echo ${RESPONSE} | jq -r .Session)
$ NEW_PW=PassW@rd123
$ ID_TOKEN=$(aws cognito-idp respond-to-auth-challenge \
--client-id ${CLIENT_ID} \
--challenge-name ${CHALLENGE_NAME} \
--session ${SESSION} \
--challenge-responses "USERNAME=${USER_EMAIL},NEW_PASSWORD=${NEW_PW}" \
--query "AuthenticationResult.IdToken")
事前にパスワード変更されている方は、以下の手順で IdToken を取得します
$ CLIENT_ID=アプリケーションクライアントID
$ USER_EMAIL=認証ユーザーEMAILアドレス
$ NEW_PW=変更したPW
$ ID_TOKEN=$(aws cognito-idp initiate-auth \
--client-id ${CLIENT_ID} \
--auth-flow USER_PASSWORD_AUTH \
--auth-parameters "USERNAME=${USER_EMAIL},PASSWORD=${NEW_PW}" \
--query "AuthenticationResult.IdToken")
続いて以下のコマンドを実行して、ID pool から一意な Identity ID を取得します。
$ REGION=ap-northeast-1
$ ID_POOL_ID=対象IDPoolのID
$ USER_POOL_ID=対象UserPoolのID
$ COGNITO_USER_POOL=cognito-idp.${REGION}.amazonaws.com/${USER_POOL_ID}
$ IDENTITY_ID=$(aws cognito-identity get-id \
--identity-pool-id ${ID_POOL_ID} \
--logins "${COGNITO_USER_POOL}=${ID_TOKEN}" \
--query "IdentityId" \
--output text)
続いて取得した Identity ID を使って、一時クレデンシャルを取得します。
$ CREDENTIALS=$(aws cognito-identity get-credentials-for-identity \
--identity-id ${IDENTITY_ID} \
--logins "${COGNITO_USER_POOL}=${ID_TOKEN}" \
--query "Credentials")
CREDENTIALS 変数に、アクセスキーID/シークレットアクセスキー/セッショントークン が json形式で格納されているため、環境変数に代入します。
$ AWS_ACCESS_KEY_ID=$(echo ${CREDENTIALS} | jq -r .AccessKeyId)
$ AWS_SECRET_ACCESS_KEY=$(echo ${CREDENTIALS} | jq -r .SecretKey)
$ AWS_SESSION_TOKEN=$(echo ${CREDENTIALS} | jq -r .SessionToken)
$ export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
$ export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
$ export AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN
実際に権限情報を以下のコマンドで確認します。
意図した通り、認証ユーザー用IAMロールを AssumeRole しているのがわかります。
$ aws sts get-caller-identity
{
"UserId": "AROA5TDDJNWS3ASHVBYSN:CognitoIdentityCredentials",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/iam-role-authenticated-user/CognitoIdentityCredentials"
}
- 割愛しますが、上記IAMロールには AWS管理ポリシーの
AmazonS3ReadOnlyAccessがアタッチされており、問題なくS3を get することができました
使用方法(デモ) - User pool
検証構成
検証構成図は以下の通りです。
呼び出すユーザーを SPA アプリケーションに見立てて検証していきます。

- 環境構築コードは以下 GitHub にあげてますので、よかったら除いてみてください
実践
実際にやっていきますが、構成上まだ仮パスワードを変更していないので、以下コマンドでPW変更を実施します。
今回は管理者で実行します。
$ USER_POOL_ID=対象UserPoolのID
$ USER_EMAIL=認証ユーザーEMAILアドレス
$ NEW_PW=PassW@rd123
$ aws cognito-idp admin-set-user-password \
--user-pool-id ${USER_POOL_ID} \
--username ${USER_EMAIL} \
--password ${NEW_PW} \
--permanent \
--profile admin
- ローカルPCにて、実行権限を持つIAMユーザーのプロファイルを作成する必要があります
- ない場合は、こちらを参考にユーザー自身による変更を実施してください
認証失敗パターンを見ていきましょう。
ヘッダーを指定せず、API Gatwayを呼び出してみます。
Postman で実行していきます。
認証エラーになりますね。

認証成功パターンを見ていきましょう。
まず、User pool から IDトークン を取得します。
Postman の入力項目は以下の通りです。
メソッド:POST
URL:https://cognito-idp.リージョン名.amazonaws.com/
キー:X-Amz-Target
バリュー:AWSCognitoIdentityProviderService.InitiateAuth
キー:Content-Type
バリュー:application/x-amz-json-1.1
{
"ClientId" : "COGNITO_APPLICATION_CLIENT_ID",
"AuthFlow" : "USER_PASSWORD_AUTH",
"AuthParameters": {
"USERNAME" : "認証ユーザーメールアドレス",
"PASSWORD" : "認証ユーザーパスワード"
}
}
IDトークン を取得できたので、ヘッダーに付与してリクエストを実行します。
また、今回の構成では気分的に APIキー を付け加えているので、そちらもヘッダーに入れて実行します。
認証成功ですね。
Postman の入力項目は以下の通りです。
メソッド:POST
URL:https://独自ドメイン/hello
キー:x-api-key
バリュー:作成したAPIキー値
キー:Authorization
バリュー:取得したIDトークン
おわりに
本記事では、Amazon Cognito についてと、デモを交えながら各コンポーネントについて整理しました。
Cognito は単体で使うことはめったにないのでなかなかイメージが沸かないですが、ぜひ本記事で整理していただければと思います。
🌟この記事が誰かの役に立てば幸いです!
また、ご質問やフィードバックもお待ちしています。
番外編
User pool の分け方
本編でも記載しましたが、ユーザープール内にアプリの入口となるアプリケーションクライアントを複数作成することが可能です。すなわち、1つのユーザープールで、複数のアプリを管理する(複数のアプリの認証方式を管理する)ことが可能ということです。
それならそもそもユーザープールを分ける必要があるかですが、基本的にはアプリごとにユーザープールを分けるのが良いと考えます。
本編にも記載しましたが、アプリケーションクライアント設定以外の項目は、ユーザープール全体に適用される項目となるため、そこのカスタマイズや柔軟性を考えると、分けるのが良いと考えています。
アプリケーション内のテナントごとにユーザープールを作成します。このアプローチは各テナントを最大限に分離します。テナントごとに異なる設定を実装することができます。ユーザープールによるテナントの分離は、ユーザー対テナントのマッピングに柔軟性を与えます。同じユーザーに複数のプロファイルを作成することができます。ただし、ユーザーはそれぞれ、アクセスできるテナントごとに個別にサインアップする必要があります。
クライアントアプリケーションタイプによる違いと認証フローについて
クライアントアプリケーションタイプの違い
再掲にはなりますが、アプリケーションクライアントを作成する際タイプを選択することになります。

どのタイプを選んでも、設定項目自体は変わりません。アプリケーションに応じたプリセットが入るくらいのイメージです。
ただし大きな違いは、クライアントシークレット有無 です。
クライアントシークレットとは、アプリケーションが認証サーバーに対して自身を証明するためのものです。
4つのタイプの内、クライアントシークレットを生成できるものは以下2つです。
- 従来のWebアプリケーション
- Machine to Machine アプリケーション
クライアントシークレットを保持できるアプリ = Public Client / クライアントシークレットを保持できないアプリ = Confidential Client と言いますが、アプリがどちらの実装かによって、アプリケーションクライアントタイプは以下の用に大別できます。
- Public Client :
- SPA アプリケーション / モバイルアプリケーション
- ブラウザ、モバイルデバイスからAPIを実行
- Confidential Client :
- 従来のWebアプリケーション / Machine to Machine アプリケーション
- シークレットを持ったサーバーからAPIを実行
- アプリの実装によってクライアントタイプは変わりますが、その点は一旦考慮外とします
まとめると、各アプリケーションクライアントタイプの選択判断は以下の通りです。
ユーザーインタラクションがあるか?
├─ No
│ └─ Machine to Machine (M2M)アプリケーション
│ ├─ アプリの種類:バッチ / API間通信 / マイクロサービス
│ ├─ Client Type:Confidential
│ ├─ Client Secret:あり
│ └─ 主なフロー:Client Credentials
│
└─ Yes
└─ Client Secret を安全に保持できるか?
│
├─ No(Public Client)
│ ├─ ブラウザのみ(JSが直接Cognitoと通信)
│ │ └─ Single Page Application (SPA)アプリケーション
│ │ ├─ アプリの種類:React / Vue / Angular
│ │ ├─ Client Type:Public
│ │ ├─ Client Secret:なし
│ │ └─ 主なフロー:Authorization Code + PKCE
│ │
│ └─ ネイティブアプリ(iOS / Android)
│ └─ Mobile アプリケーション
│ ├─ アプリの種類:iOS / Android
│ ├─ Client Type:Public
│ ├─ Client Secret:なし
│ └─ 主なフロー:Authorization Code + PKCE
│
└─ Yes(Confidential Client)
└─ サーバーあり(BFF / MVC / API)
└─ 従来のWebアプリケーション
├─ アプリの種類:Next.js(BFF) / Spring / Rails
├─ Client Type:Confidential
├─ Client Secret:あり
└─ 主なフロー:Authorization Code
認証フロー
認証フローは以下 6 種類あります。
ここは結局アプリの実装によります。
複数選択可能ですが、有効化する = 受付可能にする ということなので、アプリの実装で使わない認証フローを有効化しても意味が有りません。

認証フローによって必要な情報が変わってくるのと、どこを起点として認証が発生するのかを踏まえて、アプリの実装を検討する必要があります。
参考資料
リファレンス
- Amazon Cognito とは - デベロッパーガイド
- Amazon Cognito - AWS Black Belt Online Seminer
- Amazon Cognito -AWS Black Belt Online Seminer
- 認証・認可サービス構築 on AWS - AWS Black Belt Online Seminer
ブログ
- [アップデート] Amazon Cognito ユーザープールに機能プランの概念が導入され、料金計算方法が変わります - DevelopersIO
- [アップデート] Amazon Cognito ユーザープールに「機能 Tier」の概念が追加されたので、Tier ごとに利用可能な機能をまとめてみた - DevelopersIO
- AWS CLIで動かして学ぶCognito IDプールを利用したAWSの一時クレデンシャルキー発行 - DevelopersIO
- Cognito でユーザープールベースのマルチテナンシーを選択した際に、API Gateway で複数ユーザープールを許可する Cognito ユーザープールオーソライザーを SAM で作成してみた - DevelopersIO
- [AWS CDK] Cognito + API Gateway で M2M 認証をやってみた - DevelopersIO
- Cognitoユーザープールを移行してみる(クライアントシークレットあり/なし) - Zenn
- 【図解・コード有】Amazon Cognito を用いた2種類のパスキーの実装〜マネージドログインと Cognito Identity Provider API〜
- 【API Gateway・Cognitoユーザープール】Cognitoを使用した認証・認可を実装してみた - Zenn
- AWSで始めるサーバーレスアーキテクチャ入門 - Zenn
- SSO・Oauth2.0・OIDC・SAML・JWTなど認証・認可関連のコトバを理解する - Zenn
- IAM、OAuth、OpenID Connect、SAML、SSO、JWT を一つの記事で理解する
- 「なんとなく分かってる」を卒業!図解で完全理解するSSO・SAML・OAuth・OIDC・Kerberos認証の違い - Qiita
- OIDCとSAML
- 一番分かりやすい OAuth の説明 - Qiita
- OAuth 2.0 全フローの図解と動画 - Qiita
- 一番分かりやすい OpenID Connect の説明 - Qiita
- OAuth 2.0 の Client Type についての考え方 - Zenn
- OAuthにおけるPublic ClientとConfidential Clientについて - Zenn
- 「ログイン周り」がごちゃつく人へ:認証・認可・SSO・OAuth/OIDC/SAMLの地図 - Qiita




















