如何在 Amazon Cognito 使用者集區中使用自訂電子郵件寄件者 Lambda 觸發機制?

4 分的閱讀內容
0

我必須調用 Amazon Cognito 自訂電子郵件寄件者 AWS Lambda 觸發機制來處理和傳遞電子郵件訊息。

解決方法

使用 Amazon Cognito 自訂電子郵件寄件者觸發機制,允許第三方供應商從 Lambda 函數程式碼傳送電子郵件通知給您的使用者。Amazon Cognito 會將電子郵件訊息請求傳送至 Lambda 函數。然後,Lambda 函數會處理並傳遞電子郵件訊息。

建立 Lambda 函數,做為您的自訂電子郵件傳送者觸發機制

  1. 建立名稱為 index.js 的檔案,將下列程式碼新增至檔案,然後儲存變更。
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 has the decrypted secret.

if(event.triggerSource == 'CustomEmailSender_SignUp'){

// Send email to end-user using custom or 3rd party provider.
// Include temporary password in the email.

console.log("CustomEmailSender_SignUp: " + plainTextCode);

}else if(event.triggerSource == 'CustomEmailSender_ResendCode'){
console.log("CustomEmailSender_ResendCode: " + plainTextCode);

}else if(event.triggerSource == 'CustomEmailSender_ForgotPassword'){
console.log("CustomEmailSender_ForgotPassword: " + plainTextCode);

}else if(event.triggerSource == 'CustomEmailSender_UpdateUserAttribute'){
console.log("CustomEmailSender_UpdateUserAttribute: " + plainTextCode);

}else if(event.triggerSource == 'CustomEmailSender_VerifyUserAttribute'){
console.log("CustomEmailSender_VerifyUserAttribute: " + plainTextCode);

}else if(event.triggerSource == 'CustomEmailSender_AdminCreateUser'){
console.log("CustomEmailSender_AdminCreateUser: " + plainTextCode);

}else if(event.triggerSource == 'CustomEmailSender_AccountTakeOverNotification'){
console.log("CustomEmailSender_AccountTakeOverNotification: " + plainTextCode);
}

return;
};

**警告:**此程式碼會透過指令碼來解密已加密的保密內容。保密內容是由 Amazon Cognito 傳送的臨時密碼和授權碼。此指令碼也會在日誌中列印純文字程式碼,以供示範之用。但是,以純文字記錄保密內容是一項安全問題。當您的應用程式在生產環境中時,請勿在日誌中列印已解密的保密內容。

在 index.js 檔案中新增相關程式碼,以便從您的自訂電子郵件提供者傳送電子郵件訊息給使用者。

  1. 建立一個 .zip 封存檔,也稱為一個壓縮的 index.js 檔案:
$ zip function.zip index.js
  1. 開啟 Lambda 主控台

  2. 使用 Node.js 執行階段建立一個 Lambda 函數

以下是使用 Node.js 14.x 執行階段建立 Lambda 函數的 AWS Command Line Interface (AWS CLI) 命令範例。

**注意:**如果您在執行 AWS CLI 命令時收到錯誤訊息,請確定您使用的是最新版本的 AWS CLI

$ aws lambda create-function --function-name CustomEmailSender --runtime nodejs14.x --handler index.handler --zip-file fileb://function.zip --role <ExecutionRoleARN> --region <specify a region>

**注意:替換<ExecutionRoleARN>使用您想要與 Lambda 函數建立關聯的 AWS Identity and Access Management (IAM) 角色的 Amazon Resource Name (ARN)。如需詳細資訊,請參閱 Lambda 執行角色。您可以用您選擇的函數名稱替換「CustomEmailSender」。替換<specify a region>**使用您的 AWS 區域代碼。

  1. 安裝 @aws-crypto/client-node 模組以便使用 AWS Encryption SDK。

如果您沒有安裝 @aws-crypto/client-node 模組,則必須完成下列高階工作:

  • 安裝模組。
  • 封裝最新版本的模組。
  • 建立 Lambda 層,其中包含可與 Lambda 函數搭配使用的相依性。

**注意:**在與 Lambda 相容的本機開發環境中執行安裝命令。

建立工作目錄:

$ mkdir -p aws-crypto-layer/nodejs

變更工作目錄:

$ cd aws-crypto-layer/nodejs

