Amazon Cognito認証本番運用Vol1|User Pools・passkeys・Identity Pools

目次

1. 認証/アイデンティティの本番課題とAmazon Cognitoの全体像

fig01: Amazon Cognito全体アーキテクチャ(User Pools=エンドユーザー認証/Identity Pools=AWS一時認証情報発行の2要素と、ワークフォース向けIAM Identity Center・リソース認可のIAMとの位置関係)
fig01: Cognito全体像 — User Pools/Identity PoolsとIAM/IAM Identity Centerの位置づけ

アプリケーションに認証機能を自前で実装しようとすると、パスワードハッシュとストレッチングから始まり、メール検証・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)を対象とします。

サービス認証対象主な用途
IAMAWS サービス間リソース認可・ロール引き受け
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 が提供するリスク評価ログは、監査対応の証跡としても活用できます。

本シリーズVol1が扱うトピック(Amazon Cognito)

  • 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)
Cognito / IAM Identity Center / IAM の使い分け・既存記事との棲み分け

  • 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とサインアップ/サインイン

fig02: Cognito User Pools認証フロー(サインアップ/サインイン→トークン発行(ID/アクセス/リフレッシュトークン)と、managed login新UI・classic Hosted UIの2モード、OAuth2.0/OIDCエンドポイント)
fig02: 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が提供する主な機能

カテゴリ機能
ユーザーディレクトリサインアップ・パスワード管理・属性(標準/カスタム)・グループ
認証UImanaged 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 loginclassic Hosted UI
passkeys(WebAuthn/FIDO)対応非対応
email/SMS OTP(passwordless)対応非対応
ブランディングエディタ搭載限定的CSS変更のみ
新機能追加継続中終了
Essentialsティア以上の要否一部機能で必要不要

managed loginへの移行チェックリスト

既存のclassic Hosted UI利用者がmanaged loginへ移行する際の確認事項を示します。

  1. アプリクライアント設定: アプリクライアントで「Managed login pages」を有効化します。
  2. コールバックURL: 既存のリダイレクトURIはそのまま使用可能です。変更不要です。
  3. UIカスタマイズの再設定: classic Hosted UIのCSSカスタマイズはmanaged loginのブランディングエディタで再設定します。
  4. 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 + PKCESPA/モバイル(public client) — 推奨PKCE必須。code_verifierは毎回生成
authorization code + secretサーバーサイド(confidential client)client secretはサーバー側のみで管理
implicit flow非推奨(廃止方向)トークンがURLに露出するリスクあり
client credentialsM2M(サービス間認証)グラントはアプリクライアント単位

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:rolescognito: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のトークンは有効期限切れ前にロールオーバーされます。

User Poolsの主要要素

  • ユーザーディレクトリ+サインアップ/サインイン+トークン発行(ID/アクセス/リフレッシュ・OIDC準拠)
  • managed login(新UI・passwordless/passkeys対応)とclassic Hosted UI(第一世代)の2モード
  • アプリクライアント(public/confidential)・OAuth2.0フロー(authorization code+PKCE推奨)・カスタムスコープ
  • 標準/カスタム属性・サインインエイリアス・ドメイン設定

3. 認証強化 — passwordless/passkeys・MFA・フェデレーション

fig03: Cognito認証強化フロー(passkeys(WebAuthn/FIDO)・email/SMS OTPのpasswordless、MFA、SAML/OIDC/socialフェデレーションのIdP選択とメールドメインベースの自動ルーティング)
fig03: 認証強化 — 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の動作原理

  1. 登録(Registration): ユーザーのデバイス(ブラウザ・スマートフォン)が公開鍵/秘密鍵ペアを生成し、公開鍵のみをCognitoに登録します。秘密鍵はデバイス内・クラウドパスワードマネージャーで保管されます
  2. 認証(Authentication): Cognitoがランダムなチャレンジを発行し、デバイスが秘密鍵でチャレンジを署名してCognitoに返却します。Cognitoが登録済みの公開鍵で署名を検証し、認証を完了します

秘密鍵はデバイスを離れないため、フィッシングサイトに誘導されてもPasskeyの認証情報は漏洩しません。これはフィッシング耐性(Phishing-Resistant)という、従来のパスワード方式やSMS OTPにはない特性です。

対応デバイス・ブラウザ

プラットフォーム認証方式備考
macOS Safari/ChromeTouch ID・パスワードマネージャーmacOS 13+推奨
iOS 16+Face ID / Touch IDiCloud Keychainで同期可能
Android 9+指紋 / Face unlockGoogleパスワードマネージャーで同期可能
Windows 11Windows 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_configurationONは全ユーザーにMFAを必須化します。OPTIONALはユーザーが任意で設定できます。機密情報を扱うB2Bアプリや社内ツールではONを選択し、全ユーザーにMFAを強制することを推奨します。

