Cognito & STS — 認証認可・フェデレーション・トークン管理
Cognito User/Identity Pools、Lambda トリガー、STS AssumeRole、Confused Deputy対策を徹底解説
はじめに
Cognito と STS は AWS における認証・認可・トークン管理の中心的サービス。SCS-C03 では両者の連携パターン、制約、セキュリティ対策が頻出です。
本講では AWS の責任分界点を理解しながら、実装レベルの詳細設定を掘り下げます。
第1部:Amazon Cognito
1.1 Cognito の2大コンポーネント
| 側面 | User Pools | Identity Pools |
|---|---|---|
| 機能 | 認証(Authentication) | 認可(Authorization) |
| 役割 | ユーザーID・パスワード管理、トークン発行 | AWS リソースへのアクセス権限付与 |
| 出力 | ID Token / Access Token / Refresh Token | 一時的な AWS 認証情報 |
| 連携先 | アプリケーション、API Gateway | AWS サービス(S3, DynamoDB等) |
| スコープ | リージョナル | グローバル(リージョン指定なし) |
重要: User Pools だけでは AWS リソースにアクセスできない。Identity Pools と組み合わせて初めて完全な認証認可が成立します。
Cognito 認証フロー図
Loading diagram...
1.2 User Pools — 詳細設定
1.2.1 パスワードポリシー&アカウント復旧
User Pools 作成時に以下を設定します:
- パスワード最小文字数: 8~256文字(デフォルト8)
- 大文字必須、小文字必須、数字必須、特殊文字必須
- カスタムパスワードルール: Regex 対応
アカウント復旧方法:
- メール検証リンク(デフォルト24時間有効)
- SMS コード(デフォルト24時間有効)
- セルフサービスパスワードリセット可否
試験のポイント:
- パスワードリセットリンクの有効期限は設定不可(固定24時間)
- リセット時に既存トークンは無効化されます
1.2.2 MFA(多要素認証)
User Pools は3つの MFA 方式をサポート:
-
SMS(ショートメッセージ)
- Cognito が SQS 経由で SNS へ送信
- 設定: SNS IAM ロール必須
-
TOTP(Time-based One-Time Password)
- Google Authenticator など対応
- AWS が秘密鍵を保管
-
メール(Email)
- SES 経由でワンタイムコード送信
- 6桁、デフォルト24時間有効
MFAの強制方針:
- Optional: ユーザー選択可能
- Required: すべてのユーザーに必須
- Custom: リスク評価に基づき動的に要求(Advanced Security)
# AWS CLI でユーザーに MFA を強制
aws cognito-idp admin-set-user-mfa-preference \
--user-pool-id ap-northeast-1_xxxx \
--username john@example.com \
--sms-mfa-settings Enabled=true,PreferredMfa=true
1.2.3 Lambda トリガー — 8つの重要なポイント
User Pools は認証フロー内の8つのポイントで Lambda を実行できます:
| トリガー | 実行タイミング | 用途 |
|---|---|---|
| Pre Sign-up | サインアップ前 | メール確認スキップ、自動確認 |
| Pre Authentication | ログイン直前 | カスタム検証、ブロック条件 |
| Post Authentication | ログイン完了後 | ログ記録、ポイント加算 |
| Custom Message | メール/SMS送信前 | メッセージテンプレート変更 |
| Pre Token Generation | トークン発行直前 | カスタムクレーム追加、スコープ制御 |
| User Migration | User Migration フロー時 | 既存 DB からのマイグレーション |
| Post Confirmation | メール確認後 | 確認完了時の処理 |
| Custom Authflow Challenge | カスタム認証フロー | 多段階認証の実装 |
Pre Token Generation の実装例:
def lambda_handler(event, context):
"""
User Pools のトークン生成直前に実行。
カスタムスコープやグループ情報を ID Token に埋め込む。
"""
event['response']['claimsOverrideDetails'] = {
'claimsToAddOrOverride': {
'email_verified': 'true',
'custom:tenant_id': 'tenant-123',
'custom:department': 'engineering'
},
'claimsToSuppress': ['phone_number'],
'priorityOverride': 'GIVEN_CLAIMS',
}
return event
Lambda トリガーの制約(重要):
- 実行タイムアウト: 5秒(延長不可)
- 時間がかかる処理(外部 API 呼び出しなど)はできません
- エラーが発生すると認証フロー全体が失敗
- VPC 内の Lambda は起動が遅くなるため 5秒制限に注意
1.2.4 Advanced Security Features
User Pools に組み込まれた侵害対策機能:
-
適応型認証(Adaptive Authentication)
- IP アドレス、デバイス、位置情報を監視
- 異常なログイン試行を検出
- リスク評価に基づき MFA 要求
-
侵害された認証情報検出(Compromised Credentials Detection)
- AWS の脅威インテリジェンスとの連携
- パスワード漏洩データベースとマッチング
- 該当ユーザーにパスワード変更を強制
有効化方法:
aws cognito-idp update-user-pool \
--user-pool-id ap-northeast-1_xxxx \
--account-recovery-setting PriorityList=[{Name=verified_email,Priority=1},{Name=verified_phone_number,Priority=2}] \
--user-attribute-update-settings AttributesRequireVerificationBeforeUpdate=[email,phone_number]
1.2.5 ホストUI vs カスタムUI
| 要素 | ホストUI | カスタムUI |
|---|---|---|
| 構築時間 | 分単位 | 数日~数週間 |
| Cognito が提供 | ログイン・サインアップ・MFA フォーム | SDK のみ |
| ホスティング | Cognito マネージド(cognito-idp.xx.amazoncognito.com) | 自分で構築・ホスト |
| ドメイン設定 | カスタムドメイン対応(SSL/TLS 自動管理) | 自由 |
| セキュリティ | AWS マネージド | 自分で実装 |
| CSRF 対策 | 自動 | 手動実装必須 |
カスタムドメインの制約:
- 同じドメイン名は AWS 全体で一意(削除後も7日間は再使用不可)
- CloudFront を経由するため、SSL サーティフィケートは AWS が自動管理
- ACM 証明書の手動管理は不要
1.2.6 App Client 設定
User Pools ごとに複数の App Client を作成できます:
クライアント名: 自由
アプリケーションタイプ:
- Web(SPA/SSR)
- Native(iOS/Android)
- Desktop
認証フロー:
- ALLOW_USER_PASSWORD_AUTH: ユーザー名・パスワードで直接トークン取得可能(モバイルアプリに適している)
- ALLOW_USER_SRP_AUTH: パスワードを平文で送信しない(推奨)
- ALLOW_REFRESH_TOKEN_AUTH: Refresh Token でアクセストークン更新可能
- ALLOW_CUSTOM_AUTH: カスタム認証フロー利用
クライアントシークレット:
- Web アプリなら「シークレット生成」
- SPA(JavaScript)なら「シークレット生成しない」(フロント側に秘密情報を持たせない)
トークン有効期限:
- Refresh Token: 1日~10年
- Access Token: 5分~24時間
- ID Token: 5分~24時間
試験のポイント:
- SPA でシークレット有りを使うと、フロントエンドに秘密情報が露出する
- PKCE(Proof Key for Code Exchange)は OAuth 2.0 Authorization Code Flow で必須
1.3 Identity Pools — 詳細設定
User Pools でトークンを取得した後、そのトークンを使用して Identity Pools から AWS の一時認証情報 を取得します。
1.3.1 認証済み vs 未認証ロール
認証済みロール(Authenticated Role)
- User Pools / IdP のトークンで Identity を取得
- 該当ロールの権限で AWS リソースアクセス可能
未認証ロール(Unauthenticated Role)
- トークンなしで Identity を取得
- 限定的な読み取り権限(例: S3 バケットの public フォルダ)
実装例:
import boto3
import json
cognito_idp = boto3.client('cognito-idp', region_name='ap-northeast-1')
cognito_identity = boto3.client('cognito-identity', region_name='ap-northeast-1')
sts = boto3.client('sts', region_name='ap-northeast-1')
# ステップ1: User Pools からトークン取得
response = cognito_idp.admin_initiate_auth(
UserPoolId='ap-northeast-1_xxxx',
ClientId='clientid123',
AuthFlow='ADMIN_USER_PASSWORD_AUTH',
AuthParameters={
'USERNAME': 'john@example.com',
'PASSWORD': 'Password123!'
}
)
id_token = response['AuthenticationResult']['IdToken']
# ステップ2: Identity Pools から Identity ID 取得
identity_response = cognito_identity.get_id(
IdentityPoolId='ap-northeast-1:12345678-1234-1234-1234-123456789012',
Logins={
'cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxx:' + id_token
}
)
identity_id = identity_response['IdentityId']
# ステップ3: 一時認証情報を取得
credentials_response = cognito_identity.get_credentials_for_identity(
IdentityId=identity_id,
Logins={
'cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxx:' + id_token
}
)
# これで AWS リソースにアクセス可能
temporary_credentials = credentials_response['Credentials']
1.3.2 ロールマッピング — トークンベース vs ルールベース
Identity Pools は複数の IAM ロールを管理でき、どのロールを割り当てるかを制御できます:
| マッピング方式 | 制御方法 | ユースケース |
|---|---|---|
| トークンベース | ID Token のカスタムクレームで選択 | テナントごとのロール分離、部門別権限 |
| ルールベース | Cognito が提供する属性で選択 | IAM ロール数が多い場合、動的マッピング |
トークンベースマッピングの例:
{
"IdentityPoolId": "ap-northeast-1:xxxx",
"RoleMappingType": "Token",
"RulesConfiguration": null,
"RoleMapping": {
"ap-northeast-1_xxxx:client1": {
"RoleArn": "arn:aws:iam::123456789012:role/user-role",
"AmbiguousRoleResolution": "AuthenticatedRole"
}
}
}
ルールベースマッピングの例:
{
"IdentityPoolId": "ap-northeast-1:xxxx",
"RoleMappingType": "Rules",
"RulesConfiguration": {
"Rules": [
{
"Priority": 1,
"Rule": {
"Claim": "custom:department",
"MatchType": "Equals",
"Value": "engineering",
"RoleArn": "arn:aws:iam::123456789012:role/engineering-role"
}
},
{
"Priority": 2,
"Rule": {
"Claim": "custom:department",
"MatchType": "Equals",
"Value": "marketing",
"RoleArn": "arn:aws:iam::123456789012:role/marketing-role"
}
}
]
}
}
1.3.3 外部IdP連携(フェデレーション)
Identity Pools は以下の外部 IdP と統合可能:
- Cognito User Pools(同じ AWS アカウント)
- Facebook / Google / Apple / Amazon
- SAML プロバイダー(Okta, Salesforce, Active Directory 等)
- OpenID Connect(OIDC)プロバイダー
Google フェデレーションの設定例:
# Identity Pools に Google プロバイダーを追加
aws cognito-identity update-identity-pool \
--identity-pool-id "ap-northeast-1:xxxx" \
--identity-pool-name "MyPool" \
--supported-login-providers "accounts.google.com=123456789.apps.googleusercontent.com"
1.4 できないこと・制約
User Pools の制約
| 制約 | 詳細 |
|---|---|
| クォータ上限 | ユーザー数: 無制限、User Pools 数: リージョンあたり10個(拡張申請可) |
| パスワードリセットリンク有効期限 | 固定24時間(変更不可) |
| Lambda トリガーのタイムアウト | 5秒(延長不可) |
| カスタムドメイン一意性 | AWS 全体で一意、削除後7日間は再使用不可 |
| SMS 送信制限 | SNS で設定した制限に従う(デフォルト: 1秒あたり1件) |
| ホストUI のカスタマイズ | テンプレート機能で限定的に可能だが、完全なカスタマイズはできない |
| トークン署名アルゴリズム | RS256 固定(HMAC-SHA256 等への変更不可) |
Identity Pools の制約
| 制約 | 詳細 |
|---|---|
| IAM ロール切り替え遅延 | ロール変更後、既存の一時認証情報は変更前のロールで有効 |
| ロールマッピング最大数 | トークンベース: クレーム値によって上限あり |
| リージョン指定なし | Identity Pool はグローバルだが、関連する IAM ロールはリージョンごと |
1.5 ベストプラクティス
1. Advanced Security を常に有効化
aws cognito-idp update-user-pool \
--user-pool-id ap-northeast-1_xxxx \
--user-attribute-update-settings AttributesRequireVerificationBeforeUpdate=[email,phone_number] \
--account-recovery-setting PriorityList=[{Name=verified_email,Priority=1}]
理由: 侵害された認証情報の検出、適応型認証により、ブルートフォース攻撃やリスト型攻撃を防止できます。
2. Lambda トリガーでカスタムバリデーション
def pre_authentication_handler(event, context):
"""
ログイン直前に実行。
カスタムビジネスロジック(例: IP ホワイトリスト、デバイス登録確認)を追加。
"""
user_attributes = event['request'].get('userAttributes', {})
email = user_attributes.get('email')
# カスタムバリデーション(5秒以内に完了必須)
if not is_ip_whitelisted(event['request']['userContextData']['sourceIp']):
raise Exception(f"Login from {event['request']['userContextData']['sourceIp']} not allowed")
return event
def is_ip_whitelisted(ip):
# ホワイトリスト確認ロジック
return ip.startswith('10.0.')
3. トークンのスコープ設計
OAuth 2.0 スコープを使用して、API への細粒度なアクセス制御を実装します:
# App Client にカスタムスコープを追加
aws cognito-idp create-resource-server \
--user-pool-id ap-northeast-1_xxxx \
--identifier api \
--name "API Resource Server" \
--scopes Name=read,Description="Read access to API" Name=write,Description="Write access to API"
4. RefreshToken の安全な管理
- HTTPOnly Cookie に Refresh Token を保存(JavaScript からアクセス不可)
- CSRF 保護を実装
- Refresh Token の定期更新(ローテーション)
第2部:AWS STS(Security Token Service)
2.1 STS の役割
STS は 一時的な AWS 認証情報 を発行するサービス。長期的な IAM ユーザーのアクセスキーの代わりに、期限付きの認証情報を提供することで、セキュリティを向上させます。
STS が発行する一時認証情報:
- AccessKeyId
- SecretAccessKey
- SessionToken(重要)
- Expiration(有効期限)
2.2 AssumeRole — クロスアカウント認証
2.2.1 基本的なフロー
Account A(信頼側)
- STS AssumeRole リクエスト
- Account B(委任側)の IAM ロール
- 一時認証情報を取得
- Account B のリソースにアクセス可能
実装例:
# Account A のユーザーが、Account B のロールを引き受ける
aws sts assume-role \
--role-arn arn:aws:iam::999999999999:role/CrossAccountRole \
--role-session-name session-name-123 \
--duration-seconds 3600
レスポンス:
{
"Credentials": {
"AccessKeyId": "ASIAX1234567890ABCD",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"SessionToken": "AQoDYXdzEJr...<省略>...EXAMPLETOKEN",
"Expiration": "2026-04-27T15:30:00Z"
},
"AssumedRoleUser": {
"AssumedRoleId": "AIDAI1234567890ABCD:session-name-123",
"Arn": "arn:aws:iam::999999999999:assumed-role/CrossAccountRole/session-name-123"
}
}
2.2.2 Confused Deputy 問題と External ID
Confused Deputy 問題とは:
シナリオ:
- Account A のサービス S が、Account B のロール R を AssumeRole
- 悪意のある Account C が、Account A の S に命令
- S が知らないうちに、Account B のロール R の権限で C の指示を実行
対策: External ID を使用
External ID による保護:
# Account B(委任側)でロール作成時に External ID を指定
aws iam create-role \
--role-name CrossAccountRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-external-id-12345"
}
}
}
]
}'
# Account A(信頼側)でロール引き受け時に External ID を指定
aws sts assume-role \
--role-arn arn:aws:iam::999999999999:role/CrossAccountRole \
--role-session-name session-name-123 \
--external-id unique-external-id-12345 \
--duration-seconds 3600
External ID がない場合、Account C も同じロールを AssumeRole できてしまいます。必ず使用してください。
2.2.3 Session Tags
AssumeRole 時に、セッションに対してタグ(キー・値ペア)を設定できます。これにより、ロール内でセッションごとの権限を制御できます:
aws sts assume-role \
--role-arn arn:aws:iam::999999999999:role/CrossAccountRole \
--role-session-name session-name-123 \
--tags Key=Project,Value=ProjectA Key=Department,Value=Engineering \
--duration-seconds 3600
IAM ポリシーで Session Tags を参照:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/projects/${aws:PrincipalTag/Project}/*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/Department": "Engineering"
}
}
}
]
}
2.3 AssumeRoleWithSAML / AssumeRoleWithWebIdentity
2.3.1 AssumeRoleWithSAML
Okta、Salesforce、Active Directory などの SAML IdP との統合:
aws sts assume-role-with-saml \
--role-arn arn:aws:iam::123456789012:role/SAMLRole \
--principal-arn arn:aws:iam::123456789012:saml-provider/ExampleProvider \
--saml-assertion file://saml-assertion.xml \
--duration-seconds 3600
2.3.2 AssumeRoleWithWebIdentity
Google、Facebook などの OIDC プロバイダーとの統合:
aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::123456789012:role/OIDCRole \
--role-session-name session-name-123 \
--web-identity-token token-from-google-oauth \
--duration-seconds 3600
Cognito との連携:
# Cognito User Pools の ID Token を使用
aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::123456789012:role/CognitoRole \
--role-session-name session-name-123 \
--web-identity-token ${ID_TOKEN} \
--duration-seconds 3600
2.4 GetSessionToken(MFA付き)
IAM ユーザーが MFA 経由で一時認証情報を取得:
aws sts get-session-token \
--serial-number arn:aws:iam::123456789012:mfa/user-mfa-device \
--token-code 123456 \
--duration-seconds 3600
ユースケース:
- CLI での高権限操作を MFA で保護
- CI/CD パイプラインへの認証情報提供
2.5 GetFederationToken
長期的な認証情報を持つユーザーが、期限付きの代理認証情報を発行:
aws sts get-federation-token \
--name federated-user-session \
--policy '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}' \
--duration-seconds 3600
AssumeRole との違い:
- AssumeRole: IAM ロールを引き受ける(ロールの権限 ∩ セッション権限)
- GetFederationToken: カスタム権限を定義できる(より柔軟)
2.6 セッション期間の制約
| API | 最小期間 | 最大期間 | デフォルト | 注記 |
|---|---|---|---|---|
| AssumeRole | 900秒(15分) | 43200秒(12時間) | 3600秒(1時間) | ロール最大セッション期間で制限可能 |
| AssumeRoleWithSAML | 900秒 | 43200秒 | 3600秒 | 同上 |
| AssumeRoleWithWebIdentity | 900秒 | 43200秒 | 3600秒 | 同上 |
| GetSessionToken | 900秒 | 129600秒(36時間) | 3600秒 | ユーザーの最大セッション期間で制限可能 |
| GetFederationToken | 900秒 | 129600秒 | 3600秒 | 呼び出し元ユーザーの権限で制限 |
ロールチェーン時の制限(重要):
Account A の User → Account B のロール → Account C のロール
↓
A→B での期間: 1時間可能
↓
B→C での期間: **A の残り時間以下**(最大1時間)
ロールチェーンは1時間以内に完了する必要があります。
2.7 できないこと・制約
| 制約 | 詳細 |
|---|---|
| トークン有効期間の上限 | AssumeRole は最大12時間、GetSessionToken は最大36時間 |
| ロールチェーン1時間制限 | 複数の AssumeRole を連続実行する場合、合計期間は1時間以内 |
| リージョナルエンドポイント推奨 | グローバルエンドポイント(sts.amazonaws.com)よりもリージョナルエンドポイント(sts.ap-northeast-1.amazonaws.com)を推奨 |
| MFA デバイス再登録 | IAM ユーザーのMFAデバイスを変更後、GetSessionToken に一時的に失敗する場合あり |
| External ID の後からの追加 | ポリシー更新後、既に発行された一時認証情報には影響なし |
2.8 ベストプラクティス
1. 一時認証情報の徹底活用
import boto3
from botocore.credentials import RefreshableCredentials
from botocore.session import Session
# 長期的なアクセスキーではなく、一時認証情報を使用
sts = boto3.client('sts')
response = sts.assume_role(
RoleArn='arn:aws:iam::999999999999:role/ApplicationRole',
RoleSessionName='app-session',
DurationSeconds=900
)
credentials = response['Credentials']
session = Session()
session.set_credentials(
credentials['AccessKeyId'],
credentials['SecretAccessKey'],
credentials['SessionToken']
)
s3 = session.create_client('s3')
2. Confused Deputy 防止(必須)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-id-for-this-lambda-function"
},
"ArnLike": {
"aws:SourceArn": "arn:aws:lambda:ap-northeast-1:123456789012:function/my-function"
}
}
}
]
}
3. STS エンドポイントはリージョナルを使用
# 推奨: リージョナルエンドポイント
aws sts assume-role \
--endpoint-url https://sts.ap-northeast-1.amazonaws.com \
--role-arn arn:aws:iam::999999999999:role/CrossAccountRole \
--role-session-name session-name-123
理由: グローバルエンドポイント(sts.amazonaws.com)よりもレイテンシが低く、リージョン側のレートリミットに対応できます。
4. セッション期間を最小限に
# 15分(最小期間)で十分な場合は 900 秒を使用
aws sts assume-role \
--role-arn arn:aws:iam::999999999999:role/CrossAccountRole \
--role-session-name session-name-123 \
--duration-seconds 900
第3部:Cognito + STS の連携パターン
3.1 Architecture: Cognito + API Gateway + Lambda
┌─────────────────────────────────────────────────────────────┐
│ ユーザーの流れ │
└─────────────────────────────────────────────────────────────┘
① ユーザーがログイン
↓
User Pools(認証)
↓
ID Token / Access Token / Refresh Token を取得
② API への認可を取得
↓
Identity Pools
↓
一時的な AWS 認証情報(AccessKeyId, SecretAccessKey, SessionToken)
③ API Gateway の認可
↓
Lambda Authorizer が ID Token を検証
↓
API Gateway がリクエストを許可/拒否
④ Lambda 関数が実行
↓
一時認証情報で S3, DynamoDB などにアクセス
┌─────────┐ ┌────────────────┐
│ ユーザー │ -------> │ Cognito User │
│ │ │ Pools (認証) │
└─────────┘ └────────────────┘
↓
ID Token 発行
↓
┌─────────────────────┐
│ Cognito Identity │
│ Pools(認可) │
└─────────────────────┘
↓
一時認証情報を発行
↓
┌─────────────────────────────┐
│ API Gateway (認可) │
│ ↓ Lambda Authorizer で │
│ ↓ トークン検証 │
└─────────────────────────────┘
↓
┌─────────────────┐
│ Lambda 関数 │
│ ↓ AWS リソース │
│ (S3, DDB等) │
└─────────────────┘
3.2 実装例:Lambda Authorizer
import json
import boto3
from jose import jwt
cognito_user_pool_id = 'ap-northeast-1_xxxx'
cognito_client_id = 'clientid123'
region = 'ap-northeast-1'
# Cognito の公開鍵を取得(JWT 署名検証用)
cognito = boto3.client('cognito-idp', region_name=region)
def lambda_handler(event, context):
"""
API Gateway Lambda Authorizer
ID Token を検証して、認可を判断する
"""
token = event.get('authorizationToken', '')
method_arn = event.get('methodArn', '')
try:
# JWT の署名検証
claims = verify_token(token, cognito_user_pool_id, cognito_client_id, region)
# トークンが有効な場合、ユーザーに API へのアクセスを許可
return generate_policy('user', 'Allow', method_arn, claims)
except Exception as e:
print(f"Token verification failed: {str(e)}")
return generate_policy('user', 'Deny', method_arn)
def verify_token(token, user_pool_id, client_id, region):
"""
JWT トークンの署名を検証
"""
# Cognito の JWKS エンドポイントから公開鍵を取得
jwks_url = f"https://cognito-idp.{region}.amazonaws.com/{user_pool_id}/.well-known/jwks.json"
# jose ライブラリを使用して検証
# 実装はライブラリの公式ドキュメントに従う
claims = jwt.get_unverified_claims(token)
# 実際の署名検証はここで行う
# 省略(本来は JWKS を使用して署名を検証)
return claims
def generate_policy(principal_id, effect, resource, claims=None):
"""
API Gateway の承認ポリシーを生成
"""
auth_response = {
'principalId': principal_id,
'policyDocument': {
'Version': '2012-10-17',
'Statement': [
{
'Action': 'execute-api:Invoke',
'Effect': effect,
'Resource': resource
}
]
}
}
# クレーム情報を Context に追加
if claims:
auth_response['context'] = {
'email': claims.get('email', ''),
'sub': claims.get('sub', '')
}
return auth_response
3.3 Cognito + ALB
┌──────────────┐
│ ユーザー │
└──────────────┘
↓
┌──────────────────────┐
│ ALB(Application │
│ Load Balancer) │
│ ↓ Cognito で認証 │
└──────────────────────┘
↓
Cognito User Pools
↓
ID Token を ALB に返却
↓
ALB が トークン検証後、
バックエンド EC2 / ECS へ
リクエストを転送
ALB リスナールールの設定例:
aws elbv2 create-rule \
--listener-arn arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener/app/my-alb/1234567890abcdef/1 \
--priority 1 \
--conditions Field=path-pattern,Values='/api/*' \
--actions \
Type=authenticate-cognito,AuthenticateCognitoConfig='{
UserPoolArn=arn:aws:cognito-idp:ap-northeast-1:123456789012:userpool/ap-northeast-1_xxxx,
UserPoolClientId=clientid123,
UserPoolDomain=my-domain
}' \
Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/my-targets/1234567890abcdef
3.4 STS + Organizations クロスアカウント
複数の AWS アカウントを一元管理する場合、STS を使用して Organizations 内のロールを AssumeRole します:
実装例:
# Management Account のユーザーが、Production Account のロールを AssumeRole
aws sts assume-role \
--role-arn arn:aws:iam::111111111111:role/OrganizationAccountAccessRole \
--role-session-name management-session \
--external-id arn:aws:organizations::123456789012:organization/o-1234567890 \
--duration-seconds 3600
3.5 フェデレーションパターン全体像
┌────────────────────────────────────────────────────────────┐
│ フェデレーション全体像 │
└────────────────────────────────────────────────────────────┘
1. User Pools だけで認証(Web / Mobile アプリ)
↓
ID Token / Access Token を取得
↓
API Gateway + Lambda Authorizer で API 保護
↓
AWS リソースへはアクセスしない
2. User Pools + Identity Pools(AWS リソースアクセス必須)
↓
ID Token で Identity Pools から認可取得
↓
一時認証情報を使用して S3, DynamoDB へアクセス
3. 外部 IdP (Google / Okta / SAML)
↓
Cognito User Pools と外部 IdP をフェデレーション
↓
パターン2と同様
4. STS AssumeRole(B2B / クロスアカウント)
↓
別 AWS アカウントのロールを引き受ける
↓
External ID で Confused Deputy を防止
5. STS AssumeRoleWithWebIdentity(Cognito との直接連携)
↓
Cognito User Pools の ID Token を直接利用
↓
Identity Pools を経由せずに AWS リソースアクセス可能
試験で狙われるポイント
Cognito 編
-
User Pools vs Identity Pools の役割
- User Pools = 認証(ユーザー名・パスワード管理)
- Identity Pools = 認可(AWS リソースへのアクセス権限)
-
Lambda トリガーの 5秒制限
- Pre Token Generation で外部 API 呼び出しは原則 NG
- 5秒以内に完了する処理のみ
-
Advanced Security Features
- 侵害された認証情報検出
- 適応型認証(リスク評価に基づく MFA)
-
SPA でシークレット生成は NG
- フロントエンドに秘密情報を露出させないため
-
Identity Pool ロールマッピング
- トークンベース vs ルールベース の選択基準
STS 編
-
Confused Deputy 問題
- External ID の使用は必須
- AWS の責任分界点を理解
-
ロールチェーン1時間制限
- A → B → C のように複数ロールをチェーンする場合、合計期間は1時間以内
-
AssumeRole と GetFederationToken の違い
- AssumeRole: ロール権限の一部を取得
- GetFederationToken: カスタム権限を定義
-
Session Tags による細粒度な権限制御
- セッション単位で権限を制御
-
リージョナルエンドポイントの推奨
- sts.ap-northeast-1.amazonaws.com の使用
まとめ
| サービス | 用途 | 出力 | 有効期限 |
|---|---|---|---|
| Cognito User Pools | 認証 | ID/Access/Refresh Token | 調整可能(デフォルト1時間) |
| Cognito Identity Pools | 認可 | AWS 一時認証情報 | 最大12時間 |
| STS AssumeRole | クロスアカウント | AWS 一時認証情報 | 最大12時間 |
| STS GetSessionToken | MFA 認証 | AWS 一時認証情報 | 最大36時間 |
Cognito と STS は、AWS のセキュアな認証認可の基盤です。フェデレーション、ロールマッピング、Confused Deputy 対策を完全に理解することが、SCS-C03 合格の鍵となります。