キャリアメール文字化け
CognitoIdentityServiceProviderのadminUpdateUserAttributes関数を用いてメール認証やメール変更を行なっているところ、キャリアメールの場合文字化け現象が起きてしまいました。
原因はキャリアメールの場合、OSのメッセージアプリを使ってメール受信するから、送信者と受信者でメールソフトのエンコードが異なると文字化けが発生してしまいます。
SESマルチパート配信
SESを用いて、マルチパート配信すれば、解決できます。SESマルチパートについて、前の記事に書きましたので、ここでは述べません。
アーキテクチャー
CognitoIdentityServiceProviderのadminUpdateUserAttributesでカスタムEメール送信者Lambdaトリガー起動させて、Lambda関数でSESマルチパート配信を行う
Cognito Lambdaトリガーによるマルチパート配信
注意点
- カスタムEメール送信者LambdaトリガーはコンソールやCloudFormationから作成できないので、AWS CLIを利用する
- カスタムメッセージLambdaトリガーでは「確認コードを配置するためのプレースホルダー」が渡されるが、カスタムEメール送信者Lambdaトリガーでは「KMSキーで暗号化された確認コード」が渡される
- 渡されたコードを復号処理しないといけない
本件と関係ないですが、追伸となります:
カスタムメッセージLambdaトリガーでメール送信する際、 Lambda関数にてメール送信処理まで実施する必要はないです。カスタムメッセージレスポンスパラメータを Lambda 関数での return としていただけますと、その内容に基づいて Cognito 側がメール送信処理を実施します。
"response": {
"smsMessage": "string",
"emailMessage": "string",
"emailSubject": "string"
}
KMS Keyを作成する
AWS Key Management Service (AWS KMS) で対称暗号化キーを作成します
Lambda作成
カスタム送信者のトリガーとして割り当てる Lambda 関数を作成します。Lambda 関数ロールに対して、KMS キーへの kms:Decrypt アクセス許可を付与します。
const AWS = require('aws-sdk');
const b64 = require('base64-js');
const encryptionSdk = require('@aws-crypto/client-node');
//Configure the encryption SDK client with the KMS key from the environment variables.
const { encrypt, decrypt } = encryptionSdk.buildClient(encryptionSdk.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT);
const generatorKeyId = process.env.KEY_ALIAS;
const keyIds = [ process.env.KEY_ARN ];
const keyring = new encryptionSdk.KmsKeyringNode({ generatorKeyId, keyIds })
exports.handler = async (event) => {
//Decrypt the secret code using encryption SDK.
let plainTextCode;
if(event.request.code){
const { plaintext, messageHeader } = await decrypt(keyring, b64.toByteArray(event.request.code));
plainTextCode = plaintext
}
//PlainTextCode now contains the decrypted secret.
if(event.triggerSource == 'CustomEmailSender_SignUp'){
//Send an email message to your user via a custom provider.
//Include the temporary password in the message.
}
else if(event.triggerSource == 'CustomEmailSender_ResendCode'){
}
else if(event.triggerSource == 'CustomEmailSender_ForgotPassword'){
}
else if(event.triggerSource == 'CustomEmailSender_UpdateUserAttribute'){
}
else if(event.triggerSource == 'CustomEmailSender_VerifyUserAttribute'){
}
else if(event.triggerSource == 'CustomEmailSender_AdminCreateUser'){
}
else if(event.triggerSource == 'CustomEmailSender_AccountTakeOverNotification'){
}
return;
};
Lambdaイベントからもらったcodeはkmsキーを用いて復号処理しないといけない
呼び出し権限
Amazon Cognito サービスプリンシパルに、Lambda 関数を呼び出すための cognito-idp.amazonaws.com へのアクセス権を付与します。
コンソール画面からも追加できますが、AWS CLIでも追加できます。
Lambda>関数>[function name]>アクセス権限を追加
- AWS CLI
aws lambda add-permission \ --function-name <lambda_arn> \ --statement-id "CognitoLambdaInvokeAccess" \ --action lambda:InvokeFunction \ --principal cognito-idp.amazonaws.com
Cognitoにトリガーを設定
ここは注意点あります。カスタムEメール送信者LambdaトリガーはコンソールやCloudFormationから作成できないので、AWS CLIを利用します。
# 既存の設定の確認
aws cognito-idp describe-user-pool --user-pool-id YOUR_USER_POOL_ID
# トリガー作成
aws cognito-idp update-user-pool \
--userpool-id <userpool_id> \
--lambda-config "CustomEmailSender={LambdaVersion=V1_0,LambdaArn= <lambda_arn> },KMSKeyID= <key_id>" \
--auto-verified-attributes email
AWS ドキュメントに--auto-verified-attributes emailのオプションが必要だと書かれていませんが、実行すると[Cognitoが検証と確認のためにメッセージを自動的に送信することを許可]の値が[無効]となってしまい、メール送信自体できなくなります。そのオプションを忘れずにつけてください。
おまけ
トリガーだけ削除したい時、下記のコマンドで追加したトリガーをリセットします。
aws cognito-idp update-user-pool \
--userpool-id <userpool_id> \
--lambda-config "{}"
AWS Cognito APIでトリガー
トリガーするAPIは下記のAWSドキュメンに書いてますが、キャプチャーを貼ります。
参考