自定义SMS发件人 Lambda 触发器 - Amazon Cognito

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

自定义SMS发件人 Lambda 触发器

当您为用户池分配自定义发SMS件人触发器时,当用户事件要求其发送消息时,Amazon Cognito 会调用 Lambda 函数,而不是其默认行为。SMS使用自定义发件人触发器,您的 AWS Lambda 函数可以通过您选择的方法和提供商向用户发送SMS通知。您的函数的自定义代码必须处理和传送用户池中的所有SMS消息。

此触发器适用于您可能希望更好地控制用户池发送SMS消息的方式。您的 Lambda 函数可以自定义对 Amazon SNS API 操作的调用,例如,当您想要管理多个起源或IDs交叉时。 AWS 区域您的函数还可能将消息重定向到其他传送媒体或第三方服务。

注意

目前,您无法在 Amazon Cognito 控制台中分配自定义发件人触发器。您可以在CreateUserPoolUpdateUserPoolAPI请求中为触发器分配带LambdaConfig参数的触发器。

要设置此触发器,请执行以下步骤:

  1. 在 AWS Key Management Service (AWS KMS) 中创建对称加密密钥。Amazon Cognito 会生成密钥(临时密码、验证码和确认码),然后使用此密钥对机密进行加密。KMS然后,您可以在 Lambda 函数中使用解密API操作来解密密密钥并将其以明文形式发送给用户。AWS Encryption SDK是对函数进行 AWS KMS 操作的有用工具。

  2. 创建一个您要分配为自定义发件人触发器的 Lambda 函数。向 Lambda 函数kms:Decrypt角色授予KMS密钥权限。

  3. 授予 Amazon Cognito 服务主体 cognito-idp.amazonaws.com 访问权限,以调用 Lambda 函数。

  4. 编写 Lambda 函数代码,将您的消息定向到自定义传递方法或第三方提供商。要传递用户的验证码或确认码,请对请求中 code 参数的值进行 Base64 解码和解密。此操作将生成必须包含在消息中的明文代码或密码。

  5. 更新用户池,使其使用自定义发件人 Lambda 触发器。使用自定义发送者触发器更新或创建用户池的IAM委托人必须有权为您的KMS密钥创建授权。以下LambdaConfig代码段分配了自定义函数SMS和电子邮件发件人函数。

    "LambdaConfig": { "KMSKeyID": "arn:aws:kms:us-east-1:123456789012:key/a6c4f8e2-0c45-47db-925f-87854bc9e357", "CustomEmailSender": { "LambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:MyFunction", "LambdaVersion": "V1_0" }, "CustomSMSSender": { "LambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:MyFunction", "LambdaVersion": "V1_0" }

自定义SMS发件人 Lambda 触发器参数

Amazon Cognito 传递给此 Lambda 函数的请求是以下参数和 Amazon Cognito 添加到所有请求中的常用参数的组合。

JSON
{ "request": { "type": "customSMSSenderRequestV1", "code": "string", "clientMetadata": { "string": "string", . . . }, "userAttributes": { "string": "string", . . . } }

自定义SMS发件人请求参数

type

请求版本。对于自定义SMS发送者事件,此字符串的值始终为customSMSSenderRequestV1

代码

您的函数可以解密并发送给您的用户的加密代码。

clientMetadata

您可以将一个或多个键值对作为自定义输入提供给自定义发送者 SMS Lambda 函数触发器。要将此数据传递给您的 Lambda 函数,您可以使用AdminRespondToAuthChallenge和 ClientMetadata RespondToAuthChallengeAPI操作中的参数。Amazon Cognito 在传递给身份验证后函数的请求中不包含来自 ClientMetadata 参数AdminInitiateAuthInitiateAuthAPI操作的数据。

userAttributes

表示用户属性的一个或多个键值对。

自定义SMS发件人响应参数

Amazon Cognito 不需要响应中任何额外的返回信息。您的函数可以使用API操作来查询和修改您的资源,或者将事件元数据记录到外部系统。

激活自定义SMS发送器 Lambda 触发器

您可以设置自定义发SMS件人触发器,该触发器使用自定义逻辑向您的用户池发送SMS消息。以下过程将自定义SMS触发器、自定义电子邮件触发器或两者分配给您的用户池。添加自定义发SMS件人触发器后,Amazon Cognito 始终将用户属性(包括电话号码和一次性代码)发送到您的 Lambda 函数,而不是SMS使用亚马逊简单通知服务发送消息的默认行为。

重要

Amazon HTML Cognito 会对用户临时密码中的 < (&lt;) 和 > (&gt;) 等保留字符进行转义。这些字符可能出现在 Amazon Cognito 发送到您的自定义电子邮件发件人函数的临时密码中,但不会出现在临时验证码中。要发送临时密码,您的 Lambda 函数在解密密码之后必须取消对这些字符的转义,然后再将消息发送给您的用户。

  1. 在 AWS KMS中创建加密密钥。此密钥加密 Amazon Cognito 生成的临时密码和授权代码。然后,您可以在自定义发件人 Lambda 函数中解密这些密钥,将其以明文形式发送给用户。

  2. 向 Amazon Cognito 服务主体授予使用密钥加密代码的cognito-idp.amazonaws.comKMS访问权限。

    将以下基于资源的策略应用于您的KMS密钥。

    { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": "cognito-idp.amazonaws.com" }, "Action": "kms:CreateGrant", "Resource": "arn:aws:kms:us-west-2:111222333444:key/1example-2222-3333-4444-999example", "Condition": { "StringEquals": { "aws:SourceAccount": "111222333444" }, "ArnLike": { "aws:SourceArn": "arn:aws:cognito-idp:us-west-2:111222333444:userpool/us-east-1_EXAMPLE" } } }] }
  3. 为自定义发件人触发器创建 Lambda 函数。Amazon Cognito 使用AWS 加密SDK来加密授权用户API请求的机密、临时密码和代码。

    1. 为您的 Lambda 函数分配一个至少具有密钥kms:DecryptKMS权限的IAM角色。

  4. 授予 Amazon Cognito 服务主体 cognito-idp.amazonaws.com 访问权限,以调用 Lambda 函数。

    以下 AWS CLI 命令授予 Amazon Cognito 调用您的 Lambda 函数的权限:

    aws lambda add-permission --function-name lambda_arn --statement-id "CognitoLambdaInvokeAccess" --action lambda:InvokeFunction --principal cognito-idp.amazonaws.com
  5. 编写 Lambda 函数代码以发送消息。在 Amazon Cognito 将机密发送 AWS Encryption SDK 给自定义发件人 Lambda 函数之前,Amazon Cognito 使用它来加密机密。在您的函数中,解密密钥并处理任何相关的元数据。然后将验证码、您自己的自定义消息和目标电话号码发送给发送API消息的自定义机构。

  6. 将 AWS Encryption SDK 添加到您的 Lambda 函数中。有关更多信息,请参阅AWS 加密SDK编程语言。要更新 Lambda 包,请完成以下步骤:

    1. 在 AWS Management Console中将您的 Lambda 函数作为.zip 文件导出。

    2. 打开您的函数并添加 AWS Encryption SDK. 有关更多信息和下载链接,请参阅 AWS Encryption SDK Developer Guide(《Crypto SDK 开发人员指南》)中的 AWS Encryption SDK 编程语言

    3. 使用SDK依赖项压缩您的函数,然后将该函数上传到 Lambda。有关更多信息,请参阅《AWS Lambda 开发人员指南》中的将 Lambda 函数部署为 .zip 文件归档

  7. 更新用户群体,添加自定义发件人 Lambda 触发器。在UpdateUserPoolAPI请求中包含CustomSMSSenderCustomEmailSender参数。该UpdateUserPoolAPI操作需要用户池的所有参数以及您要更改的参数。如果您没有提供所有相关参数,Amazon Cognito 会将任何缺失参数的值设置为其原定设置。如以下示例所示,包括您想要添加到或保留在用户群体中的所有 Lambda 函数的条目。有关更多信息,请参阅 更新用户池和应用程序客户端配置

    #Send this parameter in an 'aws cognito-idp update-user-pool' CLI command, including any existing #user pool configurations. --lambda-config "PreSignUp=lambda-arn, \ CustomSMSSender={LambdaVersion=V1_0,LambdaArn=lambda-arn}, \ CustomEmailSender={LambdaVersion=V1_0,LambdaArn=lambda-arn}, \ KMSKeyID=key-id"

要删除带有的自定义发件人 Lambda 触发器 update-user-pool AWS CLI,请省略CustomSMSSenderCustomEmailSender参数--lambda-config,并包含您要与用户池一起使用的所有其他触发器。

要删除带有UpdateUserPoolAPI请求的自定义发送者 Lambda 触发器,请省略包含用户池其余配置的请求正文中的CustomSMSSenderCustomEmailSender参数。

代码示例

以下 Node.js 示例在您的自定义SMS发送器 Lambda 函数中处理SMS消息事件。此示例假设您的函数定义了两个环境变量。

KEY_ALIAS

您要用来加密和解密用户代码的密KMS钥的别名

KEY_ARN

您要用于加密和解密用户KMS代码的密钥的 Amazon 资源名称 (ARN)。

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 == 'CustomSMSSender_SignUp'){ //Send an SMS message to your user via a custom provider. //Include the temporary password in the message. } else if(event.triggerSource == 'CustomSMSSender_ResendCode'){ } else if(event.triggerSource == 'CustomSMSSender_ForgotPassword'){ } else if(event.triggerSource == 'CustomSMSSender_UpdateUserAttribute'){ } else if(event.triggerSource == 'CustomSMSSender_VerifyUserAttribute'){ } else if(event.triggerSource == 'CustomSMSSender_AdminCreateUser'){ } else if(event.triggerSource == 'CustomSMSSender_AccountTakeOverNotification'){ } return; };

使用自定义SMS发件人函数评估SMS消息功能

自定义SMS发送者 Lambda 函数接受您的用户池将要发送的SMS消息,该函数根据您的自定义逻辑传递内容。Amazon Cognito 将 自定义SMS发件人 Lambda 触发器参数 发送到您的函数。您的函数可以用这些信息做您想做的事。例如,您可以将代码发送到亚马逊简单通知服务 (AmazonSNS) 主题。Amazon SNS 主题订阅者可以是SMS消息、HTTPS终端节点或电子邮件地址。

要使用自定义发件人 SMS Lambda 函数为 Amazon Cognito SMS 消息传递创建测试环境,请参阅上的 aws-samp amazon-cognito-user-poolles development-and-testing-with 库sms-redirected-to-email中的--。 GitHub存储库包含可以创建新用户池或使用已有的用户池的 AWS CloudFormation 模板。这些模板创建 Lambda 函数和亚马逊SNS主题。模板指定为自定义发SMS件人触发器的 Lambda 函数会将您的SMS消息重定向到亚马逊主题的订阅者。SNS

当您将此解决方案部署到用户池时,Amazon Cognito 通常通过SMS消息发送的所有消息,Lambda 函数会改为发送到中央电子邮件地址。使用此解决方案自定义和预览SMS消息,并测试导致 Amazon Cognito 发送SMS消息的用户池事件。完成测试后,回滚 CloudFormation 堆栈,或者从用户池中移除自定义SMS发送器函数分配。

重要

不要使用 amazon-cognito-user-pool-development-and-testing-with- 中的模板sms-redirected-to-email来构建生产环境。解决方案中的自定义SMS发件人 Lambda 函数模拟SMS消息,但 Lambda 函数会将它们全部发送到一个中央电子邮件地址。在生产 Amazon Cognito 用户池中发送SMS消息之前,必须先完成中显示的要求。SMSAmazon Cognito 用户池的消息设置

自定义SMS发件人 Lambda 触发源

下表显示了 Lambda 代码中自定义SMS触发源的触发事件。

TriggerSource value 事件
CustomSMSSender_SignUp 用户注册,Amazon Cognito 随即发送欢迎消息。
CustomSMSSender_ForgotPassword 用户请求代码以重置其密码。
CustomSMSSender_ResendCode 用户请求新代码以确认其注册。
CustomSMSSender_VerifyUserAttribute 用户创建新电子邮件地址或电话号码属性,而 Amazon Cognito 将发送代码用于验证该属性。
CustomSMSSender_UpdateUserAttribute 用户更新电子邮件地址或电话号码属性,而 Amazon Cognito 将发送代码用于验证该属性。
CustomSMSSender_Authentication 配置了SMS多重身份验证 (MFA) 的用户登录。
CustomSMSSender_AdminCreateUser 您在用户池中创建新用户,而 Amazon Cognito 向其发送临时密码。