使用 npm 軟體封裝管理工具,安裝最新版本的 aws-crypto 模組:

$ npm install @aws-crypto/client-node

**注意:**在開發 Lambda 資源時,使用 Amazon Linux 2 環境是最佳做法。當您使用 Windows 或 macOS 作業系統進行開發時,請使用 Docker 來安裝 aws-Crypto 模組:

$ docker run --entrypoint "" -v "$PWD":/var/task "public.ecr.aws/lambda/nodejs:14" /bin/sh -c "npm install @aws-crypto/client-node; exit"

建立要上傳至 Lambda 層的 .zip 檔案:

$ zip -r ../package.zip ../

建立包含最新版本 @aws-crypto/client-node 模組的 Lambda 層:

$ aws lambda publish-layer-version --layer-name node_crypto --description "My layer" --license-info "MIT" --compatible-runtimes nodejs14.x --zip-file fileb://../package.zip --region <specify a region>

將 Lambda 層添加到您的函數中:

$ aws lambda update-function-configuration --function-name CustomEmailSender --layers arn:aws:lambda:us-east-2:123456789012:layer:node_crypto:1 --region <specify a region>

注意:用您的函數名稱替換「CustomEmailSender」。使用 publish-layer-version 命令輸出中的LayerVersionArn 值,替換「arn:aws:lambda:us-east-2:123456789012:layer:node_crypto:1」。替換**<specify a region>**使用您的區域代碼。

在 AWS KMS 中建立加密金鑰

Amazon Cognito 使用 AWS Key Management Service (KMS) 對稱加密金鑰來加密由 Amazon Cognito 產生的臨時密碼和授權碼。

  1. 建立 AWS KMS 金鑰:
$ aws kms create-key --description "KMS Key for CustomEmailSender" --region <specify a region>

**注意:替換<specify a region>**使用您的區域代碼。

由於此命令不會指定金鑰原則,因此會指派預設金鑰原則。若要將自訂金鑰原則套用至您的 AWS KMS 金鑰,請使用 JSON 原則--policy 參數新增到命令中。請確定您已將 kms:CreateGrant 權限授予執行 UpdateUserPool 作業的 IAM 實體,以便新增自訂電子郵件觸發機制。

當您執行create-key 命令時,您無法指定別名。若要為新 KMS 金鑰建立別名,請使用 create-alias 命令:

$ aws kms create-alias --alias-name alias/custom-email-key --target-key-id <KeyId> --region <specify a region>

**注意:替換<KeyId>使用 create-key 命令輸出中的密鑰 ID 值。替換<specify a region>**使用您的區域代碼。

此程式碼範例依賴環境變數 KEY_ALIASKEY_ARN 來取得加密金鑰資訊。您必須在 CustomEmailSender 的Lambda 觸發機制中設定這些環境變數。

$ aws lambda update-function-configuration --function-name CustomEmailSender --environment 'Variables={KEY_ALIAS=alias/custom-email-key,KEY_ARN=<key_ARN>}' --region <specify a region>

注意:使用您的 Lambda 函數名稱替換**「CustomEmailSender**」。使用您 AWS KMS 金鑰的金鑰別名替換「alias/custom-email-key」。使用 create-key 命令輸出中的 ARN 值替換「<key_ARN>」。替換**<specify a region>**使用您的區域代碼。

授予 Amazon Cognito 主體調用 Lambda 函數的 cognito-idp.amazonaws.com 權限

使用下列命令將權限授予 Amazon Cognito 服務主體,以便調用 Lambda 函數:

$ aws lambda add-permission --function-name CustomEmailSender --statement-id "CognitoLambdaInvokeAccess" --action lambda:InvokeFunction --principal cognito-idp.amazonaws.com --source-arn <UserPoolArn> --region <specify a region>

注意:使用您的 Lambda 函數名稱替換**「CustomEmailSender**」。替換**<UserPoolArn>即使用您的使用者集區 ARN。若要尋找使用者集區 ARN,請開啟 Amazon Cognito 主控台使用者集區頁面。然後從清單中選取使用者集區。或者,執行 describe-user-pool 命令。替換<specify a region>**使用您的區域代碼。

更新 Amazon Cognito 使用者集區,讓其使用自訂電子郵件寄件者 Lambda 觸發機制

