はじめに
今回はCognitoでのサインアップ前LambdaトリガーをAWS CloudFormationを用いて構築していきたいと思います。
これにより、Cognitoで登録されるアカウントを制限することが出来たりすることが可能になります。
目次
・構成について
・Lambdaの設定項目
・LambdaのCloudFormation作成
・Cognitoの設定項目
・CognitoのCloudFormation作成
・事後確認
・最後に
・参考
構成について
CognitoとLambdaのみで構成します。
Lambdaのコードを呼び出すのにS3を利用しますが、特に今回作成する構成に影響は出ないです。
CloudFormationの構成として、初めにLambdaを構築し、その後にCognitoを構築します。
Lambdaの設定項目
今回はnodejs.18.xを利用し、コードについてはS3から取得してくるようにします。
IAMロールは作成しますが、Cognitoへのアクセスを許可するためのポリシーステートメントはCognitoのIDが必要なためCognitoのCloudFormationと同時に作成します。
index.jsの内容は記載しておりますが、node_modulesなどは別途対応をお願いします。
サインアップ前のチェックとして、Gmailのみ許可するという設定をしています。
上記以外の項目についてはCloudFormationの設定を見てご確認ください
また、コードを取得してくるS3については前回の記事を参考に作成してください
LambdaのCloudFormation作成
LambdaとIAMロールを作成します
Lambda_CloudFormation
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
Lambda Deployment
#------------------------------------------------------------#
#Parameters
#------------------------------------------------------------#
Parameters:
PJPrefix:
Description: Project Name
Type: String
Default: pj-ogataro
AllowedPattern: ^[a-zA-Z0-9\-]*$
Environment:
Description: Environment Name
Type: String
Default: dev
AllowedPattern: ^[a-zA-Z0-9\-]*$
#------------------------------------------------------------#
#Resources
#------------------------------------------------------------#
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub '${PJPrefix}-${Environment}-Lambda'
Runtime: nodejs18.x
Handler: index.handler
Code:
S3Bucket: !Sub '${PJPrefix}-${Environment}-storage'
S3Key: lambda/2_lambda_signin.zip
Role: !GetAtt LambdaExecutionRole.Arn
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub '${PJPrefix}-${Environment}-Lambda-Singin-IAMRole'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
- edgelambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: LambdaExecutionPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
- PolicyName: LambdaFunctionPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
- lambda:GetFunction
Resource: !Sub 'arn:aws:lambda:ap-northeast-1:${AWS::AccountId}:function:${PJPrefix}-${Environment}-Lambda'
#------------------------------------------------------------#
#Outputs
#------------------------------------------------------------#
Outputs:
LambdaFunction:
Value: !Ref LambdaFunction
Export:
Name: !Sub '${PJPrefix}-${Environment}-Lambda-Singin-Output'
Lambda_index.js
exports.handler = async (event, context) => {
console.log(event);
try {
// Amazon Cognitoから渡されたユーザサインアップのリクエストデータ
// ユーザ登録のトリガーとなったソース情報を取得
const triggersource = event.triggerSource;
// リクエストデータからメールアドレスを抽出
const email = event.request.userAttributes.email;
console.log(email);
if (triggersource === 'PreSignUp_SignUp') {
// トリガーソースがセルフサインアップの場合、ドメイン名チェックを実行
console.log('via self signup');
const domain = email.split('@')[1];
// サインアップを許可するドメイン名群
const allowedDomains = [
'gmail.com'
];
// 許可ドメインに含まれている場合
if (allowedDomains.includes(domain)) {
console.log('domain matched');
return event;
} else {
console.log('domain unmatched');
return null;
}
} else {
// トリガーソースがセルフサインアップ以外の場合、ドメイン名チェックを実行しない
console.log('via admin console');
return event;
}
} catch (error) {
console.log(error);
}
};
Cognitoの設定項目
サインアップ前Lambdaトリガー以外の設定については以前の記事と同じです。
サインアップ前にユーザー登録するメールアドレスドメインをチェックするLambdaを呼び出します。
CognitoのCloudFormation作成
Cognitoのユーザープールとそれに関係するユーザープールドメインやユーザープールクライアント、Lambdaのポリシーステートメントを作成します
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
CognitoUserPool deployment
#------------------------------------------------------------#
#Parameters
#------------------------------------------------------------#
Parameters:
PJPrefix:
Description: Project Name
Type: String
Default: pj-ogataro
AllowedPattern: ^[a-zA-Z0-9\-]*$
Environment:
Description: Environment Name
Type: String
Default: dev
AllowedPattern: ^[a-zA-Z0-9\-]*$
#------------------------------------------------------------#
#Resources
#------------------------------------------------------------#
Resources:
##ユーザープール作成
UserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: !Sub '${PJPrefix}-${Environment}-UserPool'
AdminCreateUserConfig:
AllowAdminCreateUserOnly: False
UsernameAttributes:
- email # Eメールでのサインインを有効にする場合は"email"を指定
AccountRecoverySetting:
RecoveryMechanisms:
- Name: verified_email
Priority: 1
MfaConfiguration: 'ON'
EnabledMfas:
- SOFTWARE_TOKEN_MFA #アプリケーションでのMFA
AutoVerifiedAttributes:
- email
LambdaConfig: #サインアップ前Lambdaトリガー
PreSignUp: !Sub 'arn:aws:lambda:ap-northeast-1:${AWS::AccountId}:function:${PJPrefix}-${Environment}-Lambda'
UpdateReplacePolicy: Retain
DeletionPolicy: Delete
#ユーザープールドメイン作成
UserPoolDomain:
Type: AWS::Cognito::UserPoolDomain
Properties:
Domain: !Sub '${PJPrefix}-${Environment}-domain'
UserPoolId: !Ref UserPool
#アプリケーション統合作成
AppIntegration:
Type: AWS::Cognito::UserPoolClient
Properties:
CallbackURLs:
- https://www.yahoo.co.jp/
ClientName: !Sub '${PJPrefix}-${Environment}-cognito-app'
UserPoolId: !Ref UserPool
RefreshTokenValidity: 1
SupportedIdentityProviders:
- COGNITO
AllowedOAuthFlows:
- code
AllowedOAuthScopes:
- openid
LambdaPermission:
Type: 'AWS::Lambda::Permission'
Properties:
FunctionName:
Fn::ImportValue:
!Sub '${PJPrefix}-${Environment}-Lambda-Singin-Output'
Action: "lambda:InvokeFunction"
Principal: "cognito-idp.amazonaws.com"
SourceArn: !GetAtt UserPool.Arn
事後確認
正常に構築ができたか確認していきます。
Cognitoのアプリケーション統合から「ホストされたUIを表示」をクリックします。
そこでGmailでのみサインアップでき、Gmail以外の場合はエラーとなることを確認してください。
Gmail以外でサインアップしようとした場合、【Invalid lambda function output : Invalid JSON】と表示されれば完了です。
不具合などがあった場合、Lambdaトリガーの紐づけがきちんと行われていない場合があるので、
CognitoのユーザープールのプロパティにてLambdaトリガーの更新をしてから保存を実施してみてください。
不具合が解消される場合があります。
最後に
こちらでCognitoのサインアップ前トリガーを導入する手順は完了です。
参考になれば、幸いです。
参考サイト
Lambda
Cognito