AWS CognitoでWebアプリにログイン機能を追加する — User PoolsとIdentity Poolsの使い分け
Webアプリに「サインアップ」と「サインイン」を実装しようとしたとき、AWSコンソールを開くと『Cognito User Pools』と『Cognito Identity Pools』という2つの選択肢が並んでいる。どちらを使えばいいのか迷うのは当然で、名前が似ているせいで混同しやすい。結論から言うと、ユーザーのログイン管理にはUser Poolsを使う。Identity Poolsはまったく別の目的のサービスだ。
TL;DR — AWS Cognitoの使い分け早見表
| 目的 | 使うべきサービス | 主な機能 |
|---|---|---|
| サインアップ / サインイン / ユーザー管理 | Cognito User Pools | ユーザーDB、JWT発行、MFA、パスワードポリシー |
| AWSリソース(S3, DynamoDBなど)への一時的アクセス | Cognito Identity Pools | フェデレーテッドID、STS一時認証情報の払い出し |
| ログイン後にAWSリソースも直接操作させたい | 両方を組み合わせる | User PoolsでJWT取得 → Identity Poolsで一時認証情報に交換 |
AWS Cognito User Poolsの仕組みを理解する
User Poolsは、アプリケーション専用のユーザーディレクトリだ。メールアドレスとパスワードでサインアップしたユーザーの情報を保持し、認証が成功するとOpenID Connect準拠のJWTトークン(IDトークン、アクセストークン、リフレッシュトークン)を発行する。バックエンドAPIはこのJWTを検証するだけでよく、セッション管理の複雑さをCognitoに委譲できる。
- サインアップ / サインイン: ブラウザからCognito User Poolsへ認証リクエストを送る。
- JWT発行: 認証成功後、IDトークン・アクセストークン・リフレッシュトークンの3種類が返される。
- APIアクセス: フロントエンドはAuthorizationヘッダにIDトークンを付けてバックエンドAPIを呼ぶ。
- JWT検証: API GatewayまたはバックエンドがUser PoolsのJWKSエンドポイントを使ってトークンを検証する。
Identity Poolsはこのフローとは無関係だ。Identity Poolsの役割は、認証済みユーザー(またはゲストユーザー)にAWS STSの一時的な認証情報を払い出すことであり、ユーザーのパスワードやプロフィールを管理する機能は持っていない。
User Poolsを『アプリのユーザーDB + 認証サーバー』、Identity Poolsを『AWSリソースへの入場券発行機』と考えると役割が整理しやすい。
AWS Cognito User Poolsでサインアップ・サインインを実装する
以下の手順でUser Poolsを作成し、アプリクライアントを設定する。CLIで一連の操作を完結させることができる。
Step 1: User Poolsを作成する
まずUser Poolsを作成する。ここでパスワードポリシーやMFAの設定が決まる。作成後に返されるUserPoolIdは以降の手順で必要になるため、必ず記録しておく。
aws cognito-idp create-user-pool \
--pool-name MyAppUserPool \
--policies 'PasswordPolicy={MinimumLength=8,RequireUppercase=true,RequireLowercase=true,RequireNumbers=true,RequireSymbols=false}' \
--auto-verified-attributes email \
--region us-east-1
--auto-verified-attributes emailを指定すると、サインアップ時にメールアドレス確認コードが自動送信される。本番環境では--mfa-configurationオプションでMFAを有効化することを強く推奨する。
Step 2: アプリクライアントを作成する
User Poolsを作成しただけではアプリから認証できない。アプリクライアントを作成することで、フロントエンドやバックエンドがUser Poolsと通信するためのクライアントIDが払い出される。--no-generate-secretはSPAやモバイルアプリなどクライアントシークレットを安全に保管できない環境向けの設定だ。
aws cognito-idp create-user-pool-client \
--user-pool-id us-east-1_XXXXXXXXX \
--client-name MyAppClient \
--no-generate-secret \
--explicit-auth-flows ALLOW_USER_SRP_AUTH ALLOW_REFRESH_TOKEN_AUTH \
--region us-east-1
Step 3: ユーザーのサインアップとメール確認
アプリクライアントIDが取得できたら、実際にユーザーを登録できる。以下はCLIでサインアップを実行する例だ。実際のアプリではAWS Amplify LibrariesやCognito Hosted UIを使うことが多いが、動作確認にはCLIが便利だ。
aws cognito-idp sign-up \
--client-id YOUR_CLIENT_ID \
--username user@example.com \
--password 'MyP@ssword1' \
--region us-east-1
サインアップ後、登録メールアドレスに確認コードが届く。そのコードで確認を完了させる。
aws cognito-idp confirm-sign-up \
--client-id YOUR_CLIENT_ID \
--username user@example.com \
--confirmation-code 123456 \
--region us-east-1
Step 4: サインインしてJWTを取得する
メール確認が完了したユーザーでサインインする。USER_SRP_AUTHフローはパスワードをネットワーク上に平文で送らないSRP(Secure Remote Password)プロトコルを使用する。CLIでの簡易確認にはUSER_PASSWORD_AUTHフローも使えるが、本番アプリではUSER_SRP_AUTHを使うこと。
aws cognito-idp initiate-auth \
--auth-flow USER_PASSWORD_AUTH \
--auth-parameters USERNAME=user@example.com,PASSWORD='MyP@ssword1' \
--client-id YOUR_CLIENT_ID \
--region us-east-1
成功するとAuthenticationResultの中にIdToken、AccessToken、RefreshTokenが返される。バックエンドAPIの認証にはこのIdTokenをAuthorizationヘッダに付与する。
よくある誤解 — Identity PoolsをユーザーDBとして使おうとした場合
「Identity Poolsにもユーザーを追加できるのでは?」と考えてAWSコンソールを操作すると、Identity Poolsにはユーザー登録フォームが存在しないことに気づく。Identity Poolsが管理するのはIAMロールへのマッピングであり、ユーザーのパスワードやメールアドレスを保持する仕組みではない。
認証 / JWT発行"] UP -- "JWTトークン" --> IP["Cognito Identity Pools
JWT → 一時認証情報に交換"] IP -- "STS一時認証情報" --> STS["AWS STS"] STS -- "IAM一時認証情報" --> AWSRes["AWSリソース
S3 / DynamoDB など"] UP -- "JWTトークン" --> APIGW["API Gateway
Cognitoオーソライザー"] APIGW --> Backend["バックエンドAPI"]
- 認証フェーズ: User Poolsがユーザー認証を担当し、JWTを発行する。
- 認証情報交換フェーズ: Identity PoolsはUser PoolsのJWTを受け取り、STSに一時的なIAM認証情報を要求する。
- AWSリソースアクセス: フロントエンドはSTSから受け取った一時認証情報を使ってS3やDynamoDBに直接アクセスする。
ユーザーのサインアップ・サインインだけが目的なら、Identity Poolsは不要だ。S3バケットへの直接アップロードなど、フロントエンドからAWSリソースを直接操作させたい場合にのみ、User PoolsとIdentity Poolsを組み合わせる構成を検討する。
Cognito User Pools管理に必要なIAMポリシー
CI/CDパイプラインや管理スクリプトからUser Poolsを操作する場合、最小権限の原則に従ったIAMポリシーが必要だ。CreateUserPoolはリソースレベルの権限制御をサポートしていないため、このアクションだけResource: "*"が必要になる。その他のアクションは特定のUser Pool ARNに絞ることができる。
🔽 IAMポリシーサンプルを展開する
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CognitoCreateUserPool",
"Effect": "Allow",
"Action": [
"cognito-idp:CreateUserPool"
],
"Resource": "*"
},
{
"Sid": "CognitoManageSpecificUserPool",
"Effect": "Allow",
"Action": [
"cognito-idp:DescribeUserPool",
"cognito-idp:UpdateUserPool",
"cognito-idp:DeleteUserPool",
"cognito-idp:CreateUserPoolClient",
"cognito-idp:DescribeUserPoolClient",
"cognito-idp:AdminCreateUser",
"cognito-idp:AdminDeleteUser",
"cognito-idp:AdminGetUser",
"cognito-idp:ListUsers"
],
"Resource": "arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_XXXXXXXXX"
}
]
}
CreateUserPoolをResource: "*"にしなければならない理由は、User Pool作成時点ではARNがまだ存在しないためだ。作成後の操作(DescribeUserPool、AdminCreateUserなど)は特定のARNに絞ることができ、最小権限の原則を維持できる。
実際の障害パターン — 『トークンは返ってくるのにAPIが401を返す』
サインインは成功してIDトークンが取得できているのに、API Gatewayが401を返し続けるケースがある。最初はCognitoの設定を疑うが、実際にはAPI GatewayのCognitoオーソライザー設定の問題であることが多い。
具体的には、オーソライザーに設定したUser Pool ARNと、トークンを発行したUser Poolが一致していないケースだ。開発環境と本番環境でUser Poolsを分けているときに、デプロイ時に環境変数の差し替えを忘れると発生する。CloudFormationやTerraformでインフラを管理していても、API Gatewayのオーソライザーだけをコンソールでアドホックに変更していると見落としやすい。
確認コマンドはシンプルだ。
aws apigateway get-authorizer \
--rest-api-id YOUR_API_ID \
--authorizer-id YOUR_AUTHORIZER_ID \
--region us-east-1
返ってきたproviderARNsの値と、トークンを発行したUser PoolのARNを突き合わせる。一致していなければオーソライザーを更新する。
aws apigateway update-authorizer \
--rest-api-id YOUR_API_ID \
--authorizer-id YOUR_AUTHORIZER_ID \
--patch-operations op=replace,path=/providerARNs/0,value=arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_XXXXXXXXX \
--region us-east-1
JWTの中身をjwt.ioでデコードしてissクレームを確認すると、どのUser Poolが発行したトークンかが一目でわかる。401が出たらまずここを見る習慣をつけると診断が早い。
AWS Cognito User Poolsのまとめと次のステップ
WebアプリのサインアップとサインインにはCognito User Poolsを使う。Identity Poolsはユーザーデータベースではなく、認証済みユーザーにAWSリソースへの一時的なアクセス権を付与するための仕組みだ。この2つを混同すると設計が複雑になるだけなので、目的に応じて明確に使い分けることが重要だ。
次のステップとして、以下を参照することを推奨する。
- Amazon Cognito User Pools — AWS公式ドキュメント
- Amazon Cognito Identity Pools — AWS公式ドキュメント
- AWS Amplify Authentication — フロントエンド統合ガイド
用語集
| 用語 | 説明 |
|---|---|
| User Pools | Cognitoが提供するユーザーディレクトリ。サインアップ・サインイン・JWT発行を担う。 |
| Identity Pools | 認証済みユーザーにAWS STSの一時的な認証情報を払い出す仕組み。ユーザーDBではない。 |
| JWT (JSON Web Token) | 認証成功後にUser Poolsが発行する署名付きトークン。IDトークン・アクセストークン・リフレッシュトークンの3種類がある。 |
| SRP (Secure Remote Password) | パスワードをネットワーク上に平文で送らずに認証するプロトコル。Cognitoの推奨認証フロー。 |
| アプリクライアント | User Poolsに対してアプリが認証リクエストを送るための識別子。クライアントIDとして使用する。 |
コメント
コメントを投稿