Floci × Cognito / IAM ハンズオン — 認証・認可フローのローカル検証【2026年版】

目次
この記事でわかること
- FlociでCognito User Poolを作成しユーザー登録・認証する方法
- JWT(IDトークン/アクセストークン)の取得とローカル検証
- IAMロール・ポリシー・STS AssumeRoleのローカル実行
- Lambda + Cognito オーソライザーの検証
- ローカル検証で再現できないIAM挙動の注意点
認証・認可まわりは「本番だけで動作確認」になりがちで、バグ発覚が遅れやすい領域です。Flociを使えばCognito・IAM・STSを含む認証フローをローカルで反復検証でき、開発速度が大きく改善します。
Flociの基本は 入門記事 を参照してください。
Cognito User Pool の作成
aws cognito-idp create-user-pool \
--pool-name app-users \
--endpoint-url http://localhost:4566
レスポンスから UserPoolId を取得して、クライアント(アプリ)を登録:
aws cognito-idp create-user-pool-client \
--user-pool-id <UserPoolId> \
--client-name web-app \
--no-generate-secret \
--explicit-auth-flows ALLOW_USER_PASSWORD_AUTH ALLOW_REFRESH_TOKEN_AUTH \
--endpoint-url http://localhost:4566
ユーザー登録と認証(Python)
import boto3
cog = boto3.client(
"cognito-idp", endpoint_url="http://localhost:4566",
region_name="us-east-1",
aws_access_key_id="test", aws_secret_access_key="test",
)
USER_POOL_ID = "us-east-1_xxxxx"
CLIENT_ID = "xxxxxxxxxxxx"
# サインアップ
cog.sign_up(
ClientId=CLIENT_ID,
Username="alice@example.com",
Password="Passw0rd!",
UserAttributes=[{"Name": "email", "Value": "alice@example.com"}],
)
# 管理者確認(メール検証スキップ)
cog.admin_confirm_sign_up(UserPoolId=USER_POOL_ID, Username="alice@example.com")
# 認証
res = cog.initiate_auth(
ClientId=CLIENT_ID,
AuthFlow="USER_PASSWORD_AUTH",
AuthParameters={"USERNAME": "alice@example.com", "PASSWORD": "Passw0rd!"},
)
tokens = res["AuthenticationResult"]
print("IdToken:", tokens["IdToken"])
print("AccessToken:", tokens["AccessToken"])
JWT の検証
発行されたトークンは標準的なJWT形式です。PyJWT で中身を確認:
import jwt
payload = jwt.decode(tokens["IdToken"], options={"verify_signature": False})
print(payload)
# {'sub': '...', 'email': 'alice@example.com', 'token_use': 'id', ...}
注意: Flociは検証用のためJWT署名の整合性は簡易的です。本番アプリでは JWKSエンドポイント経由での検証ロジックを必ず実装し、本番前に実AWSで動作確認してください。
Identity Pool と一時クレデンシャル
認証ユーザーに対してAWSリソースへの一時クレデンシャルを発行する流れ:
aws cognito-identity create-identity-pool \
--identity-pool-name app-identity \
--allow-unauthenticated-identities \
--endpoint-url http://localhost:4566
ci = boto3.client("cognito-identity", endpoint_url="http://localhost:4566",
region_name="us-east-1",
aws_access_key_id="test", aws_secret_access_key="test")
res = ci.get_id(IdentityPoolId="us-east-1:xxxx")
identity_id = res["IdentityId"]
creds = ci.get_credentials_for_identity(IdentityId=identity_id)["Credentials"]
print(creds) # AccessKeyId / SecretKey / SessionToken
IAM ロールとポリシー
ロール作成
aws iam create-role \
--role-name lambda-role \
--assume-role-policy-document '{
"Version":"2012-10-17",
"Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]
}' \
--endpoint-url http://localhost:4566
ポリシーアタッチ
aws iam put-role-policy \
--role-name lambda-role \
--policy-name s3-read \
--policy-document '{
"Version":"2012-10-17",
"Statement":[{"Effect":"Allow","Action":"s3:GetObject","Resource":"*"}]
}' \
--endpoint-url http://localhost:4566
STS AssumeRole
sts = boto3.client("sts", endpoint_url="http://localhost:4566",
region_name="us-east-1",
aws_access_key_id="test", aws_secret_access_key="test")
res = sts.assume_role(
RoleArn="arn:aws:iam::000000000000:role/lambda-role",
RoleSessionName="test-session",
)
creds = res["Credentials"]
print(creds["AccessKeyId"], creds["SecretAccessKey"], creds["SessionToken"])
取得した一時クレデンシャルで別クライアントを作り、クロスサービスアクセスを検証できます。
Lambda + Cognito オーソライザー
API Gatewayのオーソライザーに Cognito User Pool を指定する構成:
# オーソライザー作成(疑似的な設定例)
aws apigateway create-authorizer \
--rest-api-id <api-id> \
--name cognito-auth \
--type COGNITO_USER_POOLS \
--provider-arns arn:aws:cognito-idp:us-east-1:000000000000:userpool/<UserPoolId> \
--identity-source method.request.header.Authorization \
--endpoint-url http://localhost:4566
クライアント側はIDトークンを Authorization: Bearer <IdToken> ヘッダで送信すればOK。
Node.js 例
import { CognitoIdentityProviderClient, InitiateAuthCommand } from
"@aws-sdk/client-cognito-identity-provider";
const cog = new CognitoIdentityProviderClient({
endpoint: "http://localhost:4566",
region: "us-east-1",
credentials: { accessKeyId: "test", secretAccessKey: "test" },
});
const res = await cog.send(new InitiateAuthCommand({
ClientId: "xxxxxxxxxxxx",
AuthFlow: "USER_PASSWORD_AUTH",
AuthParameters: { USERNAME: "alice@example.com", PASSWORD: "Passw0rd!" },
}));
console.log(res.AuthenticationResult.IdToken);
再現できないIAM挙動に注意
Flociがローカルで再現しきれない主な挙動:
- 条件キー (
aws:SourceIp,aws:PrincipalTagなど) の厳密評価 - Service Control Policies (SCP) / Organizations 連携
- Permission Boundary の詳細評価
- ResourcePolicy(S3バケットポリシーなど)の本番水準の評価
- MFAを絡めた
aws:MultiFactorAuthPresent条件 - IAM Access Analyzer の解析結果
これらはポリシーの構文チェック+ロジックフロー検証までをローカルで済ませ、本番相当の権限検証は実AWSで行う二段構えが基本です。
よくあるエラー
NotAuthorizedException: Incorrect username or password
admin_confirm_sign_upを呼んでいないexplicit-auth-flowsにALLOW_USER_PASSWORD_AUTHが含まれていない
AccessDenied なのにポリシーは正しく見える
Floci上では許可扱いになるが本番では拒否されるケースあり。aws:SourceIp などの条件キーは本番で再確認。
JWT署名検証に失敗
Flociは簡易的なJWT発行のため、本番用JWKSとは互換しません。検証ロジックの実装確認のみ行い、実AWSでの確認も必ず。
FAQ
Q. MFAのローカル検証は?
Flociでは MFA関連APIは受け付けるが、実際のTOTP検証などは簡略化されます。本番で必ず動作確認を。
Q. SAML/OIDC連携は?
本格的なIdP連携は未対応。Cognito側のフックまでがローカル検証の範囲です。
Q. IAMアクセスアナライザーは?
未対応です。AWS IAM Access Analyzer を本番で併用してください。
OAuth 2.0 / OIDC フローの検証
Cognitoは標準的なOAuth 2.0 Authorization Code Grantに対応しています。Floci上でも基本フローを検証可能:
[ブラウザ] → /oauth2/authorize → [ログイン画面] → [認可コード]
↓
[バックエンド] → /oauth2/token?code=xxx → [IDトークン・アクセストークン]
# 認可コードからトークンを交換
import requests
res = requests.post(
"http://localhost:4566/oauth2/token",
data={
"grant_type": "authorization_code",
"client_id": CLIENT_ID,
"code": "<authorization-code>",
"redirect_uri": "http://localhost:3000/callback",
},
)
tokens = res.json()
本物のIdP画面は表示されませんが、トークン交換APIの挙動を確認できます。
カスタム属性
業務要件に応じたカスタム属性の追加:
aws cognito-idp add-custom-attributes \
--user-pool-id <UserPoolId> \
--custom-attributes Name=company,AttributeDataType=String,Mutable=true \
--endpoint-url http://localhost:4566
cog.sign_up(
ClientId=CLIENT_ID,
Username="bob@example.com",
Password="Passw0rd!",
UserAttributes=[
{"Name": "email", "Value": "bob@example.com"},
{"Name": "custom:company", "Value": "Acme Corp"},
],
)
ソーシャルログイン
Google / Facebook / Apple などの外部IdP連携は Cognito の IdentityProvider として登録します。Flociは設定登録までを受け付け、実際のIdPリダイレクトフローは簡略化されます。
aws cognito-idp create-identity-provider \
--user-pool-id <UserPoolId> \
--provider-name Google \
--provider-type Google \
--provider-details client_id=xxx,client_secret=yyy,authorize_scopes=email \
--endpoint-url http://localhost:4566
本番前に実Google OAuthでのE2Eテストは必須です。
ユーザー管理API
管理者APIでユーザーを強制操作:
# パスワードリセット(管理者経由)
cog.admin_set_user_password(
UserPoolId=USER_POOL_ID,
Username="alice@example.com",
Password="NewPass0rd!",
Permanent=True,
)
# ユーザーグループ
cog.create_group(GroupName="admins", UserPoolId=USER_POOL_ID)
cog.admin_add_user_to_group(
UserPoolId=USER_POOL_ID, Username="alice@example.com", GroupName="admins",
)
# 全ユーザー一覧
users = cog.list_users(UserPoolId=USER_POOL_ID)
for u in users["Users"]:
print(u["Username"], u["UserStatus"])
Next.js / React での利用例
amazon-cognito-identity-js などを使った典型的なフロント連携:
import { CognitoUserPool, AuthenticationDetails, CognitoUser }
from "amazon-cognito-identity-js";
const pool = new CognitoUserPool({
UserPoolId: "us-east-1_xxxxx",
ClientId: "xxxxxxxxxxxx",
endpoint: "http://localhost:4566",
});
const user = new CognitoUser({ Username: "alice@example.com", Pool: pool });
user.authenticateUser(
new AuthenticationDetails({ Username: "alice@example.com", Password: "Passw0rd!" }),
{
onSuccess: (res) => console.log("IdToken:", res.getIdToken().getJwtToken()),
onFailure: (err) => console.error(err),
},
);
Floci上でフロントエンドとの統合まで検証できるのが大きな利点です。
セキュリティベストプラクティス
パスワードポリシー
aws cognito-idp update-user-pool \
--user-pool-id <UserPoolId> \
--policies 'PasswordPolicy={MinimumLength=12,RequireUppercase=true,RequireLowercase=true,RequireNumbers=true,RequireSymbols=true}' \
--endpoint-url http://localhost:4566
トークン有効期限
- IDトークン / アクセストークン: 15分〜1時間
- リフレッシュトークン: 数時間〜30日
- 短め設定で漏洩時の影響最小化をローカルで検証
JWT検証の実装例
from jose import jwt, jwk
import requests
def verify_token(token):
jwks = requests.get(
f"http://localhost:4566/{USER_POOL_ID}/.well-known/jwks.json"
).json()
header = jwt.get_unverified_header(token)
key = next(k for k in jwks["keys"] if k["kid"] == header["kid"])
return jwt.decode(token, jwk.construct(key).to_pem(),
algorithms=["RS256"], audience=CLIENT_ID)
本番では必ずJWT署名を検証すること。Floci側のキーは簡易実装のため、本番相当のJWKSフローは実AWSでも確認を。
典型的な認可アーキテクチャ
[ブラウザ]
↓ (ID/アクセストークン)
[API Gateway (Cognito Authorizer)]
↓ (検証済みClaims)
[Lambda]
↓ (IAM Role / Scope)
[DynamoDB / S3]
API Gateway オーソライザー → Lambda → AWSリソース の認可伝搬をFloci上でE2E検証できれば、本番導入の9割は完了です。
実運用の注意点
- レート制限・ボット対策(AWS WAFなど)はFlociでは再現不可
- ログ監査(CloudTrail / CloudWatch Logs)は実AWSで有効化を
- 多要素認証(MFA) は必ず本番環境で実機確認
- Cognito Sync(廃止予定)は非対応
まとめ
- FlociはCognito User Pool / Identity Pool / IAM / STSを主要APIレベルで再現
- ユーザー登録・認証・JWT取得・AssumeRoleまでローカルで完結
- IAMポリシーの細部・条件キー・MFAは本番で最終確認
- 認証フローの基本動作をローカルで高速に反復できるのが最大のメリット