

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

# 定义身份验证质询 Lambda 触发器
<a name="user-pool-lambda-define-auth-challenge"></a>

定义身份验证质询触发器是一个 Lambda 函数，用于在自定义身份验证流程中维护质询序列。它声明质询序列的成功或失败，并在序列尚未完成时设置下一个质询。

![\[质询 Lambda 触发器\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/lambda-challenges1.png)


**定义身份验证质询**  
 Amazon Cognito 调用此触发器以启动[自定义身份验证流程](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html#amazon-cognito-user-pools-custom-authentication-flow)。

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

**Topics**
+ [定义身份验证质询 Lambda 触发器参数](#cognito-user-pools-lambda-trigger-syntax-define-auth-challenge)
+ [定义身份验证质询示例](#aws-lambda-triggers-define-auth-challenge-example)

## 定义身份验证质询 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-define-auth-challenge"></a>

Amazon Cognito 传递给此 Lambda 函数的请求是以下参数和 Amazon Cognito 添加到所有请求中的[常用参数](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)的组合。

------
#### [ JSON ]

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

------

### 定义身份验证质询请求参数
<a name="cognito-user-pools-lambda-trigger-syntax-define-auth-challenge-request"></a>

 当 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](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)API 操作中使用`ClientMetadata`参数。调用 define auth 质询函数的请求不包括在 API 操作中的 ClientMetadata 参数中[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)传递的数据。[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)

### 定义身份验证质询响应参数
<a name="cognito-user-pools-lambda-trigger-syntax-define-auth-challenge-response"></a>

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

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

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

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

## 定义身份验证质询示例
<a name="aws-lambda-triggers-define-auth-challenge-example"></a>

此示例针对身份验证定义一系列质询，并仅在用户成功完成所有质询后发布令牌。当用户使用 `SRP_A` 和 `PASSWORD_VERIFIER` 质询完成 SRP 身份验证时，此功能会向他们传递一个 `CUSTOM_CHALLENGE`，用于调用“创建身份验证质询”触发器。结合我们的[创建身份验证质询示例](user-pool-lambda-create-auth-challenge.md#aws-lambda-triggers-create-auth-challenge-example)，此序列为质询三提供了 CAPTCHA 质询，为质询四提供了安全问题。

用户完成 CAPTCHA 并回答安全问题后，此功能将确认您的用户池可以颁发令牌。不需要进行 SRP 身份验证；您也可以将 CAPTCHA 和安全问题设置为质询一和二。如果您的“定义身份验证质询”功能未声明 SRP 质询，则用户的成功完全取决于他们对您的自定义提示的响应。

------
#### [ 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 };
```

------