本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
定义身份验证质询触发器是一个 Lambda 函数,用于在自定义身份验证流程中维护质询序列。它声明质询序列的成功或失败,并在序列尚未完成时设置下一个质询。

- 定义身份验证质询
-
Amazon Cognito 调用此触发器以启动自定义身份验证流程。
此 Lambda 触发器的请求包括 session
。session
参数是一个数组,包含在当前身份验证流程中向用户显示的所有质询。请求还包含相应的结果。session
数组按照时间顺序存储质询详细信息 (ChallengeResult
)。质询 session[0]
表示用户收到的第一个质询。
您可以让 Amazon Cognito 在发出自定义质询之前验证用户密码。当您在自定义质询流程中执行 SRP 身份验证时,请求频率限额身份验证类别中关联的任何 Lambda 触发器都将运行。过程概述如下:
-
您的应用程序使用
AuthParameters
映射来调用InitiateAuth
或AdminInitiateAuth
,以此来启动登录。参数必须包括CHALLENGE_NAME: SRP_A,
以及SRP_A
和USERNAME
的值。 -
Amazon Cognito 使用包含
challengeName: SRP_A
和challengeResult: true
的初始会话,调用您定义的身份验证质询 Lambda 触发器。 -
在收到这些输入后,您的 Lambda 函数发出
challengeName: PASSWORD_VERIFIER
、issueTokens: false
、failAuthentication: false
响应。 -
如果密码验证成功,Amazon Cognito 会使用包含
challengeName: PASSWORD_VERIFIER
和challengeResult: true
的新会话再次调用您的 Lambda 函数。 -
为了启动您的自定义质询,Lambda 函数发出
challengeName: CUSTOM_CHALLENGE
、issueTokens: false
和failAuthentication: false
响应。如果您不想启动包含密码验证的自定义身份验证流程,可以使用AuthParameters
映射(包括CHALLENGE_NAME: CUSTOM_CHALLENGE
)启动登录。 -
质询循环将一直重复到所有质询得到应答。
以下在使用 SRP 流进行自定义身份验证之前的起始 InitiateAuth
请求的示例。
{
"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 添加到所有请求中的常用参数的组合。
{
"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_CHALLENGE
、SRP_A
、PASSWORD_VERIFIER
、SMS_MFA
、EMAIL_OTP
、SOFTWARE_TOKEN_MFA
、DEVICE_SRP_AUTH
、DEVICE_PASSWORD_VERIFIER
或ADMIN_NO_SRP_AUTH
。当您的定义身份验证质询功能向已设置多重身份验证的用户发出
PASSWORD_VERIFIER
质询时,Amazon Cognito 会随后提出SMS_MFA
、EMAIL_OTP
或SOFTWARE_TOKEN_MFA
质询。这些是多重身份验证代码的提示。在您的函数中,包括对来自SMS_MFA
、EMAIL_OTP
和SOFTWARE_TOKEN_MFA
质询的输入事件的处理。您无需在定义身份验证质询函数中调用任何 MFA 质询。重要
在函数确定用户是否已成功通过身份验证以及是否应向其颁发令牌时,请始终检查定义身份验证质询函数中的
challengeName
以及它是否与预期值匹配。 - challengeResult
-
如果用户成功完成质询,则设置为
true
,否则设置为false
。 - challengeMetadata
-
您的自定义质询的名称。仅当
challengeName
为CUSTOM_CHALLENGE
时使用。
- clientMetadata
-
一个或多个键值对,您可以将其作为自定义输入内容提供给为定义身份验证质询触发器指定的 Lambda 函数。要将此数据传递给 Lambda 函数,您可以使用 AdminRespondToAuthChallenge 和 RespondToAuthChallenge API 操作中的
ClientMetadata
参数。调用“定义身份验证质询”函数的请求不包括在 AdminInitiateAuth 和 InitiateAuth API 操作的 ClientMetadata 参数中传递的数据。
定义身份验证质询响应参数
在响应中,您可以返回身份验证流程的下一阶段。
- challengeName
-
一个字符串,其中包含下一质询的名称。如果您希望向您的用户显示新的质询,请在此处指定质询名称。
- issueTokens
-
如果您确定用户已充分完成了身份验证质询,则设置为
true
。如果用户没有充分满足质询条件,则设置为false
。 - failAuthentication
-
如果您想要终止当前的身份验证流程,则设置为
true
。要继续当前的身份验证流程,请设置为false
。
定义身份验证质询示例
此示例针对身份验证定义一系列质询,并仅在用户成功完成所有质询后发布令牌。
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 };