- 1 1. 認証/アイデンティティの本番課題とAmazon Cognitoの全体像
- 2 2. User Pools基礎 — managed loginとサインアップ/サインイン
- 3 3. 認証強化 — passwordless/passkeys・MFA・フェデレーション
- 4 4. Identity Pools — AWS一時認証情報の発行
- 5 5. セキュリティ — threat protection・適応認証・Lambdaトリガー
- 6 6. 運用・コスト — 料金ティアとマルチテナント
- 7 7. 実戦統合パターン — SPA/モバイル/API Gateway/ALB
- 8 8. つまずきポイント・アンチパターン・まとめ
- 8.1 8.1 つまずきポイント — よくある7つの落とし穴
- 8.1.1 落とし穴1: classic Hosted UIのままpasskeys/passwordlessが使えない
- 8.1.2 落とし穴2: アプリクライアントのclient secretと認証フロー誤り
- 8.1.3 落とし穴3: トークン有効期限を長くしすぎてセキュリティ低下
- 8.1.4 落とし穴4: Identity PoolsとUser Poolsの役割混同
- 8.1.5 落とし穴5: ロールマッピング誤設定で過剰権限または認証失敗
- 8.1.6 落とし穴6: 旧ASFのままPlus未移行で割高
- 8.1.7 落とし穴7: MFA未強制による乗っ取りリスク
- 8.1.8 落とし穴8: リフレッシュトークンローテーション未設定で長期間漏洩リスク
- 8.2 8.2 アンチパターン → 正解
- 8.3 8.3 まとめ — Cognito本番運用Vol1の要点
- 8.4 8.4 関連記事
- 8.1 8.1 つまずきポイント — よくある7つの落とし穴
1. 認証/アイデンティティの本番課題とAmazon Cognitoの全体像

アプリケーションに認証機能を自前で実装しようとすると、パスワードハッシュとストレッチングから始まり、メール検証・MFA(多要素認証)・パスワードリセット・アカウントロックアウト・ブルートフォース対策・セッション管理・トークン有効期限設計・フェデレーション(SAML・OIDC・social login)・コンプライアンス対応まで、広範な実装と継続的なセキュリティアップデートが必要です。さらに本番規模では漏洩認証情報のリアルタイム検知やリスクベース認証まで求められ、セキュリティチームの常設メンテナンスコストは無視できません。
Amazon Cognito はこうしたカスタマー ID アクセス管理(CIAM)の課題をまるごとオフロードできる AWS のマネージドサービスです。2014 年のリリース以降も活発に機能追加が続き、2024〜2025 年には managed login(新ブランディング UI・passwordless/passkeys 対応)・Essentials/Plus 料金ティア・M2M client credentials GA など、本番運用に直結する更新が立て続けにリリースされています。
1-1. Cognito の 2 要素:User Pools と Identity Pools
Cognito は用途の異なる 2 つのコンポーネントを提供しています。混同しやすいため最初に整理します。
User Pools は「アプリのエンドユーザーを誰が誰であるか認証する」コンポーネントです。ユーザーディレクトリ・サインアップ/サインイン・パスワードポリシー・MFA・フェデレーション(SAML/OIDC/social)・managed login UI・トークン発行(ID トークン・アクセストークン・リフレッシュトークン)を一括管理します。発行するトークンは OIDC/OAuth 2.0 準拠で、API Gateway や ALB の認証アクションとネイティブに統合できます。
Identity Pools(フェデレーテッドアイデンティティ)は「認証済みの ID に対して AWS リソースへの一時的な認証情報を発行する」コンポーネントです。User Pools や外部 IdP(Google・SAML など)で認証された後、Identity Pools が AWS STS を通じて IAM ロールベースの一時認証情報(アクセスキー+シークレット+セッショントークン)を払い出します。モバイルアプリや SPA が DynamoDB・S3 へ直接アクセスするシナリオで使います。
2 コンポーネントは独立して利用でき、組み合わせることも可能です。「User Pools だけで API 認可まで完結させる(API Gateway JWT 検証)」ユースケースと「User Pools 認証 → Identity Pools で S3 直接アクセス」を切り分けて設計するのが本番の定石です。
User Pools が発行する ID トークン はユーザー属性(email・sub・カスタム属性など)を含む OIDC 準拠の JWT です。アクセストークン は API Gateway や ALB での認可チェックに使います。リフレッシュトークン は長期セッションの維持に使用し、有効期限内であれば再認証なしでアクセストークンを更新できます。トークン設計(有効期限・カスタムクレーム)は §6 で詳しく解説します。
1-2. IAM・IAM Identity Center・Cognito の使い分け
AWS 上でアイデンティティを扱うサービスは複数あり、混同すると誤った設計につながります。3 者の役割を整理します。
IAM(Identity and Access Management) は AWS リソースへのアクセスを認可するサービスです。IAM ユーザー・ロール・ポリシーで「誰が何の AWS API を呼べるか」を制御します。エンドユーザーの認証には使わず、アプリケーションや AWS サービス同士の認可に使います。
IAM Identity Center(旧 AWS SSO) は社内ワークフォース向けのシングルサインオン(SSO)基盤です。従業員が AWS Management Console・CLI・Slack・GitHub Actions などへシームレスにアクセスできます。外部の IdP(Active Directory・Okta・Azure AD など)と SCIM/SAML 連携してユーザーをプロビジョニングし、権限セット(Permission Set)で各 AWS アカウントの操作権限を一元管理します。社内ツールや開発者向けのアクセス管理はこちらが適しています。
Amazon Cognito(本記事) は アプリのエンドユーザー(顧客)認証 = CIAM のサービスです。外部に公開する Web アプリ・モバイルアプリ・API のサインアップ/サインインを担い、社員向けではなく不特定多数の顧客(Consumer)を対象とします。
| サービス | 認証対象 | 主な用途 |
|---|---|---|
| IAM | AWS サービス間 | リソース認可・ロール引き受け |
| IAM Identity Center | 社内ワークフォース | AWS Console/CLI への SSO・権限セット管理 |
| Amazon Cognito | アプリのエンドユーザー(顧客) | CIAM・サインアップ/サインイン・トークン発行 |
既存記事で解説している IAM Identity Center の権限セット/ABAC は社内 SSO の文脈です。本記事は 顧客向けアプリの認証基盤 として Cognito を取り上げます。
なお、Cognito Identity Pools は内部で sts:AssumeRoleWithWebIdentity を実行することで IAM と連携します。つまり Cognito・IAM Identity Center・IAM は別々に存在するのではなく、用途に応じて互いに連携する設計が可能です。
1-3. Cognito を選ぶべきシナリオ
以下のような要件がある場合、Cognito は有力な選択肢です。
- B2C/B2B SaaS アプリで 不特定多数のユーザー登録・ログイン が必要
- Google・Apple・社内 SAML IdP などの ソーシャル/フェデレーション連携
- SMS/TOTP MFA・passkeys(WebAuthn) を手間なく有効化したい
- Amplify や API Gateway・ALB と AWS ネイティブ統合 でトークン検証を実装したい
- MAU(月間アクティブユーザー) ベースのスケーラブルな従量課金を採用したい
- フィッシング耐性のある passkeys(2024 年 11 月 GA) や passwordless ログインを提供したい
- マイクロサービス間の M2M(client_credentials)認証 を OAuth 2.0 準拠で実装したい
逆に、社員のみが使う内部ツールのログインには IAM Identity Center の方が適しています。規模・セキュリティ要件・開発リソースを照らし合わせて選択してください。
スタートアップから大企業まで、Cognito の MAU ベース従量課金はユーザー数が少ない初期フェーズから大規模になるまで一貫して使えるコスト構造です。
1-4. 本記事の対象読者と Vol1 の構成
本記事は以下の読者を想定しています。
- AWS で Web アプリ・モバイルアプリを開発・運用するエンジニア
- 自前実装の認証システムを Cognito へ移行しようとしているチーム
- passkeys・passwordless・threat protection など 2024〜2025 年の新機能を本番に取り込みたい方
- 料金ティア(Essentials/Plus)とコスト設計を整理したい方
Vol1(本記事)では、User Pools の基礎から managed login・認証強化(passkeys/MFA/フェデレーション)・Identity Pools・セキュリティ(threat protection)・M2M・Lambda トリガー・運用・コスト・統合パターン・アンチパターンまでを一気通貫で解説します。
1-5. 最新動向(2024〜2025 年)
Cognito は近年アップデートが活発です。本記事執筆時点(2025 年)の主要アップデートを整理します。
managed login(2024 年) — 新しいログイン UI(第二世代)。ブランディングエディタで企業ロゴ・カラーをカスタマイズ可能。passkeys/passwordless は managed login のみ対応しており、classic Hosted UI(第一世代)では利用できません。
passwordless/passkeys(2024 年 11 月 GA) — WebAuthn/FIDO2 ベースの passkeys と email OTP・SMS OTP。公開鍵暗号を使うため認証情報がサーバーに残らず、フィッシング攻撃への耐性が高い認証方式です。managed login 環境であれば追加の実装コストなく有効化できます。
Essentials/Plus 料金ティア(2025 年 3 月) — 旧 Lite ティアを再設計。Essentials はマネージドログイン・passwordless・トークンカスタマイズを含む標準ティア。Plus は Essentials に threat protection(旧 Advanced Security Features)を追加した上位ティアです。旧 ASF 利用者は Plus へ移行すると最大 60% のコスト削減が期待できます。
M2M client credentials GA — OAuth 2.0 client_credentials grant によるサービス間認証が一般提供。マイクロサービスや Lambda 間の認可に活用できます。詳細は §6 で解説します。
これらの最新仕様は今後も変更される可能性があります。本番採用前に AWS 公式ドキュメントで最新の仕様を確認してください。
1-6. Cognito の設計上の特性と本番運用上の注意点
Cognito を本番で使う前に、いくつかの設計特性を把握しておくことが重要です。
User Pool は不変設定が多い — User Pool 作成後に変更できない設定(サインインエイリアスの種類・ユーザー属性の一部など)があります。本番環境へ移行する前に、テスト環境でサインイン方式と属性設計を確定させてください。誤って作成した User Pool はユーザーデータを移行する手間が発生します。
リージョンの選択 — User Pool はリージョンサービスです。アプリのユーザーが多く在住するリージョンへ作成することでトークン発行のレイテンシを最小化できます。グローバルアプリでは複数リージョンの User Pool とトークン検証を組み合わせた設計も検討します。
サービスクォータ — デフォルトのサービスクォータに以下のような制限があります(申請で引き上げ可能)。本番規模へ達する前に Quota を申請してください。
| 項目 | デフォルトクォータ |
|---|---|
| User Pool 数(リージョン/アカウント) | 1,000 |
| サインイン API のスロットリング | 120 RPS(初回リクエスト) |
| カスタム属性数 | 50 |
| アプリクライアント数 | 1,000/User Pool |
マネージドサービスとしての責任分担 — Cognito はインフラ管理・スケーリング・パッチ適用を AWS が担います。アプリ開発チームは User Pool 設定・アプリクライアント管理・Lambda トリガーの実装・料金モニタリングに集中できます。障害時の RCA(根本原因分析)は AWS CloudWatch メトリクスと認証イベントログをもとに行います。
既存の Cognito 記事との棲み分け — 本記事は汎用的な本番運用のベストプラクティスを扱います。Cognito と mTLS を組み合わせた特殊な API 保護や、Salesforce との具体的な SAML 連携手順については、既存記事への参照誘導に留めています。
FIPS 140-3 と コンプライアンス対応 — Cognito は SOC 1/2/3・PCI DSS・ISO 27001 などの主要なコンプライアンスプログラムに対応しています。医療分野(HIPAA)の場合は Business Associate Agreement(BAA)の締結が必要です。コンプライアンス要件を確認した上でティアと機能を選定してください。Plus ティアの threat protection が提供するリスク評価ログは、監査対応の証跡としても活用できます。
- User Pools基礎 + managed login(新UI)/classic Hosted UI(§2)
- 認証強化 — passwordless/passkeys/MFA + SAML/OIDC/socialフェデレーション(§3)
- Identity Pools — AWS一時認証情報の発行とロールマッピング(§4)
- セキュリティ — threat protection/リスクベース適応認証/Lambdaトリガー(§5)
- 運用・コスト(ティア)と統合パターン(SPA/モバイル/API Gateway/ALB)(§6・§7)
- Amazon Cognito — アプリのエンドユーザー(顧客)認証=CIAM(本記事)
- IAM Identity Center — 社内ワークフォースのSSO・権限セット(既存記事)
- IAM — AWSリソースへの認可。User Pools=認証、Identity Pools=AWS一時認証情報
- 既存のCognito+mTLS/Salesforce連携(特定事例)は本記事のスコープ外として参照誘導
社内ワークフォースのSSOはこちら(IAM Identity Center 権限セット/ABAC)
2. User Pools基礎 — managed loginとサインアップ/サインイン