本番でのMFA強制設計のポイント

  • 新規ユーザー: サインアップ後、初回サインイン時にMFA設定を強制するフローを実装します。Pre-token generation LambdaトリガーでMFA未設定ユーザーのトークンをブロックする方法もあります
  • 管理者ユーザー: adminSetUserMFAPreference APIで管理者ユーザーの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のユーザー属性にマッピングします。usernamesub(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一時認証情報の発行

fig04: Cognito Identity Pools一時認証情報フロー(User Poolsや外部IdPの認証結果からIdentity Poolsがロールマッピングを経てSTS一時認証情報を発行し、DynamoDB/S3等のAWSサービスへ直接アクセスする構成)
fig04: 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 PoolsIdentity 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トークンクレームベースで複数ロールを選択グループ/テナント別権限出し分け
TokenIdPがロールを直接アサート(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"
}

RoleResolutionStrategyDenyにすると、どのルールにもマッチしないユーザーのリクエストが拒否されます。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)は同一リージョンに配置を推奨。異なるリージョンはレイテンシに影響する
Identity Poolsの要点

  • User Poolsとは独立 — 認証済みIDからAWS一時認証情報(STS/IAMロール)を発行
  • 認証済み/未認証(ゲスト)ロール。クレームベースのロールマッピングで出し分け
  • 属性ベースアクセス制御(Cognito属性→セッションタグ→IAMポリシー条件)
  • DynamoDB/S3等へクライアントから直接アクセスする構成に活用

5. セキュリティ — threat protection・適応認証・Lambdaトリガー

fig05: Cognito threat protectionとリスクベース適応認証のフロー(サインイン試行→リスク評価(漏洩認証情報/異常検知)→リスクレベル別アクション(許可/MFA要求/ブロック)とLambdaトリガーによるカスタム制御を示すMermaid図)
fig05: threat protection — リスクベース適応認証とLambdaトリガー(Mermaid)

セキュリティは本番Cognito運用の核心です。Cognitoは認証だけでなく、不正アクセス検知・リスクベース認証・トークンセキュリティ・監査ログの4層でアプリを保護します。本セクションでは各機能の設定ポイントと、Plusティアへのアップグレード判断基準を解説します。

5.1 料金ティアとthreat protection機能の対応

Cognitoは2025年3月からLite / Essentials / Plusの3ティア制に移行しました。セキュリティ機能の観点では、EssentialsとPlusの差異が重要です。

機能LiteEssentialsPlus
基本サインアップ/サインイン
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段階で評価され、各レベルにアクションを割り当てます。

リスクレベル推奨アクション説明
LowAllow通常のサインインとして許可
MediumOptional MFA追加認証を求めてからサインイン
HighBlockサインインを拒否し、ユーザーにメール通知

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)

  • 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_idclient_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)を登録し、スコープ(例:readwrite)を定義します。

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 連携失敗急増)
ActiveUserAuthenticationCountMAU 上限の 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 ティアに再編されました。ティア選定は本番運用コストに直結します。

ティア別機能比較

機能LiteEssentialsPlus
基本認証(パスワード/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

fig06: Cognito統合パターン(SPA/モバイルのAmplify Auth、API Gateway Cognito authorizer、ALB OIDC認証、AppSyncの各統合方式を要件別に選ぶMermaidフローチャート)
fig06: 統合パターン選定 — SPA/モバイル/API Gateway/ALBの統合方式(Mermaid)

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フローを手動実装します。

  1. code_verifier(ランダム文字列)とcode_challenge(SHA-256ハッシュ)を生成
  2. managed loginの認証URLにcode_challenge・response_type=codeを付けてリダイレクト
  3. ユーザー認証後、managed loginがcodeをコールバックURLに返却
  4. バックエンドで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 AuthorizerLambda 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認証アクションの動作

  1. 未認証ユーザーがALBにアクセス
  2. ALBがCognito managed loginにリダイレクト
  3. ユーザーがCognitoで認証
  4. Cognitoがトークンを発行し、ALBのコールバックURLに返却
  5. ALBがセッションCookieを発行し、バックエンドにリクエストを転送
  6. 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 CognitoIAM Identity Center
対象ユーザーアプリのエンドユーザー(顧客・一般ユーザー)社内ワークフォース(従業員・開発者)
主な用途CIAM(カスタマーID管理)・アプリ認証AWS Management Console・AWS CLIのSSO
スケール数百万ユーザー対応(MAU課金)社内規模(ライセンス数)
フェデレーションSAML/OIDC/ソーシャルIdP→CognitoSAML/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)

Cognito統合パターン早見

  • 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ロール)
RoleResolutionStrategyDenyを設定して意図しないデフォルトロール付与を防ぐ


落とし穴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 アンチパターン → 正解

#アンチパターン問題点正解
1IDトークンを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ポリシーの条件キーで分離する
4classic 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
社内ワークフォースのSSOIAM 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を保護する実装例