[アップデート] Amazon Cognito User pool の多要素認証に E メールを利用可能になったので AWS CDK で設定してみた
こんにちは、製造ビジネステクノロジー部の若槻です。
最近の Amazon Cognito のアップデートで、User pool へのサインイン時の多要素認証に E メールを利用可能になりました。
そしてこの E メールベースの多要素認証が AWS CDK でも v2.164.0 から L2 Construct で簡単に実装可能になりました。
cognito: support email based MFA (#31816) (f9d6eef), closes #31815
今回は、実際に Cognito user pool の E メールベースの多要素認証を AWS CDK で有効化してみました。
試してみた
CDK パッケージのアップデート
AWS CDK モジュールを v2.164.0 以上にアップデートします。
npm i aws-cdk-lib@latest aws-cdk@latest
メール送信元アドレスを SES の Identity として承認する
MFA としてメールを利用するためには、メール送信元アドレスを SES の Identity として承認する必要があります。今回だと後述の CDK コード中の noreply@${COGNITO_FROM_EMAIL_DOMAIN_NAME}
のアドレスを承認します。
メールアドレスの承認も CDK で行うことができます。今回は以下記事を参考にして事前に実装しました。
E メールベースの多要素認証を CDK で有効化する
Cognito user pool の E メールベースの多要素認証を AWS CDK で有効化するコードです。
import * as cdk from 'aws-cdk-lib';
import * as cognito from 'aws-cdk-lib/aws-cognito';
import { Construct } from 'constructs';
export class Main2Stack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
const region = this.region;
const COGNITO_FROM_EMAIL_DOMAIN_NAME = process.env.DOMAIN_NAME || '';
const COGNITO_DOMAIN_PREFIX = 'cm-test-20241110';
const CALLBACK_URLS = ['https://dev.classmethod.jp/'];
const LOGOUT_URLS = ['https://dev.classmethod.jp/'];
const TEST_USER_EMAIL_ADDRESS = process.env.TEST_USER_EMAIL_ADDRESS || '';
/**
* Cognito User Pool
*/
const userPool = new cognito.UserPool(this, 'UserPool', {
selfSignUpEnabled: true,
signInAliases: {
email: true,
},
autoVerify: {
email: true,
},
// 前提1: メールプロバイダーとして SES が設定されていること
email: cognito.UserPoolEmail.withSES({
sesRegion: region, // CDK 上ではオプションだが、実際には指定必須
fromEmail: `noreply@${COGNITO_FROM_EMAIL_DOMAIN_NAME}`,
}),
mfa: cognito.Mfa.REQUIRED,
mfaSecondFactor: {
sms: true,
otp: false,
email: true, // e-mail による MFA の有効化
},
// 前提2: 高度なセキュリティ機能が有効化されていること
advancedSecurityMode: cognito.AdvancedSecurityMode.ENFORCED,
removalPolicy: cdk.RemovalPolicy.DESTROY, // 検証用リソースのため削除を許可
});
/**
* Cognito User Pool Domain
*/
userPool.addDomain('UserPoolDomain', {
cognitoDomain: { domainPrefix: COGNITO_DOMAIN_PREFIX },
});
/**
* Cognito User Pool Client
*/
userPool.addClient('UserPoolClient', {
generateSecret: false,
oAuth: {
callbackUrls: CALLBACK_URLS,
logoutUrls: LOGOUT_URLS,
flows: { authorizationCodeGrant: true },
},
});
/**
* Cognito User Pool User
* 動作確認用のユーザーを作成
*/
const userPoolUser = new cognito.CfnUserPoolUser(this, 'UserPoolUser', {
userPoolId: userPool.userPoolId,
username: TEST_USER_EMAIL_ADDRESS,
});
userPoolUser.node.addDependency(userPool);
}
}
UserPool コンストラクトクラス の mfaSecondFactor
で email
オプションが利用可能になっており、true
を指定することで、メールによる MFA を有効化できます。
また E メールベースの多要素認証の有効化の前提として、メールプロバイダーとして SES が設定され、また高度なセキュリティ機能 (Advanced security features)が有効化されていることが必要なので、それらもコード中で設定しています。
上記実装を CDK Deploy によりデプロイします。
デプロイ後の設定の確認
デプロイにより構築された User pool の設定をマネジメントコンソールから確認してみます。
ユーザープールの高度なセキュリティ機能が有効化され、その中で Add an email option to MFA が有効化されています。
また、Sign-in experience で MFA methods として Email message
が追加されています。
E メールによる MFA の動作確認
User pool の Hosted UI にアクセスし、ユーザー名とパスワードを入力してサインインを試みます。
するとコードがメールで送信されます。
このようなコードが記載されたメールが届くので、そのコードを入力します。
サインインが成功し、コールバック URL にリダイレクトされました。良さそうですね。
トラブルシュート
送信元メールアドレスが SES で未承認
CDK デプロイ時に次のようなエラーが発生する場合。
$ npm run deploy
> [email protected] deploy
> cdk deploy --require-approval never --method=direct
✨ Synthesis time: 5.41s
Main: deploying... [1/1]
Main: updating stack...
5:17:52 PM | UPDATE_FAILED | AWS::Cognito::UserPool | MyUserPoolD09D1D74
Resource handler returned message: "Cognito received the following error from Amazon SES when attempting to send email: Email address is not verified. The following identities failed the check in region AP-NORTHEAST-1: ar
n:aws:ses:ap-northeast-1:XXXXXXXXXXXX:identity/[email protected] (Service: CognitoIdentityProvider, Status Code: 400, Request ID: 7061cfbb-a6ff-4bb6-9382-b7fe47b22241)" (RequestToken: c57a9893-597f-de1
e-b300-54c21483eb48, HandlerErrorCode: InvalidRequest)
❌ Main failed: The stack named Main failed to deploy: UPDATE_ROLLBACK_COMPLETE: Resource handler returned message: "Cognito received the following error from Amazon SES when attempting to send email: Email address is not verified. The following identities failed the check in region AP-NORTHEAST-1: arn:aws:ses:ap-northeast-1:XXXXXXXXXXXX:identity/[email protected] (Service: CognitoIdentityProvider, Status Code: 400, Request ID: 7061cfbb-a6ff-4bb6-9382-b7fe47b22241)" (RequestToken: c57a9893-597f-de1e-b300-54c21483eb48, HandlerErrorCode: InvalidRequest)
送信元ドメインだけでなく、送信元メールアドレスも SES で承認されている必要があります。「メール送信元アドレスを SES の Identity として承認する」の対応がまだの場合は実施するようにします。
SMS 認証の有効化が求められる
CDK デプロイ時に次のようなエラーが発生する場合。
$ npm run deploy -- Main2
> [email protected] deploy
> cdk deploy --require-approval never --method=direct Main2
✨ Synthesis time: 5.55s
Main2: start: Building 92788324c5fdf7bdf48905d6c954c3eee5acc57ef34779f164579f917c87b6a0:current_account-current_region
Main2: success: Built 92788324c5fdf7bdf48905d6c954c3eee5acc57ef34779f164579f917c87b6a0:current_account-current_region
Main2: start: Publishing 92788324c5fdf7bdf48905d6c954c3eee5acc57ef34779f164579f917c87b6a0:current_account-current_region
Main2: success: Published 92788324c5fdf7bdf48905d6c954c3eee5acc57ef34779f164579f917c87b6a0:current_account-current_region
Main2: deploying... [1/1]
Main2: creating stack...
8:14:37 PM | CREATE_FAILED | AWS::Cognito::UserPool | MyUserPool
Resource handler returned message: "SMS configuration and Auto verification for phone_number are required when MFA is required/optional (Service: CognitoIdentityProvider, Status Code: 400,
Request ID: 342f39fa-f7e7-4da6-8673-9feb85b00a71)" (RequestToken: 6d2d35ec-4994-e991-df00-34eb306ed79c, HandlerErrorCode: InvalidRequest)
MFA 有効時は SMS 認証が有効化されている必要があります。そのため、CDK の実装が次のようになっていることを確認します。
mfaSecondFactor: {
sms: true, // 有効である必要がある
otp: true,
email: true,
},
マネジメントコンソールから User pool の MFS を構成する際に下記のような注釈が表示されるので、MFA 有効化時は SMS 認証も有効化される必要があるようです。
This option must be selected because SMS is configured.
CDK 上では SMS 認証を無効化しても実際の設定では SMS 認証が有効化されている
前項は User pool 作成時のエラーですが、作成後に MFA を有効化した場合は SMS 認証を下記のように CDK 上で無効化することができます。
// 略
mfaSecondFactor: {
sms: false, // SMS 認証を無効化
otp: false,
email: true, // e-mail による MFA の有効化
},
// 略
しかしデプロイされた User pool の実際の MFA 設定では SMS 認証は有効化されたままとなっています。
エラーにならないため紛らわしいですが、作成後の User pool で有効化済みの MFA 設定ではこのような挙動となるようです。
参考
おわりに
今回は、Cognito user pool の E メールベースの多要素認証を AWS CDK で有効化する方法をご紹介しました。
E メールベースの多要素認証は、SMS に比べて利用者にとって利便性が高い場合が多いため、ユーザー体験の向上につながると思います。
以上