2.1 User Poolsとは — ユーザーディレクトリ+認証+トークン発行
Amazon Cognito User Pools は、アプリケーションのエンドユーザー(顧客)認証を担うマネージドコンポーネントです。ユーザーディレクトリ・サインアップ/サインインUI・OIDC/OAuth2.0準拠のトークン発行・フェデレーション(外部IdP連携)・メール/SMS通知・グループ管理など、アプリ認証基盤に必要な機能をまとめて提供します。
開発チームが自前でパスワードハッシュ・MFA・アカウントロック・トークン署名を実装する必要はありません。User Poolsがこれらを担い、アプリはOIDC/OAuth2.0フローでトークンを受け取るだけで済みます。
User Poolsが提供する主な機能
| カテゴリ | 機能 |
|---|---|
| ユーザーディレクトリ | サインアップ・パスワード管理・属性(標準/カスタム)・グループ |
| 認証UI | managed login(第2世代) / classic Hosted UI(第1世代) |
| プロトコル | OIDC/OAuth2.0。authorization code + PKCE を標準サポート |
| トークン発行 | IDトークン・アクセストークン・リフレッシュトークン(JWT署名済み) |
| 通知 | 確認メール/SMS・パスワードリセット・MFAコード送信 |
| フェデレーション | SAML2.0 / OIDC / social IdP(Google/Apple/Facebook) |
| アプリクライアント | public(SPA/モバイル) / confidential(サーバーサイド)の2種別 |
2.2 managed login(第2世代)とclassic Hosted UI — 世代の違いと移行判断
managed login — 2024-11 GAの新UI
managed loginはCognito User Poolsが提供するホスト型認証UIの第2世代です。2024年11月にGA(一般提供)となり、classic Hosted UI(第1世代)の後継として位置づけられています。
managed loginの主な特徴
- ブランディングエディタ搭載: Cognitoコンソールでロゴ・背景色・フォント・ボタンデザインを変更可能です。CSSカスタマイズにも対応しています。
- passwordless/passkeys対応: email OTP・SMS OTP・passkeys(WebAuthn/FIDO)はmanaged loginでのみ利用可能です。classic Hosted UIへの追加予定はありません。
- 継続的な機能追加: 新しい認証オプションはすべてmanaged loginに追加されます。classic Hosted UIへの新機能追加は終了しています。
- Essentials/Plusティア連動: passwordless等の一部機能はEssentialsティア以上が必要です。
classic Hosted UI — 第1世代(レガシー)
classic Hosted UIは引き続き利用可能ですが、新機能(passkeys/passwordless)は追加されません。既存アプリケーションとの互換性維持には使用できますが、新規構築ではmanaged loginを選択することが推奨されています。
managed login vs classic Hosted UIの比較
| 項目 | managed login | classic Hosted UI |
|---|---|---|
| passkeys(WebAuthn/FIDO) | 対応 | 非対応 |
| email/SMS OTP(passwordless) | 対応 | 非対応 |
| ブランディングエディタ | 搭載 | 限定的CSS変更のみ |
| 新機能追加 | 継続中 | 終了 |
| Essentialsティア以上の要否 | 一部機能で必要 | 不要 |
managed loginへの移行チェックリスト
既存のclassic Hosted UI利用者がmanaged loginへ移行する際の確認事項を示します。
- アプリクライアント設定: アプリクライアントで「Managed login pages」を有効化します。
- コールバックURL: 既存のリダイレクトURIはそのまま使用可能です。変更不要です。
- UIカスタマイズの再設定: classic Hosted UIのCSSカスタマイズはmanaged loginのブランディングエディタで再設定します。
- passwordless有効化: managed loginを有効化した後、User Pool設定で「Passwordless sign-in」を有効にします。EssentialsティアへのアップグレードをAWSコンソールで確認してください。
2.3 サインアップフロー
User Poolsのサインアップフローは次の順序で進みます。
[1] アプリ → /oauth2/authorize (response_type=code, code_challenge, state)
[2] managed loginページ → ユーザーがメールアドレス/パスワードを入力
[3] Cognito → 確認コード(verification code)をメール/SMSで送信
[4] ユーザーがコードを入力 → 属性検証完了 → アカウント有効化
[5] 認証コード(code)発行 → リダイレクトでアプリへ返却
[6] アプリ → POST /oauth2/token (code, code_verifier)
→ IDトークン / アクセストークン / リフレッシュトークン発行
サインアップ設計のポイント
- セルフサービスサインアップ: デフォルトで有効です。管理者のみがユーザーを作成する構成(
adminCreateUser)に変更できます。B2B SaaSでは管理者招待フローを採用するケースが多いです。 - 属性検証: emailとphone_numberは確認コードで検証します。「自動検証」を有効にするとLambdaトリガーなしでCognitoが検証メールを自動送信します。
- パスワードポリシー: 最低文字数・記号/数字/大文字小文字の要求をUser Pool設定でカスタマイズできます。本番環境では最低12文字以上を推奨します。
- サインインエイリアス: メールアドレス・電話番号・preferred_usernameのいずれかでサインインを許可します。User Pool作成後は変更不可のため、初期設計で確定させてください。
2.4 サインインフロー — authorization code + PKCE
managed loginでのサインインはOAuth2.0 authorization code flow + PKCEが標準です。トークンをURLに露出させないため、implicit flowより安全性が高くなっています。
[1] アプリ(SPA/モバイル) → GET /oauth2/authorize
?response_type=code
&client_id={appClientId}
&redirect_uri=https://app.example.com/callback
&scope=openid email profile
&state={csrfToken}
&code_challenge={BASE64URL(SHA256(code_verifier))}
&code_challenge_method=S256
[2] managed login → ユーザー認証完了
→ https://app.example.com/callback?code={authCode}&state={csrfToken}
[3] アプリ → POST /oauth2/token
grant_type=authorization_code
&code={authCode}
&client_id={appClientId}
&redirect_uri=https://app.example.com/callback
&code_verifier={code_verifier}
→ {"id_token": "eyJ...", "access_token": "eyJ...",
"refresh_token": "eyJ...", "expires_in": 3600}
フロー選択の指針
| フロー | 用途 | 注意点 |
|---|---|---|
| authorization code + PKCE | SPA/モバイル(public client) — 推奨 | PKCE必須。code_verifierは毎回生成 |
| authorization code + secret | サーバーサイド(confidential client) | client secretはサーバー側のみで管理 |
| implicit flow | 非推奨(廃止方向) | トークンがURLに露出するリスクあり |
| client credentials | M2M(サービス間認証) | グラントはアプリクライアント単位 |
2.5 属性・グループとロールマッピング
属性の種別
User Poolsはユーザー属性を2種類サポートしています。
- 標準属性: OIDC Core仕様に基づくフィールド(email/name/phone_number/birthdate等)。User Pool作成後は変更不可の固定セットです。
- カスタム属性:
custom:プレフィックスで定義する独自属性(例:custom:tenant_id,custom:plan)。最大50個まで定義可能で、文字列・数値・日時型を選択できます。一度作成した属性はUser Pool削除まで変更できないため、型選択は慎重に行ってください。
グループとトークンクレーム
User Poolsのグループ機能を使うとユーザーを論理グループに所属させられます。認証後のトークンには cognito:groups クレームでグループ名が含まれます。
{
"sub": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"cognito:groups": ["admin", "premium"],
"email": "user@example.com",
"iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxxxx",
"token_use": "id"
}
Identity Poolsと連携する場合、グループには cognito:roles と cognito:preferred_role で直接IAMロールのARNを紐づけることが可能です。グループ優先度を設定して複数グループ所属時の優先ロールも制御できます。
2.6 トークン種別・有効期限・ローテーション
User Poolsは認証成功時に3種類のJWTを発行します。それぞれ用途が異なり、混同するとセキュリティ問題や認証エラーの原因になります。
トークン種別の比較
| トークン | 用途 | デフォルト有効期限 | 設定範囲 |
|---|---|---|---|
| IDトークン | ユーザー情報の参照。フロントエンドでの本人確認 | 1時間 | 5分〜24時間 |
| アクセストークン | API認可(Authorization: Bearer)。スコープによる制御 | 1時間 | 5分〜24時間 |
| リフレッシュトークン | 新規トークン取得(refresh_tokenグラント) | 30日 | 1時間〜10年 |
設計の注意点
- IDトークンはユーザー情報取得のためのトークンです。API Gatewayのオーソライザーなど下流サービスへの認可にはアクセストークンを使用してください(詳細は§8のアンチパターンを参照)。
- アクセストークン・IDトークンの有効期限は短めに設定し、リフレッシュトークンによるサイレント更新で利便性を維持します。
- リフレッシュトークンの有効期限は業務要件に合わせて設定しますが、セキュリティ要件が厳しいシステムでは短く設定し、ローテーションを必ず有効化してください。
リフレッシュトークンローテーション
リフレッシュトークンは /oauth2/token (grant_type=refresh_token) でアクセストークンを更新する際に使用します。Cognitoはトークン使用時に新しいリフレッシュトークンを発行し、古いトークンを無効化します。漏洩したリフレッシュトークンが使用された場合、同じトークンを再利用しようとした正規ユーザーの更新が失敗するため、漏洩を検知するサインとなります。
2.7 JWT検証パターン(iss/aud/exp確認)
Cognito発行のJWTを検証する際は次のクレームを確認します。署名検証だけでなくクレームの値の検証も必須です。
JWKsエンドポイントと検証ロジック(Python例)
import jwt
import requests
from functools import lru_cache
REGION = "ap-northeast-1"
USER_POOL_ID = "ap-northeast-1_xxxxxxxx"
ISSUER = f"https://cognito-idp.{REGION}.amazonaws.com/{USER_POOL_ID}"
@lru_cache(maxsize=1)
def get_jwks():
url = f"{ISSUER}/.well-known/jwks.json"
return {k["kid"]: k for k in requests.get(url).json()["keys"]}
def verify_access_token(token: str) -> dict:
header = jwt.get_unverified_header(token)
keys = get_jwks()
if header["kid"] not in keys:
get_jwks.cache_clear()
keys = get_jwks()
pub = jwt.algorithms.RSAAlgorithm.from_jwk(keys[header["kid"]])
return jwt.decode(
token, pub, algorithms=["RS256"],
options={"verify_aud": False}, issuer=ISSUER,
)
検証必須クレーム一覧
| クレーム | IDトークン | アクセストークン | 検証内容 |
|---|---|---|---|
iss | 必須 | 必須 | https://cognito-idp.{region}.amazonaws.com/{userPoolId} と一致 |
aud | 必須 | 不要 | アプリクライアントIDと一致 |
client_id | 不要 | 必須 | アプリクライアントIDと一致 |
exp | 必須 | 必須 | 現在時刻より未来であること |
token_use | 必須 | 必須 | "id" または "access" と一致 |
JWKsエンドポイントはキャッシュして再利用することでリクエストごとの取得コストを削減できます。kid不一致時はキャッシュをクリアして再取得するロジックを必ず実装してください。Cognitoはキーローテーションを実施する場合があります。古いkidのトークンは有効期限切れ前にロールオーバーされます。
- ユーザーディレクトリ+サインアップ/サインイン+トークン発行(ID/アクセス/リフレッシュ・OIDC準拠)
- managed login(新UI・passwordless/passkeys対応)とclassic Hosted UI(第一世代)の2モード
- アプリクライアント(public/confidential)・OAuth2.0フロー(authorization code+PKCE推奨)・カスタムスコープ
- 標準/カスタム属性・サインインエイリアス・ドメイン設定
3. 認証強化 — passwordless/passkeys・MFA・フェデレーション

