定义身份验证质询 Lambda 触发器 - Amazon Cognito

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

定义身份验证质询 Lambda 触发器

定义身份验证质询触发器是一个 Lambda 函数,用于在自定义身份验证流程中维护质询序列。它声明挑战序列的成败,如果序列尚未完成,则设置下一个挑战。

质询 Lambda 触发器
定义身份验证质询

Amazon Cognito 调用此触发器以启动自定义身份验证流程

此 Lambda 触发器的请求包括 sessionsession 参数是一个数组,包含在当前身份验证流程中向用户显示的所有质询。请求还包含相应的结果。session 数组按照时间顺序存储质询详细信息 (ChallengeResult)。质询 session[0] 表示用户收到的第一个质询。

您可以让 Amazon Cognito 在发出自定义质询之前验证用户密码。当您在自定义质询流程中执行SRP身份验证时,请求速率配额的身份验证类别中关联的任何 Lambda 触发器都将运行。过程概述如下:

  1. 您的应用程序使用 AuthParameters 映射来调用 InitiateAuthAdminInitiateAuth,以此来启动登录。参数必须包括 CHALLENGE_NAME: SRP_A, 以及 SRP_AUSERNAME 的值。

  2. Amazon Cognito 使用包含 challengeName: SRP_AchallengeResult: true 的初始会话,调用您定义的身份验证质询 Lambda 触发器。

  3. 在收到这些输入后,您的 Lambda 函数发出 challengeName: PASSWORD_VERIFIERissueTokens: falsefailAuthentication: false 响应。

  4. 如果密码验证成功,Amazon Cognito 会使用包含 challengeName: PASSWORD_VERIFIERchallengeResult: true 的新会话再次调用您的 Lambda 函数。

  5. 为了启动您的自定义质询,Lambda 函数发出 challengeName: CUSTOM_CHALLENGEissueTokens: falsefailAuthentication: false 响应。如果您不想启动包含密码验证的自定义身份验证流程,可以使用 AuthParameters 映射(包括 CHALLENGE_NAME: CUSTOM_CHALLENGE)启动登录。

  6. 质询循环将一直重复到所有质询得到应答。

以下是启动InitiateAuth请求的示例,该请求在自定义身份验证之前有一个SRP流程。

{ "AuthFlow": "CUSTOM_AUTH", "ClientId": "1example23456789", "AuthParameters": { "CHALLENGE_NAME": "SRP_A", "USERNAME": "testuser", "SRP_A": "[SRP_A]", "SECRET_HASH": "[secret hash]" } }

定义身份验证质询 Lambda 触发器参数

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

JSON
{ "request": { "userAttributes": { "string": "string", . . . }, "session": [ ChallengeResult, . . . ], "clientMetadata": { "string": "string", . . . }, "userNotFound": boolean }, "response": { "challengeName": "string", "issueTokens": boolean, "failAuthentication": boolean } }

定义身份验证质询请求参数

当 Amazon Cognito 调用您的 Lambda 函数时,Amazon Cognito 提供以下参数:

userAttributes

表示用户属性的一个或多个名称/值对。

userNotFound

一个布尔值,当您的用户池客户端将 PreventUserExistenceErrors 设置为 ENABLED 时,Amazon Cognito 将填充该值。值 true 表示用户 ID(用户名、电子邮件地址以及其他详细信息)不匹配任何现有用户。当 PreventUserExistenceErrors 设置为 ENABLED 时,该服务不会向应用程序通知不存在的用户。我们建议您的 Lambda 函数保持相同的用户体验并考虑延迟。这样,不论用户是否存在,调用方都不会检测到不同的行为。

会话

ChallengeResult 元素的数组。每个数组包含以下元素:

challengeName

以下挑战类型之一:CUSTOM_CHALLENGESRP_APASSWORD_VERIFIERSMS_MFAEMAIL_OTPSOFTWARE_TOKEN_MFADEVICE_SRP_AUTHDEVICE_PASSWORD_VERIFIER、或ADMIN_NO_SRP_AUTH

当您的定义身份验证质询功能向已设置多因子身份验证的用户发出PASSWORD_VERIFIER质询时,Amazon Cognito 会随后发出EMAIL_OTPSMS_MFA或质询。SOFTWARE_TOKEN_MFA这些是多因素身份验证码的提示。在你的函数中,包括对来自SMS_MFAEMAIL_OTP、和SOFTWARE_TOKEN_MFA挑战的输入事件的处理。您无需在定义身份验证MFA挑战函数中调用任何挑战。

重要

在函数确定用户是否已成功通过身份验证以及是否应向其颁发令牌时,请始终检查定义身份验证质询函数中的 challengeName 以及它是否与预期值匹配。

challengeResult

如果用户成功完成质询,则设置为 true,否则设置为 false

challengeMetadata

您的自定义质询的名称。仅当 challengeNameCUSTOM_CHALLENGE 时使用。

clientMetadata

一个或多个键值对,您可以将其作为自定义输入内容提供给为定义身份验证质询触发器指定的 Lambda 函数。要将此数据传递给您的 Lambda 函数,您可以使用AdminRespondToAuthChallengeClientMetadataRespondToAuthChallengeAPI操作中的参数。调用 define auth 质询函数的请求不包括在 and 操作中的 ClientMetadata AdminInitiateAuth参数中传递的数据。InitiateAuthAPI

定义身份验证质询响应参数

在响应中,您可以返回身份验证流程的下一阶段。

challengeName

一个字符串,其中包含下一质询的名称。如果您希望向您的用户显示新的质询,请在此处指定质询名称。

issueTokens

如果您确定用户已充分完成了身份验证质询,则设置为 true。如果用户没有充分满足质询条件,则设置为 false

failAuthentication

如果您想要终止当前的身份验证流程,则设置为 true。要继续当前的身份验证流程,请设置为 false

定义身份验证质询示例

此示例针对身份验证定义一系列质询,并仅在用户成功完成所有质询后发布令牌。

Node.js
const handler = async (event) => { if ( event.request.session.length === 1 && event.request.session[0].challengeName === "SRP_A" ) { event.response.issueTokens = false; event.response.failAuthentication = false; event.response.challengeName = "PASSWORD_VERIFIER"; } else if ( event.request.session.length === 2 && event.request.session[1].challengeName === "PASSWORD_VERIFIER" && event.request.session[1].challengeResult === true ) { event.response.issueTokens = false; event.response.failAuthentication = false; event.response.challengeName = "CUSTOM_CHALLENGE"; } else if ( event.request.session.length === 3 && event.request.session[2].challengeName === "CUSTOM_CHALLENGE" && event.request.session[2].challengeResult === true ) { event.response.issueTokens = false; event.response.failAuthentication = false; event.response.challengeName = "CUSTOM_CHALLENGE"; } else if ( event.request.session.length === 4 && event.request.session[3].challengeName === "CUSTOM_CHALLENGE" && event.request.session[3].challengeResult === true ) { event.response.issueTokens = true; event.response.failAuthentication = false; } else { event.response.issueTokens = false; event.response.failAuthentication = true; } return event; }; export { handler };