こんにちは、広野です。
生成 AI 界隈の技術の進化がすさまじく、以前開発したチャットボットのアーキテクチャも陳腐化が見えてきました。この記事を執筆している時点での最新のアーキテクチャで改めて作り直してみたので、いくつかの記事に分けて紹介します。
今回 (2回目) は実装編 その1 Amazon Cognito 編です。
大変恐縮ですが、AWS CloudFormation によるデプロイをしているので YAML テンプレートベースでの説明となります。ご了承ください。
前回の記事
アーキテクチャ概要については前回記事で紹介しています。こちらをご覧ください。
今回の説明範囲
アーキテクチャ図中、赤枠の部分を説明いたします。
セキュリティの根幹となる認証部分の説明になります。別件で公開している Amazon Cognito の説明記事とほぼ変わりませんが、あらためて掲載します。また、他の用途にも同じ構成で転用しやすいので一度覚えると有用です。ほんと万能です。
実装している仕様
- 図には Amazon Cognito ユーザープールしか表現していませんが、Amazon Cognito ID プールも作成しています。私が作成するアプリでは ID プールを使用した Amazon Cognito ユーザーまたはグループ単位の AWS リソースアクセス制御をすることが高いからです。ただし、本記事の構成では設定はほぼ何もなく、基本的な設定を入れているだけです。(細かい設定を入れる前の枠だけ作った感じ)
- Amazon Cognito でユーザーがセルフサインアップできるようにしています。その方がユーザー管理しなくて済み、楽だからです。代わりに、誰でも登録できるのは良くないので、メールアドレスのドメイン名 (本記事では scsk.jp) でセルフサインアップ可否を判断する AWS Lambda 関数を入れています。当然、セルフサインアップの過程でメールの存在確認をするようになっています。
- Amazon Cognito は管理者用のメール送信をする都合で、Amazon SES を使用しています。そのためのパラメータを入力する必要があります。Amazon SES は以下の参考記事のようにログ取得用の設定セットが作成されていることが前提となっています。
- ユーザーは MFA を強制されます。
- Amazon Cognito ユーザーグループは ADMIN と BASIC の 2種類を初期作成しており、後から ADMIN 所属でないとできない機能を作成するときに使用します。バックエンドやアプリ側で、Amazon Cognito ユーザーの属性を取得することで権限制御できます。
AWS CloudFormation テンプレート
AWSTemplateFormatVersion: 2010-09-09
Description: The CloudFormation template that creates a Cognito user pool, a Cognito ID pool, Lambda functions and relevant IAM roles.
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: System name. use lower case only. (e.g. example)
Default: example
MaxLength: 10
MinLength: 1
SubName:
Type: String
Description: System sub name. use lower case only. (e.g. prod or dev)
Default: dev
MaxLength: 10
MinLength: 1
DomainName:
Type: String
Description: Domain name for URL. xxxxx.xxx (e.g. example.com)
Default: example.com
MaxLength: 40
MinLength: 5
SesId:
Type: String
Description: Amazon SES ID for sending emails. (email addreess or domain)
Default: example.com
MaxLength: 100
MinLength: 5
SesConfigurationSet:
Type: String
Description: Amazon SES configuration set for sending emails.
Default: ses-logs-xxxxxxxxxxxx-ap-northeast-1
MaxLength: 100
MinLength: 5
CognitoAdminAlias:
Type: String
Description: The alias name of Cognito Admin email address. (e.g. admin)
Default: admin
MaxLength: 100
MinLength: 5
CognitoReplyTo:
Type: String
Description: Cognito Reply-to email address. (e.g. xxx@xxx.xx)
Default: xxxxxx@example.com
MaxLength: 100
MinLength: 5
CognitoEmailFrom:
Type: String
Description: Cognito e-mail from address. (e.g. xxx@xxx.xx)
Default: no-reply@mail.example.com
MaxLength: 100
MinLength: 5
AllowedUserEmailDomains:
Description: Domain list to allow user sign up. Each domains must be comma delimited and double quoted.
Type: String
Default: '"scsk.jp"'
Resources:
# ------------------------------------------------------------#
# Cognito Idp Roles (IAM)
# ------------------------------------------------------------#
CognitoIdpAuthRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${SystemName}-CognitoIdpAuthRole-${SubName}
Description: This role allows Cognito authenticated users to access AWS resources.
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action:
"sts:AssumeRoleWithWebIdentity"
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud": !Ref IdPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": authenticated
Policies:
- PolicyName: !Sub ${SystemName}-CognitoIdpAuthRolePolicy-${SubName}
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "mobileanalytics:PutEvents"
- "cognito-sync:*"
- "cognito-identity:*"
Resource: "*"
CognitoIdpUnauthRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${SystemName}-CognitoIdpUnauthRole-${SubName}
Description: This role allows Cognito unauthenticated users to access AWS resources.
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action:
"sts:AssumeRoleWithWebIdentity"
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud": !Ref IdPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": unauthenticated
Policies:
- PolicyName: !Sub ${SystemName}-CognitoIdpUnauthRolePolicy-${SubName}
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "mobileanalytics:PutEvents"
- "cognito-sync:*"
- "cognito-identity:*"
Resource: "*"
CognitoGroupAdminRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${SystemName}-CognitoGroupAdminRole-${SubName}
Description: This role allows Cognito authenticated users that belong to ADMIN group to access AWS resources.
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action:
"sts:AssumeRoleWithWebIdentity"
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud": !Ref IdPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": authenticated
Policies:
- PolicyName: !Sub example-CognitoGroupBasicPolicy-${SubName}
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "mobileanalytics:PutEvents"
- "cognito-sync:*"
- "cognito-identity:*"
Resource: "*"
CognitoGroupBasicRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${SystemName}-CognitoGroupBasicRole-${SubName}
Description: This role allows Cognito authenticated users that belong to BASIC group to access AWS resources.
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action:
"sts:AssumeRoleWithWebIdentity"
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud": !Ref IdPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": authenticated
Policies:
- PolicyName: !Sub ${SystemName}-CognitoIdpUnauthRolePolicy-${SubName}
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "mobileanalytics:PutEvents"
- "cognito-sync:*"
- "cognito-identity:*"
Resource: "*"
# ------------------------------------------------------------#
# Lambda (triggered from Cognito) Role (IAM)
# ------------------------------------------------------------#
LambdaTriggeredFromCognitoRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${SystemName}-LambdaTriggeredFromCognitoRole-${SubName}
Description: This role grants Lambda functions triggered from Cognito basic priviledges.
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
- arn:aws:iam::aws:policy/AmazonCognitoPowerUser
# ------------------------------------------------------------#
# Cognito Lambda Invocation Permission
# ------------------------------------------------------------#
CognitoLambdaInvocationPermissionPresignup:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt LambdaCognitoPresignup.Arn
Action: lambda:InvokeFunction
Principal: cognito-idp.amazonaws.com
SourceAccount: !Ref AWS::AccountId
SourceArn: !GetAtt UserPool.Arn
DependsOn:
- LambdaCognitoPresignup
- UserPool
CognitoLambdaInvocationPermissionPostconfirm:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt LambdaCognitoPostconfirm.Arn
Action: lambda:InvokeFunction
Principal: cognito-idp.amazonaws.com
SourceAccount: !Ref AWS::AccountId
SourceArn: !GetAtt UserPool.Arn
DependsOn:
- LambdaCognitoPostconfirm
- UserPool
# ------------------------------------------------------------#
# Cognito user pool
# ------------------------------------------------------------#
UserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: !Sub ${SystemName}-${SubName}
MfaConfiguration: "ON"
EnabledMfas:
- SOFTWARE_TOKEN_MFA
Policies:
PasswordPolicy:
MinimumLength: 8
RequireUppercase: true
RequireLowercase: true
RequireNumbers: true
RequireSymbols: false
TemporaryPasswordValidityDays: 180
AccountRecoverySetting:
RecoveryMechanisms:
- Name: verified_email
Priority: 1
AdminCreateUserConfig:
AllowAdminCreateUserOnly: false
AutoVerifiedAttributes:
- email
DeviceConfiguration:
ChallengeRequiredOnNewDevice: false
DeviceOnlyRememberedOnUserPrompt: false
EmailConfiguration:
ConfigurationSet: !Ref SesConfigurationSet
EmailSendingAccount: DEVELOPER
From: !Sub "${SystemName}-${SubName} ${CognitoAdminAlias} <${CognitoEmailFrom}>"
ReplyToEmailAddress: !Ref CognitoReplyTo
SourceArn: !Sub arn:aws:ses:${AWS::Region}:${AWS::AccountId}:identity/${SesId}
EmailVerificationMessage: !Sub "${SystemName}-${SubName} Verification code: {####}"
EmailVerificationSubject: !Sub "${SystemName}-${SubName} Verification code"
LambdaConfig:
PreSignUp: !GetAtt LambdaCognitoPresignup.Arn
PostConfirmation: !GetAtt LambdaCognitoPostconfirm.Arn
UsernameAttributes:
- email
UsernameConfiguration:
CaseSensitive: false
UserPoolAddOns:
AdvancedSecurityMode: "OFF"
UserPoolTags:
Cost: !Sub ${SystemName}-${SubName}
UserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
UserPoolId: !Ref UserPool
ClientName: !Sub ${SystemName}-${SubName}-appclient
GenerateSecret: false
RefreshTokenValidity: 3
AccessTokenValidity: 6
IdTokenValidity: 6
ExplicitAuthFlows:
- ALLOW_USER_SRP_AUTH
- ALLOW_REFRESH_TOKEN_AUTH
PreventUserExistenceErrors: ENABLED
SupportedIdentityProviders:
- COGNITO
CallbackURLs:
- !Sub https://${DomainName}/index.html
LogoutURLs:
- !Sub https://${DomainName}/index.html
DefaultRedirectURI: !Sub https://${DomainName}/index.html
AllowedOAuthFlows:
- implicit
AllowedOAuthFlowsUserPoolClient: true
AllowedOAuthScopes:
- email
- openid
# ------------------------------------------------------------#
# Cognito user group
# ------------------------------------------------------------#
UserPoolGroupAdmin:
Type: AWS::Cognito::UserPoolGroup
Properties:
Description: ${SystemName} User Group which allows users able to access management tools.
GroupName: ADMIN
Precedence: 1
UserPoolId: !Ref UserPool
RoleArn: !GetAtt CognitoGroupAdminRole.Arn
UserPoolGroupBasic:
Type: AWS::Cognito::UserPoolGroup
Properties:
Description: ${SystemName} User Group which allows users able to access foundation and associate contents.
GroupName: BASIC
Precedence: 101
UserPoolId: !Ref UserPool
RoleArn: !GetAtt CognitoGroupBasicRole.Arn
# ------------------------------------------------------------#
# Cognito id pool
# ------------------------------------------------------------#
IdPool:
Type: AWS::Cognito::IdentityPool
Properties:
IdentityPoolName: !Sub ${SystemName}-${SubName}
AllowClassicFlow: false
AllowUnauthenticatedIdentities: false
CognitoIdentityProviders:
- ClientId: !Ref UserPoolClient
ProviderName: !GetAtt UserPool.ProviderName
ServerSideTokenCheck: true
IdentityPoolTags:
- Key: Cost
Value: !Sub ${SystemName}-${SubName}
IdPoolRoleAttachment:
Type: AWS::Cognito::IdentityPoolRoleAttachment
Properties:
IdentityPoolId: !Ref IdPool
Roles:
authenticated: !GetAtt CognitoIdpAuthRole.Arn
unauthenticated: !GetAtt CognitoIdpUnauthRole.Arn
RoleMappings:
userpool:
IdentityProvider: !Sub cognito-idp.${AWS::Region}.amazonaws.com/${UserPool}:${UserPoolClient}
Type: Token
AmbiguousRoleResolution: AuthenticatedRole
# ------------------------------------------------------------#
# Lambda
# ------------------------------------------------------------#
LambdaCognitoPresignup:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub ${SystemName}-CognitoPresignup-${SubName}
Description: !Sub Lambda Function triggered from Cognito before user self signup to check the user's email domain for ${SystemName}-${SubName}
Runtime: python3.13
Timeout: 3
MemorySize: 128
Role: !GetAtt LambdaTriggeredFromCognitoRole.Arn
Handler: index.lambda_handler
Tags:
- Key: Cost
Value: !Sub ${SystemName}-${SubName}
Code:
ZipFile: !Sub |
import re
def lambda_handler(event, context):
try:
print(event)
triggersource = event['triggerSource']
email = event['request']['userAttributes']['email']
print(email)
if triggersource == 'PreSignUp_SignUp':
print('via self signup')
domain = email.split('@')[1]
allowedDomains = [ ${AllowedUserEmailDomains} ]
if domain in allowedDomains:
print('allowed domain and email account')
return event
else:
print('prohibited domain')
return None
else:
print('via admin console')
return event
except Exception as e:
print(str(e))
DependsOn: LambdaTriggeredFromCognitoRole
LambdaCognitoPostconfirm:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub ${SystemName}-CognitoPostconfirm-${SubName}
Description: !Sub Lambda Function triggered from Cognito after user confirmation to add the user in BASIC group for ${SystemName}-${SubName}
Runtime: python3.13
Timeout: 3
MemorySize: 128
Role: !GetAtt LambdaTriggeredFromCognitoRole.Arn
Handler: index.lambda_handler
Tags:
- Key: Cost
Value: !Sub ${SystemName}-${SubName}
Code:
ZipFile: |
import boto3
client = boto3.client('cognito-idp')
def lambda_handler(event, context):
USERPOOLID = event['userPoolId']
USERNAME = event['userName']
try:
print(event)
res = client.admin_add_user_to_group(
UserPoolId=USERPOOLID,
Username=USERNAME,
GroupName='BASIC'
)
return event
except Exception as e:
print(str(e))
DependsOn: LambdaTriggeredFromCognitoRole
# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# Cognito
CognitoUserPoolID:
Value: !Ref UserPool
Export:
Name: !Sub CognitoUserPoolId-${SystemName}-${SubName}
CognitoArn:
Value: !GetAtt UserPool.Arn
Export:
Name: !Sub CognitoArn-${SystemName}-${SubName}
CognitoProviderName:
Value: !GetAtt UserPool.ProviderName
Export:
Name: !Sub CognitoProviderName-${SystemName}-${SubName}
CognitoProviderURL:
Value: !GetAtt UserPool.ProviderURL
Export:
Name: !Sub CognitoProviderURL-${SystemName}-${SubName}
CognitoAppClientID:
Value: !Ref UserPoolClient
Export:
Name: !Sub CognitoAppClientId-${SystemName}-${SubName}
CognitoIdPoolID:
Value: !Ref IdPool
Export:
Name: !Sub CognitoIdPoolId-${SystemName}-${SubName}
続編記事

React で Amazon Bedrock ベースの簡易生成 AI チャットボットをつくる [2025年7月版] 実装編2 API作成
生成 AI 界隈の技術の進化はすさまじく、以前開発したチャットボットのアーキテクチャも陳腐化が見えてきました。この記事を執筆している時点での最新のアーキテクチャで改めて作り直してみたので、いくつかの記事に分けて紹介します。今回 (3回目) は API 作成編です。

React で Amazon Bedrock ベースの簡易生成 AI チャットボットをつくる [2025年7月版] 実装編3 React
生成 AI 界隈の技術の進化はすさまじく、以前開発したチャットボットのアーキテクチャも陳腐化が見えてきました。この記事を執筆している時点での最新のアーキテクチャで改めて作り直してみたので、いくつかの記事に分けて紹介します。今回 (4回目) は React アプリ開発編です。
まとめ
いかがでしたでしょうか。
まだ本来の目的を達成するための前段階ですが、別件でも役に立つ構成だと思いますので改めて載せました。
本記事が皆様のお役に立てれば幸いです。