UpdateUserPool API 中設定 CustomEmailSender 參數來更新使用者集區。UpdateUserPool 需要使用者集區的所有現有參數以及您要變更的參數。Amazon Cognito 會將任何缺少參數的值設為預設值。如需詳細資訊,請參閱更新使用者集區組態

在下列範例中,只有 --lambda-config 參數與 CustomEmailSender Lambda 函數詳細資料搭配使用。因此,該命令會將自訂電子郵件寄件者觸發機制新增至您的使用者集區,並將其餘的使用者集區參數設為預設值。如果您使用非預設值設定使用者集區,請傳遞 update-user-pool 命令中的值,避免參數被設為預設值。

$ aws cognito-idp update-user-pool --lambda-config "CustomEmailSender={LambdaVersion=V1_0,LambdaArn= <LambdaArn>},KMSKeyID=<KMSKeyArn>" --user-pool-id <UserPoolId> --region <specify a region>

**注意:替換<LambdaArn>使用來自 create-function 命令輸出的函數 ARN 值。替換<KMSKeyArn>使用 create-key 命令輸出中提供的 ARN 值。替換<UserPoolId>使用您的 Amazon Cognito 使用者集區 ID。替換<specify a region>**使用您的區域代碼。

測試功能

若要測試 Lambda 函數的整合,請從使用者集區模擬使用者的電子郵件傳送者作業,例如電子郵件驗證或密碼復原。下列範例顯示由 Amazon Cognito 傳送至 Lambda 函數的 ForgotPassword 事件。

{
  version: '1',
  triggerSource: 'CustomEmailSender_ForgotPassword',
  region: 'us-east-1',
  userPoolId: 'us-east-1_xxxxxxxx',
  userName: 'example_user',
  callerContext: {
    awsSdkVersion: 'aws-sdk-unknown-unknown',
    clientId: '12a3b4example-clientid'
  },
  request: {
    type: 'customEmailSenderRequestV1',
    code: 'XXXXeBlI7XP3RQmipedVF+7OGa4AgQACABVhdXXXXXXXvLXB1YmxpYy1rZXkAREF6Zk9NR2lBR0FUeDRITStmRHl4RDJyNlpqa2wvWktBbG45ckRmTEpMZ1A3THp4ME9RaVVjVHl3MVFOSEZjS3piZz09AAt1c2VycG9vbC1pZAATdXMtZWFzdC0xX29DOUhnUHVKWgABAAdhd3Mta21zAEthcm46XXdzOmttczp1cy1lYXN0LTE6XXX3XXc0NDA5OXXzOmtleS8yNmQ0ZjVmMy00YmZhLTQ0OXXtODUxZS01ZTM2ZWIwYjhmYjMAuAECAQB42Am0o+Rx0MgG+wLLyKtm1/vTm03JK3jQBZxqABAkreYBMOoAUtm3mLS7+kb2VL0SHgAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHjPPHlSWPt+UKrQOQIBEIA7oFUeGe2NPX2cuEVi+Qxwp8/IH1bgyYQut+QbbkElc1rXXXXXbeEVMjMkFQmQufmJyag9v1f+PUalvXwXAAAAAAwAABAAAAAAAAAAAAAAAAAAscZHg8dY/cKTskGQc065mv////8AAAABAAAAAAAAAAAAAAABAAAABpofXaVnP4pmf+yMoCElrOGy7Gn8pIUAZzBlAjEAn/7tuTNko8/HCwXXXXlCOJDeU0SSyB7o9y0TXHM7GptdvmB1JL9OzLxmUg6zChIhAjAFFbH4NrSblvwh/m0inDc11BpeOSKghtg8Pg5Nkf8eY6vmXX6GxjaCuyhBSO7IDcM=',
    clientMetadata: null,
    userAttributes: {
      sub: '1a2b3cde-33cd-402f-5g67-examplesub',
      'cognito:user_status': 'CONFIRMED',
      email_verified: 'true',
      email: 'user@example.com'
    }
  }
}

下列範例是純文字程式碼的回應:

CustomEmailSender_ForgotPassword: 12345

您可以在為 Lambda 函數建立的 Amazon CloudWatch 日誌群組中查看完整的日誌。若要深入了解如何查看這些日誌,請參閱存取 AWS Lambda 的 Amazon CloudWatch 日誌

AWS 官方
AWS 官方已更新 1 年前