Amazon CognitoのIDプール(Identity Pool)は、ユーザープールのIDトークンや外部IdPのトークンを受け取り、IAMロールに紐づく一時的なAWS認証情報に交換する仕組みです。この記事では、ユーザープールとの違いを整理したうえで、AWS CLIで認証情報を取り出す手順、JavaScript SDK v3でブラウザからS3へ直接アクセスするコード、ロールを切り替える方式を解説します。拡張フローと基本フローの選び方、ゲストの制約、採用を見送る構成まで、2026年10月時点の公式ドキュメントに沿って整理しました。
まとめ|Cognito IDプールで一時認証情報を安全に配る実装の結論
IDプールが必要になるのは、ブラウザやモバイルアプリからS3やDynamoDBなどのAWSサービスを利用者自身の権限で直接呼ぶときです。自前のAPIで受けてサーバー側からAWSを呼ぶ構成なら、ユーザープールのJWT検証だけで足り、IDプールは使いません。
使うと決めたら、認証フローは拡張フロー(GetId→GetCredentialsForIdentity)一択です。基本フローは作成時に無効のままにします。ロールの信頼ポリシーにはcognito-identity.amazonaws.com:audとamrの条件を必ず書き、S3のパスやDynamoDBのキーはIDプールのIDで区切ります。
ロールの切り替えは、管理者だけが付け外しできるグループでcognito:preferred_roleを決める方式を勧めます。利用者が書き換えられる属性を条件に使うと、権限の昇格につながります。
ユーザープールとIDプールの違いをトークンと認証情報の受け渡しで整理
両者の役割分担を概念から知りたい場合は、Amazon Cognito(コグニート)とは?料金・できること・使い方をCLIとコード例で解説で全体像を先に押さえてください。ここでは実装に直結する「何を渡して何が返るか」に絞ります。
IDプールが受け取る4種類の認証成果物と返ってくる認証情報の中身
IDプールの認証フローの公式ガイドによると、受け付ける証明は次の表のとおりプロバイダーごとに決まっています。
| プロバイダー | IDプールに渡すもの |
|---|---|
| Cognitoユーザープール | IDトークン |
| OpenID Connect(OIDC) | IDトークン |
| SAML 2.0 | SAMLアサーション |
| ソーシャルプロバイダー | アクセストークン |
ユーザープールから渡すのはアクセストークンではなくIDトークンです。返るのはアクセスキーID・シークレットキー・セッショントークンと有効期限で、アプリはこれでAWSのAPIに署名します。
ユーザープールだけで済む構成とIDプールが必要になる構成の分かれ目
判定基準は1つです。AWSのAPIに署名する主体が、利用者の端末か、自社のサーバーか。端末が署名するならIDプールが要り、サーバーが署名するなら要りません。
公式ガイドは使い道として、S3からのアセット取得や、IAM認可のAPI Gateway・AppSync・DynamoDBへの接続を挙げています。API Gatewayなら、IDプールを使わないCognitoオーソライザーやJWTオーソライザーもあり、その比較はAPI Gatewayの認証:Cognito・JWT・Lambdaオーソライザー・IAM認可の使い分けと設定例で扱っています。
拡張フローと基本フローのAPI呼び出し順とロール選択の主体の違い
認証フローは、ロールをIDプール側で選ぶかアプリ側で選ぶかで2種類あります。拡張フローはGetIdからGetCredentialsForIdentityへ進み、基本フローでは途中でトークンを取得してSTSへ渡す呼び出し順です。
拡張フローの2回のAPI呼び出しと1時間で失効する認証情報の扱い
拡張フロー(enhanced)は、トークンを添えたGetIdでIDプール内のID(ap-northeast-1:GUID形式)を受け取り、同じトークンとIDをGetCredentialsForIdentityに渡して認証情報を受け取る2段階です。どのIAMロールを渡すかはIDプールの設定で決まり、クライアントにロール選択のロジックを書く必要がありません。
公式ガイドは、拡張フローで得た認証情報の有効期間を1時間と明記しています。延長はできないため、SDKの認証情報プロバイダーに再取得を任せる構成が前提です。IDそのものは端末でキャッシュし、2回目以降のGetIdを省く設計が推奨されています。
基本フローを既定で無効にする理由とロールマッピング併用時のエラー
基本フロー(basic/classic)はGetId→GetOpenIdToken→STSのAssumeRoleWithWebIdentityの3段階で、引き受けるロールをアプリが指定します。セッション時間を指定できる、別アカウントのロールを引き受けられるといった自由度がある反面、IDプールを信頼するロールなら何でも要求できてしまいます。
公式ガイドは、新しいIDプールで基本フローを既定で有効にしないことをベストプラクティスとしています。ロールマッピングを設定したIDプールでGetOpenIdTokenを呼ぶとBasic (classic) flow is not supported with RoleMappings, please use enhanced flow.が返り、両者は併用できません。
AWS CLIでIDプールを作成し一時認証情報を取り出すまでの手順
ここからは東京リージョン(ap-northeast-1)に既存のユーザープールがある前提で、AWS CLI 2.38.1時点のリファレンスに沿って作業します。ユーザープールとアプリクライアントの作り方はCognitoで認証基盤を実装する手順:ユーザープール構築からJWT検証までを参照してください。
create-identity-poolでユーザープールを認証プロバイダーに登録する
create-identity-poolのCLIリファレンスにあるとおり、ゲストを許可するかどうかは必須の指定です。ここではゲストを許可せず、基本フローも無効で作ります。
# ゲスト不可・基本フロー無効でIDプールを作成し、IDプールIDを控える
aws cognito-identity create-identity-pool \
--region ap-northeast-1 \
--identity-pool-name app_identity_pool \
--no-allow-unauthenticated-identities \
--no-allow-classic-flow \
--cognito-identity-providers ProviderName="cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_EXAMPLE",ClientId="1example23456789abcdefghij",ServerSideTokenCheck=true \
--query IdentityPoolId --output text
ServerSideTokenCheck=trueにすると、IDプールは認証情報を出す前に、その利用者がグローバルサインアウト済みか削除済みかをユーザープールに問い合わせ、該当すれば400エラーを返します。退会者の残ったIDトークンで認証情報が出るのを防げるため、会員サービスではtrueにします。
認証済みロールの信頼ポリシーにaudとamrの条件を書く設定
IDプールが引き受けるIAMロールは、信頼ポリシーでIDプールを限定します。IDプールのIAMロールの公式ガイドによると、cognito-identity.amazonaws.com:audの条件が無い信頼ポリシーは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:11111111-2222-3333-4444-555555555555"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
amrをauthenticatedに絞らないと、ゲストのセッションでもこのロールを引き受けられる余地が残ります。拡張フローではIDプールが利用者に代わってSTSを呼ぶため、送信元は利用者の端末になりません。そのためaws:SourceIpの条件は常に不一致になり、使えません。IAMロールと信頼ポリシーの基本はAWS IAMとは?仕組み・ユーザー/ロール/ポリシーの違いと権限設計のベストプラクティスで解説しています。
CLIでの既定ロールの紐付けとID取得後の一時認証情報の確認手順
ロールを作ったらset-identity-pool-rolesでIDプールに紐付け、ユーザープールで取得したIDトークンを使って2つのAPIを順に呼びます。get-idのリファレンスにあるとおり、get-idとget-credentials-for-identityは認証情報不要のパブリックAPIです。
POOL=ap-northeast-1:11111111-2222-3333-4444-555555555555
PROVIDER=cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_EXAMPLE
aws cognito-identity set-identity-pool-roles \
--identity-pool-id "$POOL" \
--roles authenticated=arn:aws:iam::123456789012:role/app-auth-role
# ID_TOKEN にはユーザープールのサインインで得たIDトークンを入れておく
IDENTITY_ID=$(aws cognito-identity get-id \
--identity-pool-id "$POOL" \
--logins "$PROVIDER=$ID_TOKEN" \
--query IdentityId --output text)
aws cognito-identity get-credentials-for-identity \
--identity-id "$IDENTITY_ID" \
--logins "$PROVIDER=$ID_TOKEN" \
--query 'Credentials.[AccessKeyId,SecretKey,SessionToken,Expiration]' \
--output text
出力のキー名はSecretAccessKeyではなくSecretKeyです。環境変数に流し込むスクリプトで取り違えやすい箇所なので注意してください。得た認証情報が意図したロールになっているかは、aws sts get-caller-identityの使い方でassumed-role/app-auth-roleと表示されるかで確かめられます。
ブラウザからS3へ直接アップロードする認証情報プロバイダーの実装例
SDKの認証情報プロバイダーは、2つのAPIの呼び出し、IDのキャッシュ、期限切れ時の再取得を代行します。
LoginsマップのキーとIDトークンを渡すJavaScript SDK v3のコード
ユーザープールとIDプールを連携する公式ガイドのとおり、Loginsのキーはcognito-idp.<リージョン>.amazonaws.com/<ユーザープールID>の形式です。値にIDトークンを渡し、生成したプロバイダーをS3クライアントに渡します。
import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
const region = "ap-northeast-1";
const userPoolId = "ap-northeast-1_EXAMPLE";
export async function uploadOwnFile(idToken, file) {
const credentials = fromCognitoIdentityPool({
identityPoolId: "ap-northeast-1:11111111-2222-3333-4444-555555555555",
logins: { [`cognito-idp.${region}.amazonaws.com/${userPoolId}`]: idToken },
clientConfig: { region },
});
const s3 = new S3Client({ region, credentials });
// IDプールのID(ユーザープールのsubではない)をプレフィックスにする
const { identityId } = await credentials();
await s3.send(new PutObjectCommand({
Bucket: "example-user-uploads",
Key: `${identityId}/${file.name}`,
Body: file,
}));
}
バケットのCORS設定で自社オリジンからのPUTを許可しておきます。SDK v3の書き方はAWS SDK for JavaScript v3とは?使い方・v2からの移行手順とS3・DynamoDB実装例にまとめています。
IDプールのsubを条件に利用者ごとのS3パスへアクセスを限定する設定
ロールの権限ポリシーでは、ポリシー変数${cognito-identity.amazonaws.com:sub}を使い、利用者が自分のIDのプレフィックス以外に触れないようにします。公式ガイドの例を東京リージョン向けに書き直すと次のとおりです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example-user-uploads",
"Condition": { "StringLike": { "s3:prefix": ["${cognito-identity.amazonaws.com:sub}/*"] } }
},
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::example-user-uploads/${cognito-identity.amazonaws.com:sub}/*"
}
]
}
ここでのsubはIDプールのID(ap-northeast-1:GUID形式)で、公式ガイドも元のIdPのsubではないと明記しています。会員データにユーザープールのsubしか保存していないと、S3上のファイルと利用者を突き合わせられません。初回のGetIdで得たIDを会員テーブルに記録しておきます。DynamoDBならdynamodb:LeadingKeysの条件で同じ絞り込みができます。バケット側の権限設計はAWS S3の使い方|CLIでのバケット作成から権限設計・署名付きURLまでの実装手順を参照してください。
ロール選択の3方式:既定ロール・preferred_role・ルールマッピングの使い分け
全員に同じロールを渡すなら、前章の既定ロールで足ります。管理者と一般会員で権限を分けるときは次の方式を使います。
グループの優先度でcognito:preferred_roleを決めるトークン方式
ユーザープールのグループにIAMロールを設定すると、IDトークンにcognito:roles(許可ロールのカンマ区切り)とcognito:preferred_roleが入ります。ロールベースアクセス制御の公式ガイドによると、preferred_roleはPrecedenceの値が最も小さいグループのロールで、最小値が並んだ場合は設定されません。
IDプールはまずGetCredentialsForIdentityのCustomRoleArnを見て、cognito:rolesに含まれていればそのロールを、含まれていなければ拒否します。指定が無ければpreferred_role、それも無ければロール解決の設定に従う仕組みです。IDプール側では、ロールの選択を「トークンからロールを選択」にしておきます。グループは管理者APIでしか付け外しできず、権限の境界として信頼しやすい方式です。ロール設計の考え方はRBACとは?ロールベースアクセス制御の仕組みと導入判断で整理しています。
ルールマッピングの25件上限と条件に一致しない場合のロール解決設定
外部IdPのクレームでロールを振り分けるときは、ルールマッピングを使います。一致タイプはEquals・NotEqual・StartsWith・Containsの4種類で、カスタム属性はcustom:deptのように接頭辞を付けて指定します。
{
"IdentityPoolId": "ap-northeast-1:11111111-2222-3333-4444-555555555555",
"Roles": { "authenticated": "arn:aws:iam::123456789012:role/app-auth-role" },
"RoleMappings": {
"cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_EXAMPLE:1example23456789abcdefghij": {
"Type": "Rules",
"AmbiguousRoleResolution": "Deny",
"RulesConfiguration": {
"Rules": [
{ "Claim": "custom:dept", "MatchType": "Equals", "Value": "sales",
"RoleARN": "arn:aws:iam::123456789012:role/app-sales-role" }
]
}
}
}
}
このJSONをset-identity-pool-roles --cli-input-jsonで適用します。ユーザープールの場合、RoleMappingsのキーは「プロバイダー名:アプリクライアントID」です。ルールは上から評価され、最初に一致したロールが使われます。上限はプロバイダーごとに25件で、Cognitoのクォータ一覧でも引き上げ不可です。どれにも一致しないときはAmbiguousRoleResolutionに従い、既定ロールに落とすAuthenticatedRoleより、拒否するDenyのほうが設定漏れに気づけます。custom:deptのような属性を条件にするなら、次の節で述べる書き換え対策が前提です。
属性ベースのアクセス制御に必要なセッションタグの付与と参照の設定
ロールを増やさずに部署やテナントで権限を分けたい場合は、IDプールの「アクセス制御の属性」を使います。トークンのクレームをセッションのプリンシパルタグに写し、ポリシー側で${aws:PrincipalTag/department}のように参照する仕組みです。アクセス制御の属性の公式ガイドのとおり、信頼ポリシーのActionにsts:TagSessionを加えないとタグを付けられません。
公式ガイドは、利用者がUpdateUserAttributesで書き換えられる属性をセキュリティの境界に使わないよう警告しています。すべてのアプリクライアントのWriteAttributesからその属性を外すか、Mutable: falseで定義してください。値に*や?が入るとワイルドカードとして働き、他テナントのリソースまで一致するおそれもあります。属性で制御する設計の全体像はABACとは?属性ベースアクセス制御の仕組みとRBACとの使い分けを参照してください。
ゲストを許可する未認証ロールに掛かるスコープダウンとリクエスト上限値
サインイン前の利用者にも地図表示や画像解析を使わせるなら、未認証IDを許可します。ロールの権限ポリシーとは別の制約が掛かります。
拡張フローのゲストが使えるサービスの範囲とNotAuthorizedException
拡張フローでゲストに認証情報を出すとき、CognitoはインラインのセッションポリシーとAmazonCognitoUnAuthedIdentitiesSessionPolicyを自動で重ねます。実効権限は両者の共通部分になるため、公式の一覧(S3・DynamoDB・Lambda・Location Serviceなど)に無いサービスは、ロールで許可しても使えません。KMSはEncryptやDecryptなど一部の操作に限られます。
ロールで許可したのにNotAuthorizedExceptionが返る場合は、この制約を疑います。公式ガイドは、要件から外せないなら基本フローへの切り替えを案内しています。ただ、ゲストに一覧外のサービスを開ける要件そのものを見直すほうが先です。
未認証IDの乱発に備えるGetIdの25RPS上限とIDのキャッシュ
クォータ一覧によると、GetIdの既定上限はアカウントとリージョンの合計で毎秒25リクエストです。GetCredentialsForIdentityの200より大幅に低く設定されています。IDプールあたりのID数は無制限です。そのため、ページを開くたびに新しいゲストIDを取る実装だと、上限に当たるうえにIDが際限なく増えます。
SDKはIDをキャッシュしますが、ブラウザのストレージを消すと新しいIDになります。ゲストIDに紐づけたデータは消える前提で設計します。ゲストIDのまま外部IdPのトークンを渡すと、IDがリンクまたはマージされ、返るIDが変わることがある点にも注意してください。
IDプールを採用すべき構成と見送るべき構成の署名主体に基づく判断基準
端末からS3・IoT・Location Serviceを直接呼ぶならIDプールを採用する
大容量ファイルのアップロード、IoTのMQTT接続、地図や経路計算のように、サーバーを経由させると帯域やレイテンシの負担が大きい処理はIDプールに向いています。Amplify Gen 2のdefineAuthは既定でIDプールも作るため、Amplifyで組む場合はAmplify×Cognito認証の実装手順:defineAuthと既存プールの参照で生成内容を確かめてから権限を足してください。
この場合の前提は、ロールの権限ポリシーをIDプールのIDやプリンシパルタグで必ず絞ることです。絞らないロールを端末に配るのは、全利用者に同じアクセスキーを配るのと変わりません。
自前APIの裏でAWSを呼ぶ構成ではIDプールを使わずAPI側で認可する
業務ロジックの大半を自前のAPIで処理する会員サービスや業務システムでは、IDプールを入れません。APIがJWTを検証し、サーバーのIAMロールでAWSを呼べば、権限の判断がコードの1か所に集まります。端末に一時認証情報を配ると、利用者はロールが許すAPIを自由な組み合わせで呼べてしまい、業務ルールでの制御が効きません。
監査の観点でも、既定で操作が記録されるかどうかに差がある構成です。CognitoのCloudTrail記録の公式ガイドによると、GetIdやGetCredentialsForIdentityなどはデータイベント扱いで既定では記録されず、記録すると追加料金がかかります。詳細はCognitoのログ取得手順:CloudTrailとユーザーアクティビティログでサインインを監査するに操作の記録方法をまとめました。どちらの構成にするか、既存の会員基盤をどう移すかの判断から相談したい場合は、認証基盤・ID管理システム開発で要件整理から支援しています。
よくある質問
Cognito IDプールの実装で寄せられやすい疑問を、公式ドキュメントの記述に沿って回答します。
Cognito IDプールに料金はかかりますか?
かかりません。Cognitoの料金ページには、ユーザーの認証とユニークIDの付与にIDプールを使っても料金は発生しないと書かれています。費用が出るのは、ユーザープールの月間アクティブユーザー料金と、一時認証情報で呼び出すS3やDynamoDBなど各サービスの利用料です。ユーザープール側の料金体系は機能プランで変わるため、時点を確認してから見積もってください。
IDプールで取得した一時認証情報の有効期限は延ばせますか?
拡張フローでは延ばせません。公式ガイドは拡張フローの認証情報の有効期間を1時間としており、期限が来たらSDKの認証情報プロバイダーが再取得します。基本フローならAssumeRoleWithWebIdentityでセッション時間を指定できますが、ロール選択をアプリに委ねる分だけ守りが弱くなります。期限の延長だけを目的に基本フローへ切り替えるのは勧めません。
ロールの信頼ポリシーが、そのIDプールと認証状態を許可していないときに出るエラーです。cognito-identity.amazonaws.com:audのIDプールIDが一致しているか、amrの条件がゲストと認証済みのどちらを許可しているかを確認します。拡張フローではロールがIDプールと同じAWSアカウントにある必要があり、aws:SourceIpの条件を入れていても失敗します。
IDプールの認証情報でAPI GatewayのIAM認可を呼ぶにはどうしますか?
APIのメソッドの認可をIAMにし、IDプールのロールにexecute-api:Invokeを許可したうえで、取得した一時認証情報でリクエストにSigV4署名を付けます。ゲストの場合も、API Gatewayは拡張フローのセッションポリシーに含まれるサービスです。CognitoオーソライザーやJWTオーソライザーとの違いと設定例はAPI Gatewayの認証の使い分けで解説しています。
ユーザープールを使わずGoogleやSAMLのIdPを直接IDプールにつなげますか?
つなげます。IDプールはGoogle・AppleなどのソーシャルIdP、OIDCプロバイダー、SAMLプロバイダーを直接受け付けます。ただしプロフィール管理やグループによるロール選択はユーザープールの機能です。会員情報を持つアプリなら、外部IdPをユーザープールにフェデレーションしてからIDプールへつなぐほうが管理しやすくなります。
関連記事
- Cognitoで認証基盤を実装する手順:ユーザープール構築からJWT検証まで:IDプールに渡すIDトークンを発行するユーザープール側の構築手順。
- Amazon Cognito(コグニート)とは?料金・できること・使い方をCLIとコード例で解説:ユーザープールとIDプールの役割分担と料金の全体像。
- API Gatewayの認証:Cognito・JWT・Lambdaオーソライザー・IAM認可の使い分けと設定例:一時認証情報で署名するIAM認可と他の3方式の比較。
- AWS IAMとは?仕組み・ユーザー/ロール/ポリシーの違いと権限設計のベストプラクティスを実装者目線で解説:IDプールが引き受けるIAMロールとポリシーの基本。
- Cognitoのログ取得手順:CloudTrailとユーザーアクティビティログでサインインを監査する:IDプールの操作をCloudTrailで記録するときの扱い。