AmplifyプロジェクトでCognito送信者のLambdaトリガーを設定してみた
概要
- Amplifyプロジェクトで普通にAuthを追加してMFA対応していた
- SMS認証コードとEMail認証コードはそれぞれCognito標準機能を使っていたが、TwilioやSendGridなどの別サービスで送るための対応が必要になった
- Cognitoから認証コードを送るときに、カスタム送信できるような機構が用意されているので、それを利用
ドキュメントや参考になるブログ
対応方法
- AmplifyのCloud Formationに組み込みたかったが、現状、この機能はCloud Formationに対応されていないらしく、別途設定が必要になる
- KMS(AWSコンソール)から、「カスタマー管理型のキー」を作成する
- 特に考えずそのまま作成する
- Lambda Layerを作っておく
- Lambdaを用意する
- 公式ドキュメントにあるものを流用すれば良い
- handler関数では、Cognitoから発火されたイベント名をみて、処理をハンドリングしてあげる(TwilioやSendGridを使って認証コード送信を書く)
- LambdaにKMSの権限をアタッチしてあげる
- Lambdaの[設定]→[アクセス権限]→[実行ロール]からKMSの権限をアタッチする
Amazon Cognitoサービスプリンシパルに、Lambda関数を呼び出すための、cognito idp.amazonaws.com へのアクセス権を付与
aws lambda add-permission \ --function-name <作成したLambdaのARN> \ --statement-id "CognitoLambdaInvokeAccess" \ --action lambda:InvokeFunction \ --principal cognito-idp.amazonaws.com
Cognitoユーザープールを更新して、Lambdaトリガーを追加する
aws cognito-idp update-user-pool \ --user-pool-id <CognitoユーザープールID> \ --lambda-config "CustomSMSSender={LambdaVersion=V1_0,LambdaArn=<作成したLambdaのARN>},CustomEmailSender={LambdaVersion=V1_0,LambdaArn=<作成したLambdaのARN>},KMSKeyID=<作成したKMSのARN>" \ --profile <AWSのプロファイル>
間違ってLambdaトリガーを追加したときに解除するコマンド
aws cognito-idp update-user-pool \ --userpool-id <userpool_id> \ --lambda-config "{}"
ハマったところ
たまに認証コードが同じユーザーに2度送られる事象が発生
- SMS認証コードをTwilioのVerify APIを使って送信していたが、時たま、2度送られていた
- 設定したLambdaトリガーのログを見ていると、以下が出力されており、失敗したLambdaの約1分後に同じイベントが発火されていた。
Verify API処理が3秒超える場合がたまにあり、そのときに再度Lambdaが実行され2度送信されていることを確認
Task timed out after 3.00 seconds
対応方法
- Lambdaのタイムアウトをデフォルトの3秒から10秒に変更し、メモリも256mbに変更
- 設定値は、利用するサービス仕様に合わせる
カスタムLambdaトリガーが実行されない事象発生
- aws cognito-idp update-user-pool コマンドでLambdaカスタムトリガーを紐付けても、Lambdaが呼ばれない
- AmplifyでAuth追加した時点では、Cognitoの「どの属性を確認しますか?」の項目では、「Eメールまたは電話番号」を選択していたが、コマンド実行すると、「検証なし」に変更されていた。
対応方法
- aws cognito-idp update-user-pool コマンドのオプションに
auto-verified-attributes
を追加 - 上記オプションには、
sms-configuration
が必要になるsms-configuration
に指定には、「SMS 送信に使用する IAM ロールの ARN」と「SMS 送信に使用する IAM ロールの、信頼ポリシーに設定されている sts:ExternalId の値」が必要になる。- このIAMロールは、Amplifyで適切にAuth追加していると既に作成されているので、それを使う。
- Cognito(AWSコンソール)の「MFAそして確認」メニューの一番下に「新規ロール名」があるので、IAM(AWSコンソール)から検索して、信頼関係のタブを開くと「sts:ExternalId」の値が確認可能
aws cognito-idp update-user-pool \ --user-pool-id <CognitoユーザープールID> \ --lambda-config "CustomSMSSender={LambdaVersion=V1_0,LambdaArn=<作成したLambdaのARN>},CustomEmailSender={LambdaVersion=V1_0,LambdaArn=<作成したLambdaのARN>},KMSKeyID=<作成したKMSのARN>" \ --profile <AWSのプロファイル> \ --auto-verified-attributes {email,phone_number} \ --sms-configuration SnsCallerArn=<SMS 送信に使用する IAM ロールの ARN>,ExternalId=<SMS 送信に使用する IAM ロールの、信頼ポリシーに設定されている sts:ExternalId の値>