3-1. passwordless認証 — パスワード不要のサインイン
Cognitoのpasswordless認証は2024年11月にGA(一般提供)となりました。managed loginのみで使用可能で、classic Hosted UIではpasswordless・passkeysを利用できません。新規実装では最初からmanaged loginを選択することを推奨します。
passwordlessで使用できる認証方式は以下の2種類です。
email OTP(メールワンタイムパスワード)
ユーザーがメールアドレスを入力すると、Cognitoが6桁のOTPをメールで送信します。ユーザーはパスワードなしでOTPのみを入力してサインインを完了させます。OTPの有効期間はデフォルト3分で、有効期限内に入力が必要です。
passwordless email OTPを有効化するには、アプリクライアントの認証フローにALLOW_USER_AUTHを設定します。USER_AUTHフローがpasswordless・passkeys認証の基盤となるフローです。
resource "aws_cognito_user_pool_client" "app" {
user_pool_id = aws_cognito_user_pool.main.id
name= "app-client"
explicit_auth_flows = [
"ALLOW_USER_AUTH", # passwordless/passkeys有効化
"ALLOW_REFRESH_TOKEN_AUTH",
]
}
USER_AUTHフローではクライアントがPREFERRED_CHALLENGEパラメータで認証方式を指定でき、CognitoがOTPチャレンジを発行します。アプリのUIでは「パスワードなしでメールでサインイン」ボタンを配置するとユーザー体験が向上します。
SMS OTP
SMS OTPもmanaged loginでサポートされています。ユーザーが電話番号を入力すると、CognitoがAmazon SNS経由で6桁のOTPをSMS送信します。SMS OTPを本番環境で使用する場合は、Amazon SNSのSMSサンドボックスを解除し、送信先の電話番号を制限なく利用できる状態としてください。SMS費用はAmazon SNSの料金に従い、送信先の国・地域によって異なります。
passwordless SMS OTPとSMS MFA(§3-3)は異なる機能です。SMS OTPはサインインの主認証として機能し、SMS MFAはパスワード認証後の2段階目として機能します。
3-2. passkeys(WebAuthn/FIDO2) — フィッシング耐性の強い認証
passkeysはWebAuthn(FIDO2)規格に基づく認証方式で、公開鍵暗号方式を使用するためフィッシング攻撃に対して本質的な耐性があります。CognitoのPasskeys対応は2024年11月にmanaged loginでGA対応しました。
passkeysの動作原理
- 登録(Registration): ユーザーのデバイス(ブラウザ・スマートフォン)が公開鍵/秘密鍵ペアを生成し、公開鍵のみをCognitoに登録します。秘密鍵はデバイス内・クラウドパスワードマネージャーで保管されます
- 認証(Authentication): Cognitoがランダムなチャレンジを発行し、デバイスが秘密鍵でチャレンジを署名してCognitoに返却します。Cognitoが登録済みの公開鍵で署名を検証し、認証を完了します
秘密鍵はデバイスを離れないため、フィッシングサイトに誘導されてもPasskeyの認証情報は漏洩しません。これはフィッシング耐性(Phishing-Resistant)という、従来のパスワード方式やSMS OTPにはない特性です。
対応デバイス・ブラウザ
| プラットフォーム | 認証方式 | 備考 |
|---|---|---|
| macOS Safari/Chrome | Touch ID・パスワードマネージャー | macOS 13+推奨 |
| iOS 16+ | Face ID / Touch ID | iCloud Keychainで同期可能 |
| Android 9+ | 指紋 / Face unlock | Googleパスワードマネージャーで同期可能 |
| Windows 11 | Windows Hello(PIN/顔/指紋) | Microsoft Authenticatorでも可 |
| 1Password・Bitwarden | クロスプラットフォーム | ブラウザ拡張経由 |
managed loginとpasskeysの統合
managed loginがWebAuthn APIを処理するため、アプリ側でWebAuthn APIを直接実装する必要はありません。アプリクライアントにALLOW_USER_AUTHを設定するだけで、managed loginのUIにPasskeysサインインボタンが表示されます。
Passkeysはサインインの主認証(passwordless passkeys)としても、パスワード後のMFAファクタ(§3-3)としても使用可能です。
3-3. MFA — 多要素認証の種類と強制ポリシー
MFA(多要素認証)はパスワード認証後の2段階目として、セキュリティを強化します。CognitoはTOTP・SMS MFA・WebAuthn(passkeys)の3種類のMFAファクタをサポートしています。
TOTP(タイムベースワンタイムパスワード)
Google Authenticator・Microsoft Authenticatorなどのスマートフォンアプリを使用します。アプリがQRコードをスキャンしてシークレットを保存し、30秒ごとに更新される6桁のコードで認証します。TOTPはオフライン環境でも使用でき、SMS費用が発生しないためコスト面でも優れています。
セキュリティ要件が高い場合は、SMS MFAよりTOTPを推奨します。SMS MFAはSIMスワッピング(SIMジャッキング)攻撃に対して脆弱な面があります。
SMS MFA
ユーザーの登録済み電話番号にSMSで6桁のコードを送信します。TOTPアプリの追加設定が不要なため、シンプルな操作性を実現できます。ただし、前述のSIMスワッピングリスクには留意してください。
WebAuthn(passkeys)MFA
パスワード認証後のMFAとしてWebAuthn(passkeys)を使用できます。パスワード+passkeysの2要素認証によりセキュリティを強化します。
MFA設定
resource "aws_cognito_user_pool" "main" {
name = "production-pool"
mfa_configuration = "ON" # OFF / OPTIONAL / ON
software_token_mfa_configuration {
enabled = true # TOTP有効化
}
sms_configuration {
external_id = var.sns_external_id
sns_caller_arn = aws_iam_role.cognito_sms_role.arn
}
}
mfa_configurationのONは全ユーザーにMFAを必須化します。OPTIONALはユーザーが任意で設定できます。機密情報を扱うB2Bアプリや社内ツールではONを選択し、全ユーザーにMFAを強制することを推奨します。
本番でのMFA強制設計のポイント
- 新規ユーザー: サインアップ後、初回サインイン時にMFA設定を強制するフローを実装します。
Pre-token generationLambdaトリガーでMFA未設定ユーザーのトークンをブロックする方法もあります - 管理者ユーザー:
adminSetUserMFAPreferenceAPIで管理者ユーザーのMFAを必須化できます - threat protectionとの組合せ: Plus ティアのthreat protection(§5)はリスクスコアが高いサインインに追加のMFAを要求します。OPTIONAL設定でも高リスク時にMFAを強制するリスクベース適応認証を実現できます
3-4. ソーシャルフェデレーション — Google/Facebook/Apple/Amazon
Cognitoはソーシャルプロバイダー(Google・Facebook・Apple・Amazon)との連携をマネージドでサポートしています。ユーザーは既存のソーシャルアカウントでサインインでき、Cognitoがフェデレーションを仲介してアプリに標準的なOIDCトークンを発行します。
Googleフェデレーションの設定例
まずGoogle Cloud ConsoleでOAuth 2.0クライアントを作成し、クライアントIDとクライアントシークレットを取得します。CognitoのコールバックURL(https://<ドメイン>.auth.<リージョン>.amazoncognito.com/oauth2/idpresponse)をGoogleの承認済みリダイレクトURIに追加します。
resource "aws_cognito_identity_provider" "google" {
user_pool_id = aws_cognito_user_pool.main.id
provider_name = "Google"
provider_type = "Google"
provider_details = {
client_id = var.google_client_id
client_secret = var.google_client_secret
authorize_scopes = "email profile openid"
}
attribute_mapping = {
email = "email"
given_name = "given_name"
family_name = "family_name"
picture = "picture"
username = "sub"
}
}
attribute_mappingでGoogleのクレームをCognitoのユーザー属性にマッピングします。usernameにsub(GoogleのユーザーID)をマッピングすることで、Cognitoのユーザー名がGoogle_<sub>という形式になります。
managed loginページでは、有効化したソーシャルプロバイダーのボタンが自動的に表示されます。ユーザーが「Googleでサインイン」ボタンをクリックすると、Cognitoがそのプロバイダーに自動リダイレクトします。
Appleサインインの注意点
AppleはOIDCをベースにした独自実装を持つため、他のプロバイダーと異なる点があります。Apple Developer Programへの登録・Service IDの作成・秘密鍵の生成が必要です。またAppleはclient_secretを動的に生成する必要があります(JWTを使用)。
resource "aws_cognito_identity_provider" "apple" {
user_pool_id = aws_cognito_user_pool.main.id
provider_name = "SignInWithApple"
provider_type = "SignInWithApple"
provider_details = {
client_id = var.apple_service_id
team_id = var.apple_team_id
key_id = var.apple_key_id
private_key= var.apple_private_key
authorize_scopes = "email name"
}
attribute_mapping = {
email = "email"
username = "sub"
}
}
3-5. エンタープライズフェデレーション — SAML 2.0 / OIDC IdP
社内の既存IdP(Active Directory・Okta・Azure AD・Keycloak等)との連携にはSAML 2.0またはOIDCフェデレーションを使用します。CognitoがサービスプロバイダーとしてIdPにSAML/OIDCリクエストを送り、認証結果を受け取ります。
SAML 2.0フェデレーション(Okta連携例)
OktaのApplicationでSAML 2.0アプリを作成し、メタデータURLをCognitoに登録するだけで設定できます。
resource "aws_cognito_identity_provider" "okta_saml" {
user_pool_id = aws_cognito_user_pool.main.id
provider_name = "OktaSAML"
provider_type = "SAML"
provider_details = {
MetadataURL= "https://company.okta.com/app/<app_id>/sso/saml/metadata"
IDPSignout = "true"
RequestSigningAlgorithm= "rsa-sha256"
}
attribute_mapping = {
email = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
given_name = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
family_name = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"
}
}
SAML属性のクレーム名はXMLの名前空間を含む長い文字列になります。IdPが出力するSAMLアサーションを確認し、attribute_mappingを正確に設定してください。
OIDC IdPフェデレーション(Keycloak連携例)
OIDC準拠のIdPではSAMLより設定がシンプルです。oidc_issuerを指定するとOpenID Connect Discovery(/.well-known/openid-configuration)からエンドポイント情報を自動取得します。
resource "aws_cognito_identity_provider" "keycloak_oidc" {
user_pool_id = aws_cognito_user_pool.main.id
provider_name = "KeycloakOIDC"
provider_type = "OIDC"
provider_details = {
client_id = var.keycloak_client_id
client_secret = var.keycloak_client_secret
oidc_issuer= "https://keycloak.company.com/realms/myapp"
authorize_scopes = "openid email profile"
attributes_request_method = "GET"
}
attribute_mapping = {
email= "email"
given_name = "given_name"
username= "sub"
}
}
フェデレーション本番設計の要点
JITプロビジョニング(Just-In-Time Provisioning)はフェデレーション初回サインイン時にCognitoのユーザーディレクトリへ自動登録する仕組みです。Pre-sign-up Lambdaトリガーでプロビジョニング時のカスタムロジック(許可ドメインチェック・グループ割り当て等)を追加できます。
複数IdPを混在させる場合は、アカウントリンキングの設計が必要です。同一メールアドレスを持つSAMLユーザーとGoogleユーザーを同一Cognitoユーザーに紐づけたい場合はadminLinkProviderForUser APIを使用します。IdP側での属性更新はCognitoに自動同期されないため、Pre-token generationトリガーで最新属性を毎回反映させる実装が一般的です。
- passwordless(2024-11 GA・managed loginのみ) — passkeys(WebAuthn/FIDO・フィッシング耐性)/email OTP/SMS OTP
- MFA — SMS/TOTP/passkey。本番ではMFA強制ポリシーを設計
- フェデレーション — SAML2.0/OIDC/social IdP。メールドメインベースのIdP自動ルーティング
- IdP属性マッピングでユーザー属性を連携
4. Identity Pools — AWS一時認証情報の発行

4.1 Identity Poolsの役割とUser Poolsとの関係
Amazon Cognitoは2つの独立したコンポーネントで構成されます。User Poolsがエンドユーザーの認証(サインアップ/サインイン/トークン発行)を担うのに対し、Identity Pools(フェデレーテッドアイデンティティ)はAWSサービスへの一時認証情報(IAM認証情報)を発行する役割を担います。この2つは独立しており、それぞれ単独でも、組み合わせても利用できます。
Identity Poolsの目的を一言で表すと「認証済みの外部アイデンティティをIAMロールにマッピングし、STSから一時認証情報を取得させる仕組み」です。アプリがDynamoDBやS3などのAWSサービスに直接アクセスする際、IAMユーザーの長期認証情報を埋め込む代わりに、Identity Poolsを通じて短命な一時認証情報を安全に付与できます。
User Poolsとの役割分担を整理すると次のようになります。
| 機能 | User Pools | Identity Pools |
|---|---|---|
| 主な目的 | エンドユーザー認証・トークン発行 | AWS一時認証情報の発行 |
| 出力 | JWTトークン(ID/アクセス/リフレッシュ) | AWS一時認証情報(STS) |
| 認可対象 | アプリのAPI/リソース | AWSサービス(S3/DynamoDB等) |
| 依存性 | 独立 | 外部IdP/User Poolsのトークンを入力とする |
Identity PoolsはUser Pools以外のIdPも受け入れることができます。Google、Facebook、SAML 2.0プロバイダー、OIDCOP、さらにカスタム開発者認証プロバイダーを利用した認証済みIDも、Identity Poolsを通じてAWS一時認証情報を取得できます。
4.2 認証フロー — STSへの委任メカニズム
Identity Poolsを使った一時認証情報の取得フローは以下のステップで進みます。
Step 1: 認証の完了
アプリはCognito User Pools(またはGoogle/Facebook等の外部IdP)で認証し、IDトークン(JWT)を取得します。User Poolsの場合はGetIdAPIに先立ちID/アクセストークンを取得します。
Step 2: Identity Pool IDの取得
アプリはCognito Identity PoolsのGetId APIを呼び出し、IDトークンをプレゼンテーションします。Identity Poolsは受け取ったトークンをIdPに照合してアイデンティティを検証し、一意のIdentity IDを返します。Identity IDはユーザーとIdPの組み合わせに対してプールスコープで永続します。
Step 3: 一時認証情報の取得
アプリはGetCredentialsForIdentity APIを呼び出します。Identity Poolsは設定されたロールマッピングルールに従って適切なIAMロールを選択し、内部でsts:AssumeRoleWithWebIdentityを実行して一時認証情報(アクセスキー/シークレットキー/セッショントークン)を返します。
Step 4: AWSサービスへの直接アクセス
アプリは取得した一時認証情報を使い、AWS SDKを通じてDynamoDBやS3などに直接アクセスします。一時認証情報のデフォルト有効期限は1時間で、期限切れ前にGetCredentialsForIdentityを再呼び出しして更新します。
sequenceDiagram
participant App as アプリ
participant UP as User Pools
participant IP as Identity Pools
participant STS as AWS STS
participant S3 as S3
App->>UP: サインイン
UP-->>App: IDトークン(JWT)
App->>IP: GetId(IDトークン)
IP->>UP: トークン検証
UP-->>IP: 検証OK
IP-->>App: Identity ID
App->>IP: GetCredentialsForIdentity
IP->>STS: AssumeRoleWithWebIdentity(ロールARN)
STS-->>IP: 一時認証情報(有効期限1h)
IP-->>App: 一時認証情報
App->>S3: PutObject(一時認証情報使用)
S3-->>App: 200 OK
STSの詳細な仕組みやAssumeRoleWithWebIdentityの前提条件については、IAM/STS専門の解説記事を参照してください。本節ではIdentity Pools固有のロールマッピング設計に焦点を当てます。
4.3 サポートされるIdPとフェデレーション
Identity Poolsは次のIdPから発行された認証情報を受け入れます。
Amazon Cognito User Pools
最も一般的な構成です。User PoolsのIDトークンをそのままIdentity Poolsに渡せます。User PoolsとIdentity Poolsを組み合わせることで、認証(User Pools)とAWS認可(Identity Pools)の責務を明確に分離できます。
ソーシャルIdP
Google、Facebook、Login with Amazonをサポートします。それぞれのIDトークンをIdentity PoolsのGetId APIに渡すだけで利用できます。ソーシャルIdPを利用する場合、User Poolsを介さずに直接Identity PoolsとフェデレーションするSimplified Flowと、User Poolsをハブとして統合するパターンの2つが選択できます。
SAML 2.0プロバイダー
SAMLアサーションを持つユーザーもIdentity Poolsに統合できます。主に企業の既存IdP(Okta、Azure ADなど)のユーザーにAWS一時認証情報を付与するユースケースに使われます。
OpenID Connect(OIDC)プロバイダー
任意のOIDC互換IdPをサポートします。カスタムOIDCサーバーを構築している場合も統合できます。
カスタム開発者認証GetOpenIdTokenForDeveloperIdentity APIを使うと、自社の認証バックエンドがアイデンティティを検証し、Cognito Identity Poolsに代わってトークンを発行できます。既存の認証システムをCognitoに移行せず、段階的に統合したい場合に有効です。
4.4 ロールマッピング — 認証済みロールとゲストロール
Identity Poolsでは最低2つのIAMロールを設定します。
認証済みロール(Authenticated Role)
IdPで認証したユーザーに付与されるデフォルトロールです。cognito-identity.amazonaws.comを信頼するIAMロールを作成し、Identity Poolsのコンソールで指定します。認証済みユーザー全員に同じロールを付与するか、ロールマッピングルールで細かく出し分けるかを選択します。
未認証ロール(Unauthenticated Role / ゲストロール)
ゲストアクセスを有効にした場合のみ使われます。IdPでの認証なしに一時認証情報を取得できますが、ロールのIAMポリシーは最小権限に絞る必要があります。詳細は次の節で説明します。
ロールマッピングの種類
Identity Poolsのロールマッピングには3つのモードがあります。
| モード | 概要 | 適用場面 |
|---|---|---|
| Default | 認証済み/未認証の2ロールのみ | シンプルな構成 |
| Rules | トークンクレームベースで複数ロールを選択 | グループ/テナント別権限出し分け |
| Token | IdPがロールを直接アサート(SAML/カスタム) | 既存IdPのロール情報を活用 |
Rulesモードのクレームベースロールマッピング
Rulesモードでは、IDトークンの特定クレームの値に応じてIAMロールを切り替えます。たとえばCognito User Poolsのグループ(cognito:groups)にAdminが含まれる場合はAdminロール、Memberが含まれる場合はMemberロールを付与する設定が可能です。
{
"Rules": [
{
"Claim": "cognito:groups",
"MatchType": "Contains",
"Value": "Admin",
"RoleARN": "arn:aws:iam::123456789012:role/CognitoAdminRole"
},
{
"Claim": "cognito:groups",
"MatchType": "Contains",
"Value": "Member",
"RoleARN": "arn:aws:iam::123456789012:role/CognitoMemberRole"
}
],
"RoleResolutionStrategy": "Deny"
}
RoleResolutionStrategyをDenyにすると、どのルールにもマッチしないユーザーのリクエストが拒否されます。UseDefaultにするとデフォルトの認証済みロールが割り当てられます。本番環境では原則Denyを推奨します。
4.5 ゲストアクセス(未認証アイデンティティ)の設計
Identity Poolsはゲストアクセスを有効化すると、IdPでの認証なしに一時認証情報を発行できます。ゲストユーザーにも固有のIdentity IDが割り当てられ、後で認証した場合は同じIDへ統合(マージ)されます。
代表的なユースケース
– S3への匿名アップロード(ユーザーが登録前にファイルをアップロードし、後でアカウントに紐付ける)
– DynamoDBの公開読み取り専用データへのアクセス
– アプリ初回起動時のオフボーディングコンテンツ取得
ゲストロールのIAMポリシー設計
ゲストロールには最小権限を厳守します。特定のS3バケットプレフィックスやDynamoDBのGetItemのみに限定し、書き込みを許可する場合はcognito-identity:identityId条件キーでユーザー固有のパスのみに制限します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject"],
"Resource": "arn:aws:s3:::my-app-uploads/guests/${cognito-identity.amazonaws.com:sub}/*"
}
]
}
${cognito-identity.amazonaws.com:sub}はポリシー変数で、実行時にユーザーのIdentity IDに展開されます。これによりゲストユーザーは自分のIdentity IDプレフィックス以下にのみ書き込めます。
ゲストアクセスを有効にする場合は、レート制限とコスト試算が重要です。悪意あるクライアントがGetCredentialsForIdentityを連続呼び出しすることでSTS一時認証情報を大量取得するリスクがあります。アプリレイヤーでの呼び出し制限と、IAMロールのsts:RoleSessionDurationで有効期限を短くすることを検討してください。
4.6 User Pools + Identity Poolsの組み合わせパターン
最も一般的かつ推奨される構成は、User PoolsとIdentity Poolsを組み合わせたパターンです。このパターンでは次の責務分担が明確になります。
- User Pools: エンドユーザーの認証(サインイン)、JWTトークン発行、MFA、フェデレーション
- Identity Pools: User PoolsのIDトークンを受け取り、IAMロールを経由してAWS一時認証情報を発行
- IAMロール/ポリシー: AWSサービスへの実際のアクセス制御
典型的な実装パターン
SPA(シングルページアプリケーション)の場合、Amplify Authがこの全体フローを抽象化してくれます。Auth.signIn()でUser Poolsの認証を完了し、Auth.currentCredentials()でIdentity Poolsから一時認証情報を取得できます。内部ではGetId→GetCredentialsForIdentityが自動で呼ばれます。
モバイルアプリの場合は、AWS SDKのCognito Identity Providerクライアントを使って同様のフローを実装します。iOSはAWS SDK for Swift、AndroidはAWS SDK for Kotlinが対応しています。
Identity Poolsを使わない選択肢
すべてのAWSアクセスをバックエンド経由とする設計では、Identity Poolsは不要です。クライアントがAPI Gateway → Lambda → AWSサービスの経路のみでアクセスする場合、Lambdaが必要なAWSサービスにアクセスする実行ロールを持てば足ります。クライアントから直接AWSサービスにアクセスする要件がある場合にIdentity Poolsを検討します。
4.7 IAMポリシー設計 — cognito-identity:subとセッションタグ
Identity Poolsを使ったIAMポリシー設計のポイントは、ユーザーのIdentity IDをポリシー条件として利用することです。
cognito-identity.amazonaws.com:sub 条件キー
認証済みユーザーがSTSから取得した一時認証情報のセッションには、cognito-identity.amazonaws.com:subというコンテキストキーが含まれます。これをIAMポリシーのCondition要素で使うと、ユーザーごとのデータ分離を実現できます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:DeleteItem"],
"Resource": "arn:aws:s3:::my-app-table",
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": ["${cognito-identity.amazonaws.com:sub}"]
}
}
}
]
}
このポリシーでは、DynamoDBのLeadingKeyが自分のIdentity IDである行にのみアクセスを許可します。一つのDynamoDBテーブルで多数のユーザーデータを管理しながら、ユーザーが互いのデータにアクセスできない設計が実現します。
属性ベースアクセス制御(ABAC)とセッションタグ
Identity PoolsはUser Poolsのカスタム属性やグループをセッションタグとしてSTSセッションに引き渡すことができます。これによりIAMポリシーでaws:PrincipalTag条件を使い、よりきめ細かい制御が可能です。
たとえば、User Poolsのカスタム属性custom:tenantIdをセッションタグとして設定し、S3オブジェクトキーのプレフィックスをテナントIDで分離するマルチテナント設計が実現できます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::multi-tenant-bucket/${aws:PrincipalTag/tenantId}/*"
}
]
}
セッションタグのマッピング設定はIdentity Poolsのコンソールの「Attributes for access control」セクションで行います。User Poolsのカスタム属性名とセッションタグのキー名を対応付けます。
IAMロールの信頼ポリシー
Identity Poolsから呼び出されるIAMロールには、次の形式の信頼ポリシーが必要です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
cognito-identity.amazonaws.com:audにはIdentity Pool IDを指定します。これにより、特定のIdentity Poolからの委任のみを受け入れる安全な信頼関係が設定できます。ゲストロールの場合はamr条件をunauthenticatedに変更します。
4.8 設計チェックポイント
本番環境でIdentity Poolsを導入する前に確認すべき点をまとめます。
- ゲストアクセスの要否: 不要な場合は無効化し、攻撃対象を減らす
- ロールマッピング戦略: Rulesモードを使う場合は
Deny戦略でデフォルト漏洩を防ぐ - 一時認証情報の有効期限: デフォルト1時間。機密性の高いアプリでは15〜30分に短縮を検討
- Identity IDの永続性: ユーザーがIdPを変えると異なるIdentity IDが割り当てられる。マージ(
MergeDeveloperIdentities)が必要な場合はカスタム認証フローを設計 - エラーハンドリング: 一時認証情報の有効期限切れ(ExpiredTokenException)を検知してSDKが自動更新するかを確認。Amplify AuthはデフォルトでCognitoから自動更新するが、カスタム実装では明示的な処理が必要
- クロスリージョン: Identity PoolsとUser Pools(またはIdP)は同一リージョンに配置を推奨。異なるリージョンはレイテンシに影響する
- User Poolsとは独立 — 認証済みIDからAWS一時認証情報(STS/IAMロール)を発行
- 認証済み/未認証(ゲスト)ロール。クレームベースのロールマッピングで出し分け
- 属性ベースアクセス制御(Cognito属性→セッションタグ→IAMポリシー条件)
- DynamoDB/S3等へクライアントから直接アクセスする構成に活用
5. セキュリティ — threat protection・適応認証・Lambdaトリガー

セキュリティは本番Cognito運用の核心です。Cognitoは認証だけでなく、不正アクセス検知・リスクベース認証・トークンセキュリティ・監査ログの4層でアプリを保護します。本セクションでは各機能の設定ポイントと、Plusティアへのアップグレード判断基準を解説します。
5.1 料金ティアとthreat protection機能の対応
Cognitoは2025年3月からLite / Essentials / Plusの3ティア制に移行しました。セキュリティ機能の観点では、EssentialsとPlusの差異が重要です。
| 機能 | Lite | Essentials | Plus |
|---|---|---|---|
| 基本サインアップ/サインイン | ○ | ○ | ○ |
| managed login(新UI) | × | ○ | ○ |
| passwordless/passkeys | × | ○ | ○ |
| Pre token generation V2(トークンカスタマイズ) | × | ○ | ○ |
| パスワード再利用禁止 | × | ○ | ○ |
| threat protection(旧ASF) | × | × | ○ |
| 漏洩認証情報チェック | × | × | ○ |
| リスクベース適応認証 | × | × | ○ |
| 認証イベントログエクスポート | × | × | ○ |
| MAU課金単価(概算・最初の50,000MAU) | 無料 | $0.0055/MAU | $0.0105/MAU |
旧Advanced Security Features(ASF)を利用していた場合、Plusティアに移行することで最大60%のコスト削減が見込めます。旧ASFはPlusと同等機能を割高な価格で提供していたためです。MAUが多いほど単価が下がる段階課金なので、MAUを試算してからティアを選定してください。
5.2 threat protection — 漏洩認証情報とリスクベース適応認証
threat protectionはPlusティア専用の高度な不正アクセス対策機能です。User Poolの「Advanced security」→「Threat protection」から有効化します。
漏洩認証情報チェック(Compromised credentials)
ユーザーがサインアップやパスワード変更時に入力したパスワードを、既知の漏洩認証情報データベースと照合します。一致した場合はサインインをブロックするか、ユーザーに通知するかをポリシーで設定できます。
設定ポイントは以下のとおりです。
- 検知対象イベント: サインアップ・サインイン・パスワード変更
- アクション: Block(ブロック)またはNo action(通知のみ・ログ記録)
- 漏洩パスワードを強制変更させるフローと組み合わせると実効性が高まります
リスクベース適応認証(Adaptive authentication)
サインイン試行ごとにリスクスコアを算出し、スコアに応じてMFA要求・ブロック・通知などのアクションを動的に適用します。リスクスコアの算出には以下の要素が使われます。
- 新規デバイス・新規IPアドレスからのアクセス
- 短時間での多数の失敗試行(ブルートフォース検知)
- 地理的に異常なアクセス元の変化
- 既知の悪意あるIPアドレスリストとの照合
リスクレベルはLow / Medium / Highの3段階で評価され、各レベルにアクションを割り当てます。
| リスクレベル | 推奨アクション | 説明 |
|---|---|---|
| Low | Allow | 通常のサインインとして許可 |
| Medium | Optional MFA | 追加認証を求めてからサインイン |
| High | Block | サインインを拒否し、ユーザーにメール通知 |
Audit onlyモードを使うと実際のブロックは行わず、リスク評価ログのみを記録できます。本番適用前にこのモードで挙動を確認してから、ブロックポリシーを有効化するのが安全な進め方です。
認証イベントログ
Plusティアでは、サインインイベントの詳細ログ(デバイス・IP・リスクスコア・アクション)をCloudWatch Logsに出力できます。Athenaでクエリしてアクセス傾向を分析したり、Security Hubに集約してコンプライアンス監査に対応したりできます。ログの保持期間はCloudWatch Logsの設定で制御してください。
5.3 トークンセキュリティ — JWTの検証
Cognitoが発行するIDトークン・アクセストークンはJWT(JSON Web Token)形式です。バックエンドAPIはトークンを受け取るたびに必ず検証する必要があります。
JWKSエンドポイントによる署名検証
Cognitoは各User Pool固有のJWKSエンドポイントで公開鍵を提供しています。
https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
JWT検証ライブラリ(Python のpython-jose、Node.jsのjsonwebtoken等)はこのエンドポイントから公開鍵を取得し、トークンの署名を検証します。
検証すべき主なクレームは以下のとおりです。
| クレーム | 内容 | 検証ポイント |
|---|---|---|
iss | 発行者 | https://cognito-idp.{region}.amazonaws.com/{userPoolId} と一致するか |
aud | 対象クライアント | アプリクライアントIDと一致するか(IDトークン) |
exp | 有効期限(Unix時刻) | 現在時刻より未来であるか |
token_use | トークン種別 | idまたはaccessが期待値と一致するか |
| 署名 | RS256署名 | JWKSの公開鍵で正しく検証できるか |
アクセストークンのaudクレームにはUser Pool IDが入るため、IDトークンとは検証ロジックが異なる点に注意が必要です。ライブラリのドキュメントを確認して、トークン種別ごとに適切な検証オプションを設定してください。
トークン有効期限の設計
| トークン種別 | デフォルト有効期限 | 設定可能範囲 |
|---|---|---|
| IDトークン | 1時間 | 5分〜1日 |
| アクセストークン | 1時間 | 5分〜1日 |
| リフレッシュトークン | 30日 | 60分〜10年 |
本番ではアクセストークンは最短1時間、リフレッシュトークンは用途に応じて7〜30日が一般的です。永続ログインを提供するモバイルアプリでは長めに設定することがありますが、リフレッシュトークン漏洩時のリスクと天秤にかけて判断してください。有効期限を短くするほど漏洩時の影響を限定できます。
5.4 トークン失効・ローテーション
リフレッシュトークンのローテーション
User Poolのアプリクライアント設定でRefresh token rotationを有効にすると、リフレッシュトークンを使うたびに新しいリフレッシュトークンが発行され、古いものは無効化されます。これにより、リフレッシュトークンが漏洩した場合でも、正規ユーザーが先に使えば漏洩したトークンは無効になります。
同じリフレッシュトークンを短時間内に並行使用するケース(アプリの複数タブ等)に備えて、Refresh token reuse windowを数秒〜数分に設定しておくと二重使用エラーを防げます。
グローバルサインアウト
GlobalSignOut APIを呼び出すと、そのユーザーのすべてのリフレッシュトークンと現在のアクセストークンが即時失効します。デバイス紛失や不正アクセス検知時の緊急対処として活用できます。
import boto3
cognito = boto3.client('cognito-idp')
cognito.global_sign_out(AccessToken=access_token)
なお、JWTベースのIDトークン・アクセストークンはCognito側で失効させても、有効期限が切れるまでクライアント側で利用できます。完全な即時失効が必要な場合は、バックエンドでトークンブラックリストを管理するか、アクセストークンの有効期限を短く設定する設計が必要です。
AdminUserGlobalSignOut
管理者が特定ユーザーを強制サインアウトさせる場合はAdminUserGlobalSignOut APIを使います。インシデント対応や不正アカウントの一時停止と組み合わせて活用できます。
import boto3
cognito = boto3.client('cognito-idp')
cognito.admin_user_global_sign_out(
UserPoolId='ap-northeast-1_XXXXXXXXX',
Username='user@example.com'
)
5.5 WAFとの統合
Cognito User PoolにAWS WAFのWebACLを関連付けることで、managed loginや認証APIに対してbot対策・レートリミット・IP制限を適用できます。WAFをUser Poolに関連付けるには、WAFコンソールでWebACLを作成し、「Associated AWS resources」でCognito User Poolを選択します。
主なユースケースは以下のとおりです。
- レートリミット(Rate-based rule): 短時間の大量サインイン試行を自動ブロック
- AWS Managed Rules — Bot Control: AWS管理のbotシグネチャでスクレイパー・クローラーを排除
- IP Set rule: 許可IPリストまたはブロックIPリストで制御
- Geo match rule: 特定地域からのアクセスをブロック
WAFはCognito固有の機能ではなく、WAF側で別途課金されます。WAFルール設計の詳細は、AWS WAF関連記事を参照してください。
5.6 Secrets Manager連携 — Client Secret管理
CognitoのアプリクライアントにClient Secretを設定した場合(confidential client)、このシークレットをバックエンドで安全に管理する必要があります。Client SecretはAWS Secrets Managerに保存し、ランタイム時に取得するパターンを推奨します。
import boto3
import json
def get_cognito_client_secret(secret_name: str) -> str:
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response['SecretString'])['client_secret']
Client Secretを手動ローテーションする場合は、Cognito User Poolコンソールで新しいシークレットを生成し、Secrets Managerの値を更新してからアプリをデプロイします。ローテーション中に旧シークレットと新シークレットが共存するウィンドウでサービス断が発生しないよう、シークレットキャッシュとフォールバック取得を組み込む設計が必要です。
Secrets Managerのローテーション設計詳細は「AWS Secrets Manager 本番運用」を参照してください。
5.7 Lambdaトリガー — カスタム制御の設計
Cognitoはサインアップ・サインイン・トークン発行などのライフサイクルイベントにLambdaトリガーを挿入できます。Lambdaトリガーにより、Cognito標準機能では対応できないカスタムロジックを組み込めます。
主なトリガー種別は以下のとおりです。
| トリガー | タイミング | 主な用途 |
|---|---|---|
| Pre sign-up | サインアップ前 | ドメイン検証・招待制サインアップ制御 |
| Post confirmation | メール確認後 | DynamoDBへのユーザー初期データ書込み |
| Pre authentication | 認証前 | カスタムブロックリスト・メンテナンス中拒否 |
| Post authentication | 認証後 | ログイン履歴記録・不正検知システムへの連携 |
| Pre token generation V2 | トークン発行前 | カスタムクレーム追加・不要クレーム削除 |
| Migrate user | 既存システムからの透過移行 | 旧DBのユーザーをCognitoへ移行 |
| Custom message | メール/SMS送信前 | カスタムメールテンプレート適用 |
| Define/Create/Verify auth challenge | カスタム認証フロー | CAPTCHA・独自OTPフロー実装 |
Pre token generation V2 — トークンカスタマイズ
Pre token generation V2(Essentials以上)では、発行されるIDトークン・アクセストークンにカスタムクレームを追加したり、既存クレームを削除したりできます。
def lambda_handler(event, context):
event['response'] = {
'claimsAndScopeOverrideDetails': {
'idTokenGeneration': {
'claimsToAddOrOverride': {
'tenant_id': event['request']['userAttributes'].get('custom:tenant_id', ''),
'app_role': event['request']['userAttributes'].get('custom:app_role', 'user'),
},
'claimsToSuppress': ['address'],
},
'accessTokenGeneration': {
'claimsToAddOrOverride': {
'tenant_id': event['request']['userAttributes'].get('custom:tenant_id', ''),
},
'scopesToAdd': ['custom.read'],
},
}
}
return event
LambdaトリガーはCognitoと同期呼び出しのため、実行タイムアウトが認証レイテンシに直結します。Lambdaのタイムアウトは5秒以内を目安に設計し、外部APIコールが必要な場合はDynamoDBキャッシュやフォールバック値で対策してください。トリガーがタイムアウトするとユーザーのサインインが失敗します。
- threat protection(旧ASF・Plusティア) — 漏洩認証情報検知/リスクベース適応認証/異常サインイン検知/認証イベントログ出力
- リスクレベル別アクション — 許可/追加MFA要求/ブロック
- Lambdaトリガー — Pre/Post認証・Pre token generation(トークンカスタマイズ)・migrate user等
- WAF連携・監査ログでコンプライアンス対応
6. 運用・コスト — 料金ティアとマルチテナント
6-1. M2M 認証 — OAuth 2.0 client_credentials グラント
マイクロサービスや Lambda 関数同士が互いを呼び出す M2M(Machine-to-Machine) 認証では、ユーザーの介在しないサービス間トークンが必要です。Cognito User Pools は OAuth 2.0 client_credentials グラント で M2M をサポートしており、2024 年に一般提供(GA)されました。
仕組みと設定
クライアント(呼び出し側サービス)はアプリクライアントの client_id と client_secret を使って token エンドポイントにリクエストし、アクセストークン(JWT)を取得します。このトークンをリソースサーバー(呼び出される側の API)が検証することで、ユーザーなしの認可が成立します。
POST https://<domain>.auth.<region>.amazoncognito.com/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64(clientId:clientSecret)>
grant_type=client_credentials&scope=<resource-server-identifier>/<scope-name>
設定手順のポイントは以下のとおりです。
1. リソースサーバーとカスタムスコープの定義 — User Pool の「リソースサーバー」に API の識別子(例:https://api.example.com)を登録し、スコープ(例:read・write)を定義します。
2. アプリクライアントの設定 — 「クライアント認証情報グラント」を有効化し、許可するカスタムスコープを選択します。client_secret は必須です(public クライアントでは利用不可)。
3. トークン有効期限の設計 — client_credentials で発行するアクセストークンにはリフレッシュトークンが付きません。有効期限(最大 24 時間)を短く設定し、TTL 前に再取得するロジックをクライアント側に組み込みます。
Lambda でのトークンキャッシュ実装例
Lambda のグローバルスコープでキャッシュすることで、同一実行環境内でのトークン再取得を抑制できます。
import time
import urllib.request
import urllib.parse
import base64
import json
_token_cache = {"token": None, "expires_at": 0}
def get_m2m_token(client_id, client_secret, domain, scope):
now = time.time()
if _token_cache["token"] and now < _token_cache["expires_at"] - 60:
return _token_cache["token"]
auth = base64.b64encode(
f"{client_id}:{client_secret}".encode()
).decode()
body = urllib.parse.urlencode({
"grant_type": "client_credentials",
"scope": scope,
}).encode()
req = urllib.request.Request(
f"https://{domain}/oauth2/token",
data=body,
headers={
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": f"Basic {auth}",
},
)
with urllib.request.urlopen(req) as res:
data = json.load(res)
_token_cache["token"] = data["access_token"]
_token_cache["expires_at"] = now + data["expires_in"]
return _token_cache["token"]
M2M の料金に関する注意
M2M トークン発行はアプリクライアント単位で課金されます。Essentials ティアでは 1,000 トークン/月 まで無料で、超過分は別途課金されます。マイクロサービスのサービス数とトークン発行頻度(呼び出しレート × 有効期限)を掛け合わせて月次トークン数を試算し、超過課金をコスト計画に組み込んでください。
6-2. Lambda トリガーによるカスタマイズ
Cognito User Pools は 認証・サインアップ・トークン生成の各フェーズ で Lambda 関数を呼び出すトリガー機能を提供しています。標準機能では対応できない独自ロジックを組み込む際に活用します。
主要なトリガー種別
| トリガー | 呼び出しタイミング | 主なユースケース |
|---|---|---|
| Pre sign-up | サインアップ直前 | ドメイン制限・既存アカウントとの名寄せ |
| Post confirmation | メール/電話番号確認後 | DynamoDB へのユーザーレコード初期化 |
| Pre authentication | 認証前 | 追加の事前検証・ログ記録 |
| Post authentication | 認証後 | ログイン履歴の外部連携 |
| Pre token generation | トークン発行前 | カスタムクレームの追加・スコープの書き換え |
| Migrate user | 既存 DB 移行 | 旧認証システムからの透過移行 |
| Custom message | メール/SMS 送信前 | 認証コードメッセージのカスタマイズ |
Pre token generation でカスタムクレームを追加する
Pre token generation トリガーは、ID トークンやアクセストークンにカスタムクレームを追加するために特によく使われます。アクセストークンへのカスタムクレーム追加(V2 トリガー)は Essentials ティア以上 で利用できます。Lite ティアでは ID トークンのみです。
def handler(event, context):
user_sub = event["request"]["userAttributes"]["sub"]
tenant_id = lookup_tenant(user_sub) # 独自実装
event["response"]["claimsOverrideDetails"] = {
"claimsToAddOrOverride": {
"tenant_id": tenant_id,
"custom:role": "admin",
},
"claimsToSuppress": [],
}
return event
トリガー実装時の注意点
Lambda は 5 秒以内に応答 しないと認証フロー全体が失敗します。DynamoDB などへのアクセスが必要な場合は、同一リージョンに Lambda と Cognito を配置し、処理を最小化してください。ステートレスに実装し、グローバルスコープでのキャッシュ(接続の再利用など)はコールドスタートを考慮した上で活用します。
6-3. CloudWatch による監視設計
Cognito User Pools は CloudWatch メトリクス を自動で出力します。本番運用では以下のメトリクスをダッシュボードとアラームに組み込みます。
主要メトリクスと推奨アラーム
| メトリクス名 | 推奨アラーム閾値の例 |
|---|---|
SignInSuccesses | 直近 1h 平均の 50% 未満(急落検知) |
SignInThrottles | > 0 回/5 min(スロットリング発生) |
TokenRefreshSuccesses | 直近 1h 平均の 50% 未満(急落検知) |
FederationSuccesses | 直近 1h 平均の 50% 未満(IdP 連携失敗急増) |
ActiveUserAuthenticationCount | MAU 上限の 80% 超過アラート |
aws cloudwatch put-metric-alarm \
--alarm-name "cognito-sign-in-throttles" \
--namespace "AWS/Cognito" \
--metric-name "SignInThrottles" \
--dimensions Name=UserPool,Value=<UserPoolId> \
--statistic Sum \
--period 300 \
--evaluation-periods 1 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
--alarm-actions arn:aws:sns:<region>:<account>:ops-alert
MAU 使用量の監視
Essentials/Plus ティアは MAU(Monthly Active User)ベース課金 です。ActiveUserAuthenticationCount メトリクスの月次累計を監視し、料金試算に対して乖離がないかチェックします。AWS Budgets と組み合わせて月次コスト超過アラートを設定することを推奨します。
threat protection のログ活用(Plus ティア)
Plus ティアでは 認証イベントログ が CloudWatch Logs に出力されます(設定必須)。ログには IP アドレス・デバイスフィンガープリント・リスクレベル・実行したアクション(許可/MFA 要求/ブロック)が含まれ、Security Hub や SIEM(Amazon OpenSearch)への転送も可能です。
6-4. 料金ティア設計と MAU 試算
2025 年 3 月から Cognito User Pools は Lite / Essentials / Plus の 3 ティアに再編されました。ティア選定は本番運用コストに直結します。
ティア別機能比較
| 機能 | Lite | Essentials | Plus |
|---|---|---|---|
| 基本認証(パスワード/MFA) | ✓ | ✓ | ✓ |
| managed login(新 UI) | — | ✓ | ✓ |
| passwordless/passkeys | — | ✓ | ✓ |
| Pre token generation V2(アクセストークンカスタム) | — | ✓ | ✓ |
| パスワード再利用禁止 | — | ✓ | ✓ |
| threat protection(旧 ASF・適応認証/漏洩検知) | — | — | ✓ |
| M2M client credentials | ✓ | ✓ | ✓ |
Lite は無料枠(MAU 10,000 まで)で managed login・passwordless は非対応です。検証用途や社内限定ツールに向いています。Essentials は passkeys・managed login・アクセストークンカスタマイズが必要な本番の標準選択肢です。Plus は threat protection が必須の場合に選択します。旧 ASF 利用者は Plus への移行で最大 60% のコスト削減が見込まれます。
MAU 試算モデル
MAU は「当月中に 1 回以上認証した一意のユーザー数」です。DAU(日次アクティブユーザー)とは異なり、月内に何度ログインしても 1 MAU としてカウントします。
東京リージョンの概算単価(2025 年 3 月時点)は以下のとおりです。
| ティア | MAU 単価(50,001〜)の概算 | 月次コスト(MAU 10 万人) |
|---|---|---|
| Essentials | 約 $0.0055/MAU | 約 $275 |
| Plus | 約 $0.0195/MAU | 約 $975 |
上記はリージョンやボリュームディスカウントにより変動します。AWS 料金計算ツールで正確に試算してください。
マルチテナント設計
SaaS アプリでマルチテナント認証を実装する場合、以下の 2 パターンから選択します。
テナント別 User Pool — テナントごとに独立した User Pool を作成します。データ完全隔離・テナント単位のポリシー設定が可能ですが、User Pool 数の上限(デフォルト 1,000)と管理コストに注意が必要です。
単一 User Pool + グループ/カスタム属性 — 全テナントを 1 つの User Pool で管理し、Cognito グループや custom:tenantId 属性でテナントを識別します。運用は簡易ですが、テナント間のポリシー分離が限定的です。高いテナント隔離要件がある場合は前者を選択してください。
トークン有効期限とリフレッシュトークンローテーション
本番設計では以下のデフォルト有効期限を見直します。
| トークン種別 | デフォルト | 推奨範囲 |
|---|---|---|
| アクセストークン | 60 分 | 5〜60 分 |
| ID トークン | 60 分 | 5〜60 分 |
| リフレッシュトークン | 30 日 | 1〜7 日(セキュリティ要件に応じて) |
リフレッシュトークンのローテーション(使用ごとに新しいトークンを発行し旧トークンを無効化)を有効化することで、トークン漏洩時の被害を最小化できます。アプリ側は新旧トークンを両方保持し、ローテーション後に確実に旧トークンを破棄する実装が必要です。
- ★料金ティア(2025-03) — Lite/Essentials(managed login+passwordless)/Plus(+threat protection)。MAUベース課金
- 旧ASF利用者はPlusへ移行推奨(最大60%コスト削減)
- マルチテナント — テナント別User Pool vs 単一User Pool+グループ/カスタム属性(SaaS設計)
- トークン有効期限・リフレッシュトークンローテーション・CloudWatch監視。M2Mはアプリクライアント単位課金に注意
7. 実戦統合パターン — SPA/モバイル/API Gateway/ALB

7-1. SPA(React/Vue)統合 — Amplify Auth / PKCEフロー
シングルページアプリケーション(SPA)からCognito User Poolsを使用するパターンを解説します。SPAではブラウザに秘密鍵を安全に保存できないため、PKCEフロー(Proof Key for Code Exchange)を用いたAuthorization Code Flowを使用します。
AWS Amplify Authによる統合
AWS Amplify Authライブラリ(aws-amplify)を使用すると、Cognito統合の実装が大幅に簡略化されます。Amplifyがトークンの取得・保存・更新を自動的に処理します。
npm install aws-amplify
import { Amplify } from 'aws-amplify';
import { signIn, signOut, fetchAuthSession } from 'aws-amplify/auth';
Amplify.configure({
Auth: {
Cognito: {
userPoolId: 'ap-northeast-1_xxxxxxxxx',
userPoolClientId: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
loginWith: {
oauth: {
domain: 'myapp.auth.ap-northeast-1.amazoncognito.com',
scopes: ['openid', 'email', 'profile'],
redirectSignIn: ['https://myapp.example.com/callback'],
redirectSignOut: ['https://myapp.example.com/'],
responseType: 'code', // PKCEフロー
},
},
},
},
});
// サインイン
const { isSignedIn } = await signIn({ username: 'user@example.com', password: '***' });
// セッション取得(APIコール時のトークン取得)
const session = await fetchAuthSession();
const idToken = session.tokens?.idToken?.toString();
AmplifyはlocalStorageまたはsessionStorageでトークンを管理します。XSSリスクを軽減するため、アプリのCSPヘッダーを適切に設定してください。
managed login(ホスト型UI)によるPKCE統合
Amplifyライブラリを使用せず、managed loginを直接使用する場合はPKCEフローを手動実装します。
- code_verifier(ランダム文字列)とcode_challenge(SHA-256ハッシュ)を生成
- managed loginの認証URLにcode_challenge・response_type=codeを付けてリダイレクト
- ユーザー認証後、managed loginがcodeをコールバックURLに返却
- バックエンドでcode+code_verifierをCognito token endpointに送信してトークンを取得
managed loginはブランディングエディタでUIをカスタマイズでき、passwordless/passkeys・ソーシャルフェデレーションのボタンも自動的に表示されます。
API Gateway/Lambdaの構築はこちら(サーバーレス本番運用)
7-2. モバイル(iOS/Android)統合 — Amplify SDK / ネイティブSDK
モバイルアプリからCognitoを使用するパターンです。iOS(Swift/SwiftUI)とAndroid(Kotlin)の統合方法を解説します。
Amplify Auth for iOS(Swift)
import AWSCognitoAuthPlugin
import Amplify
try Amplify.add(plugin: AWSCognitoAuthPlugin())
try Amplify.configure()
// サインイン
let result = try await Amplify.Auth.signIn(
username: "user@example.com",
password: "myPassword"
)
// セッション取得(APIリクエスト時)
let session = try await Amplify.Auth.fetchAuthSession()
if let cognitoSession = session as? AuthCognitoTokensProvider {
let tokens = try cognitoSession.getCognitoTokens().get()
let idToken = tokens.idToken
}
Amplify Auth for Android(Kotlin)
// Application.onCreate で初期化
Amplify.addPlugin(AWSCognitoAuthPlugin())
Amplify.configure(applicationContext)
// サインイン(コルーチン)
val result = Amplify.Auth.signIn("user@example.com", "myPassword")
val session = Amplify.Auth.fetchAuthSession() as AWSCognitoAuthSession
val idToken = session.userPoolTokensResult.value?.idToken
ネイティブSDK(Cognito Identity Provider SDK)
Amplifyを使用せず、CognitoのネイティブSDK(AWS SDK for Swift・AWS SDK for Kotlin)を直接利用できます。AmplifyはモバイルUX向けの追加機能(オフライン支援・データストア)を提供しますが、認証のみが目的であればネイティブSDKの方がシンプルです。
モバイルでのSecure Token Storage
モバイルアプリでのトークン保存にはOSのキーチェーン(iOS: Keychain Services・Android: Android Keystore)を使用します。AmplifyのSDKはデフォルトでこれらのセキュアストレージを使用するため、追加実装は不要です。
biometrics認証との組み合わせも可能で、アプリ再起動時にFace ID/Touch IDでトークンのアンロックを要求する設計が一般的です。
7-3. API Gateway統合 — Cognito Authorizer / Lambda Authorizer比較
API GatewayとCognitoを統合し、APIエンドポイントを認証済みユーザーのみに制限するパターンです。
Cognito Authorizer(REST API)
REST APIのCognito Authorizerは、リクエストヘッダーのAuthorization(Bearerトークン)をCognito User Poolsで検証します。有効なIDトークンまたはアクセストークンを持つリクエストのみが通過します。
resource "aws_api_gateway_authorizer" "cognito" {
rest_api_id= aws_api_gateway_rest_api.main.id
name = "CognitoAuthorizer"
type = "COGNITO_USER_POOLS"
provider_arns = [aws_cognito_user_pool.main.arn]
identity_source = "method.request.header.Authorization"
}
resource "aws_api_gateway_method" "protected" {
rest_api_id= aws_api_gateway_rest_api.main.id
resource_id= aws_api_gateway_resource.api.id
http_method= "GET"
authorization = "COGNITO_USER_POOLS"
authorizer_id = aws_api_gateway_authorizer.cognito.id
}
Cognito Authorizerはトークン検証のみを行い、Lambdaバックエンドは認証済み前提でビジネスロジックに集中できます。検証はCognitoのJWKSエンドポイントで署名を確認します。
JWT Authorizer(HTTP API)
HTTP APIではよりシンプルなJWT Authorizerを使用します。
resource "aws_apigatewayv2_authorizer" "jwt" {
api_id = aws_apigatewayv2_api.main.id
authorizer_type = "JWT"
identity_sources = ["$request.header.Authorization"]
name = "CognitoJWT"
jwt_configuration {
audience = [aws_cognito_user_pool_client.app.id]
issuer= "https://cognito-idp.${var.aws_region}.amazonaws.com/${aws_cognito_user_pool.main.id}"
}
}
Cognito Authorizer vs Lambda Authorizer
| 比較項目 | Cognito Authorizer | Lambda Authorizer |
|---|---|---|
| 設定の複雑さ | 低(マネージド) | 高(Lambda実装が必要) |
| 柔軟性 | 低(トークン検証のみ) | 高(任意のロジック) |
| レイテンシ | 低(マネージド) | 高(Lambda cold start) |
| コスト | 低(API GW料金のみ) | 高(Lambda実行料金) |
| カスタムクレーム判定 | 不可(Cognitoクレームのみ) | 可 |
| 外部IdP対応 | Cognito連携IdPのみ | 任意のトークン検証 |
Cognito Authorizerはマネージドで設定が容易なため、Cognitoトークン検証だけで十分な場合に最適です。複雑な認可ロジック(クレームの組合せ判定・外部データベースとの照合等)を実装する場合はLambda Authorizerを使用します。
7-4. ALB統合 — OIDC認証アクションによる認証強制
Application Load Balancer(ALB)のOIDC認証アクションを使用すると、ALBがCognito User Poolsとの認証を処理し、認証済みユーザーのみバックエンドへのアクセスを許可します。バックエンドアプリ側の認証実装が不要となるため、既存アプリへの認証機能追加で特に有効です。
ALB認証アクションの動作
- 未認証ユーザーがALBにアクセス
- ALBがCognito managed loginにリダイレクト
- ユーザーがCognitoで認証
- Cognitoがトークンを発行し、ALBのコールバックURLに返却
- ALBがセッションCookieを発行し、バックエンドにリクエストを転送
- ALBがCognitoのユーザー情報(クレーム)をヘッダーで転送
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.main.arn
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn= aws_acm_certificate.main.arn
default_action {
type = "authenticate-cognito"
authenticate_cognito {
user_pool_arn = aws_cognito_user_pool.main.arn
user_pool_client_id = aws_cognito_user_pool_client.alb.id
user_pool_domain = aws_cognito_user_pool_domain.main.domain
on_unauthenticated_request = "authenticate"
session_cookie_name = "AWSELBAuthSessionCookie"
session_timeout= 3600
}
}
}
ALBのセッションCookieにより、認証後は再認証なしにバックエンドへアクセスできます。バックエンドはALBからのX-Amzn-Oidc-Dataヘッダーでユーザー情報を取得できます。
ALB用アプリクライアントの設定
ALBはCognito client secretが必要なconfidentialクライアントとして機能します。コールバックURLにALBのドメインを設定します。
resource "aws_cognito_user_pool_client" "alb" {
user_pool_id = aws_cognito_user_pool.main.id
name= "alb-client"
generate_secret = true
allowed_oauth_flows = ["code"]
allowed_oauth_scopes = ["openid", "email", "profile"]
callback_urls = [
"https://${aws_lb.main.dns_name}/oauth2/idpresponse",
]
}
7-5. IAM Identity Centerとの使い分け設計
Amazon CognitoとIAM Identity CenterはどちらもAWSのアイデンティティサービスですが、対象ユーザーと用途が根本的に異なります。設計段階で明確に区分することが重要です。
使い分けの基本原則
| 比較軸 | Amazon Cognito | IAM Identity Center |
|---|---|---|
| 対象ユーザー | アプリのエンドユーザー(顧客・一般ユーザー) | 社内ワークフォース(従業員・開発者) |
| 主な用途 | CIAM(カスタマーID管理)・アプリ認証 | AWS Management Console・AWS CLIのSSO |
| スケール | 数百万ユーザー対応(MAU課金) | 社内規模(ライセンス数) |
| フェデレーション | SAML/OIDC/ソーシャルIdP→Cognito | SAML/OIDC IdP→IAM Identity Center |
| アクセス先 | アプリのAPIやリソース | AWSアカウント・AWS Console・AWS CLI |
| Identity Poolsとの組合せ | エンドユーザーへのAWS一時認証情報付与 | 社内ユーザーのAWS権限セット管理 |
典型的なアーキテクチャの使い分け
BtoCアプリ(顧客向け): Cognitoで顧客のサインアップ/サインインを処理し、API Gateway + Cognito AuthorizerでAPI保護します。Identity PoolsでS3への直接アクセス権限を付与します。IAM Identity Centerは使用しません。
BtoBアプリ(社内ツール・業務システム): 従業員認証にIAM Identity Centerを使用してAWS ConsoleのSSOを実現します。社内システムへのログインが別途必要な場合は、CognitoにOIDC IdPとしてIAM Identity Centerを連携させる構成も可能です。
ハイブリッド構成(大企業向けSaaS): 顧客認証(CIAM)にCognito、開発者チームのAWSコンソールアクセスにIAM Identity Centerを並立させます。両者は独立したサービスで、通常は互いに依存しません。
IAM Identity CenterをCognitoのOIDC IdPとして使用
社内従業員がCognitoベースのアプリにSSOでアクセスするユースケースでは、IAM Identity Centerの外部アプリ機能を使ってCognitoにSAML/OIDCフェデレーションを構成できます。
ただし一般的なBtoCアプリでは、Cognito User PoolsのSAML/OIDC IdPにAzure ADやOktaを直接接続するケースが多く、IAM Identity Centerを経由する必要はありません。「社内従業員向けCognitoアプリ」という特殊なケースに限定した構成です。
社内ワークフォースのSSOはこちら(IAM Identity Center 権限セット/ABAC)
きめ細かい認可はこちら(Security Vol4 — Verified Permissions)
- SPA/モバイル — Amplify Auth/AWS SDKでUser Pools認証→トークン→APIアクセス
- API Gateway — Cognito authorizer(REST=User Pools authorizer / HTTP API=JWT authorizer)でトークン検証
- ALB — OIDC認証アクションでCognito認証を強制(アプリは認証済み前提)
- Identity Pools — フロントから直接AWSサービス(S3アップロード等)へアクセス
API Gateway/Lambdaの構築はこちら(サーバーレス本番運用)
きめ細かい認可はこちら(Security Vol4 — Verified Permissions)
8. つまずきポイント・アンチパターン・まとめ
8.1 つまずきポイント — よくある7つの落とし穴
落とし穴1: classic Hosted UIのままpasskeys/passwordlessが使えない
症状: managed loginに移行していないため、passwordless(email OTP)やpasskeys(WebAuthn)を有効化しようとするが設定項目が表示されない。
原因: passwordless/passkeysは managed login(第2世代)のみ対応しています。classic Hosted UIでは設定不可です。
対策:
1. アプリクライアントの「Managed login pages」を有効化する
2. User Pool設定で「Passwordless sign-in」を有効化する
3. Essentialsティア以上であることをAWSコンソールで確認する
落とし穴2: アプリクライアントのclient secretと認証フロー誤り
症状: SPAからCognito APIに直接リクエストを送ると認証エラーになる。またはclient_secretをフロントエンドコードに含めてしまいセキュリティ問題が発生する。
原因: SPAやモバイルアプリはpublic client(client secretなし)を使うべきです。client secretはサーバーサイドでのみ管理できる機密情報です。
対策:
– SPA/モバイル → public clientを使用し、client secretを生成しない
– authorization code + PKCEフローを必ず使用する
– サーバーサイドのみconfidential client(client secretあり)とする
落とし穴3: トークン有効期限を長くしすぎてセキュリティ低下
症状: アクセストークンの有効期限を24時間や7日間に設定している。トークンが漏洩した場合に長期間悪用されるリスクがある。
原因: 利便性優先でトークン有効期限を長く設定してしまうケースが多いです。
対策:
– アクセストークン: 最大1時間(デフォルト)が推奨
– リフレッシュトークンによるサイレント更新で利便性を維持
– 機密性の高いアプリでは15〜30分に短縮を検討する
落とし穴4: Identity PoolsとUser Poolsの役割混同
症状: User PoolsだけでS3やDynamoDBへ直接アクセスしようとするが、IAM権限が取得できない。
原因: User Poolsはエンドユーザー認証(JWT発行)のみを担当します。AWSサービスへの一時認証情報発行はIdentity Poolsの役割です。
対策:
– User Pools(認証) → IDトークン/アクセストークン取得
– Identity Pools(認可) → User PoolsのIDトークンをIdentity Poolsに渡してSTS一時認証情報を取得
– S3/DynamoDBへ直接アクセスする場合はIdentity Poolsを組み合わせる
落とし穴5: ロールマッピング誤設定で過剰権限または認証失敗
症状: Identity Poolsのロールマッピングで意図したロールが返らない。または全ユーザーが管理者ロールになってしまう。
原因: Identity Poolsのロールマッピングルールが正しく設定されていない。またはcognito:groupsクレームの値が一致していない。
対策:
– ロールマッピングの「Type」を「Token」または「Rules」で適切に選択する
– Token型: cognito:rolesクレームのロールARNを直接マッピング
– Rules型: クレームの値でロールを出し分ける(例: cognito:groups が “admin” → adminロール)
– RoleResolutionStrategyはDenyを設定して意図しないデフォルトロール付与を防ぐ
落とし穴6: 旧ASFのままPlus未移行で割高
症状: 旧Advanced Security Features(ASF)を有効にしているが、2025-03のティア移行後も継続している。料金が予想より高い。
原因: 2025年3月のティア変更でASFはPlusティアに統合されました。新しいティア体系での最適化が行われていないケースがあります。
対策:
– 必要な機能に応じてLite/Essentials/Plusティアを選択する
– threat protectionを活用する場合はPlusを維持するが、MAU数を最適化する
– Plusへ完全移行することで最大60%のコスト削減が見込める
落とし穴7: MFA未強制による乗っ取りリスク
症状: User PoolでMFAを「オプション」にしているが、エンドユーザーの大半がMFAを設定しておらず、フィッシング/クレデンシャルスタッフィング攻撃を受けやすい状態になっている。
原因: MFAを強制すると離脱率が上がるという懸念から「オプション」設定にするケースが多いです。
対策:
– 管理者・特権ユーザーアカウントはMFA強制必須
– エンドユーザーには適応認証(threat protection)で高リスクサインイン時にMFA要求
– passkeys(managed login必須)は生体認証でUXを損なわずにMFA強度を確保できる
落とし穴8: リフレッシュトークンローテーション未設定で長期間漏洩リスク
症状: アプリクライアントのリフレッシュトークンローテーションを有効化していない。リフレッシュトークンが窃取されても気づけない状態になっている。
原因: Cognitoのデフォルト設定ではリフレッシュトークンのローテーションが無効です。意識しないまま運用しているケースがあります。
対策:
– Cognitoコンソールの「アプリクライアント」→「認証フロー設定」で「Refresh token rotation」を有効化する
– RefreshTokenReuseWindow(秒)を設定して正規ユーザーの並行利用を許容する
– リフレッシュトークンの有効期限も業務要件に応じて設定する(デフォルト30日)
– GlobalSignOut APIを活用してデバイス紛失・不正アクセス時に即時失効できる運用体制を整える
なぜ重要か: ローテーションを有効化すると、漏洩したリフレッシュトークンが使用された時点で元のトークンが無効化されます。正規ユーザーが次回更新を試みた際に異常を検知できるため、インシデント対応の起点となります。
8.2 アンチパターン → 正解
| # | アンチパターン | 問題点 | 正解 |
|---|---|---|---|
| 1 | IDトークンをAPI認可に使う | IDトークンはユーザー情報取得用。API Gatewayのオーソライザーに渡すとaud/token_useの検証が複雑化し将来的なセキュリティリスクになる | アクセストークンをAPIアクセスに使用する。IDトークンはフロントエンドでのユーザー情報表示のみに使う |
| 2 | リフレッシュトークンをlocalStorageに保存 | XSS攻撃でトークンが窃取される。有効期限が長いため長期間悪用される | HttpOnly Cookieに保存する。JavaScriptからアクセス不可。SPAではBFFパターン(Backend For Frontend)でサーバーサイドにトークン保持する設計も有効 |
| 3 | マルチテナントでUser Poolを大量作成 | テナント数分のUser Poolを作成すると管理コストが爆発。ティア設定・監視・デプロイが複雑化する | 単一User Pool + グループ/カスタム属性でテナント分離する。custom:tenant_idでテナントを識別し、IAMポリシーの条件キーで分離する |
| 4 | classic Hosted UIでpasskeys未対応のまま運用 | 2024-11以降、passkeys/passwordlessはmanaged loginのみ対応。classic Hosted UIは新機能が追加されない | managed loginへ移行する。アプリクライアントで「Managed login pages」を有効化。UIカスタマイズはブランディングエディタで再設定する |
| 5 | サインアップ時に全属性を必須にする | 登録フォームが長すぎてCVRが低下。住所・生年月日など不要な属性も入力させてしまう | サインアップ時は最小限(email/password)のみ要求する。プロフィール情報はサインイン後の画面で段階的に収集(Progressive Profiling)する |
8.3 まとめ — Cognito本番運用Vol1の要点
本記事では、Amazon Cognito User Poolsの基礎から本番運用まで、以下の要点を解説しました。
User Pools — 基礎と設計
- User Poolsはエンドユーザー認証(CIAM)のコンポーネントです。AWSリソースへの一時認証情報発行はIdentity Poolsが担当します。
- managed login(第2世代)を採用することで、passkeys/passwordless対応・ブランディングカスタマイズ・最新認証フローを活用できます。
- SPA/モバイルはpublicクライアント、サーバーサイドはconfidentialクライアントとし、authorization code + PKCEフローを標準とします。
トークン設計
- アクセストークン(API認可用)とIDトークン(ユーザー情報用)を混同しないことが重要です。
- リフレッシュトークンのローテーションを有効化してセキュリティリスクを最小化します。
- JWT検証時はiss/aud(またはclient_id)/exp/token_useを必ず確認します。
セキュリティ
- MFAは管理者アカウントで強制し、エンドユーザーにはthreat protection(Plusティア)で適応認証を適用します。
- passkeys(managed login必須)でフィッシング耐性を確保しつつUXを維持できます。
コスト最適化
- 料金ティア(Lite/Essentials/Plus)をMAU試算で選定します。
- 旧ASFからPlusへの移行で最大60%コスト削減の可能性があります。
- M2M(client credentials)はアプリクライアント単位課金に注意してください。
Cognito vs IAM Identity Center vs IAM
| 用途 | サービス |
|---|---|
| アプリのエンドユーザー認証(CIAM) | Amazon Cognito |
| 社内ワークフォースのSSO | IAM Identity Center |
| AWSリソースへの認可 | IAM |
設計チェックリスト(本番前確認)
| チェック項目 | 確認内容 |
|---|---|
| managed login移行 | classic Hosted UIではなくmanaged loginを使用しているか |
| PKCEフロー | SPA/モバイルでauthorization code + PKCEを使用しているか |
| トークン有効期限 | アクセストークンは1時間以下に設定しているか |
| リフレッシュトークンローテーション | 有効化済みか |
| JWT検証 | iss/aud/exp/token_useをバックエンドで検証しているか |
| MFAポリシー | 管理者アカウントはMFA強制済みか |
| ロールマッピング | Identity PoolsのRoleResolutionStrategyはDenyか |
| ゲストアクセス | 不要なら無効化済みか |
| WAF設定 | User PoolにWebACLを関連付けているか |
| ティア確認 | 機能要件に合ったLite/Essentials/Plusを選択しているか |
Vol2では以下のトピックを深掘りします:
- passkeys/passwordlessの詳細設定とトラブルシューティング
- SAML2.0/OIDCフェデレーションの実装パターン
- threat protectionの詳細設定とインシデント対応
- Amplify Auth/API Gateway/ALBとの具体的な統合手順
- マルチリージョン対応とDR設計
8.4 関連記事
- Cognitoは2要素=User Pools(エンドユーザー認証)とIdentity Pools(AWS一時認証情報)。CIAMのマネージド基盤
- managed loginでpasswordless/passkeys/フェデレーション。threat protection(Plus)でリスクベース適応認証
- API Gateway authorizer/ALB OIDC/Amplify Authで統合。料金ティア(Lite/Essentials/Plus)をMAUで選定
- 顧客認証=Cognito、社内SSO=IAM Identity Center、リソース認可=IAMと使い分ける
関連: Cognito + mTLS で Salesforce連携APIを保護する実装例