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

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-flowsALLOW_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は本番で最終確認
  • 認証フローの基本動作をローカルで高速に反復できるのが最大のメリット

関連記事