

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

# 使用 Amazon Cognito 用户池进行身份验证
<a name="authentication"></a>

Amazon Cognito 包含多种对用户进行身份验证的方法。用户可以使用 WebAuthn 密码和密钥登录。Amazon Cognito 可以通过电子邮件或短信向他们发送一次性密码。您可以实现 Lambda 函数，以编排您自己的质询与响应序列。这些是*身份验证流程*。在身份验证流程中，用户提供密钥，然后 Amazon Cognito 会验证该密钥，然后发放 JSON 网络令牌 (JWTs) 供应用程序使用 OIDC 库进行处理。本章将介绍如何在不同的应用程序环境中，为您的用户池和应用程序客户端配置各种身份验证流程。您将了解使用托管登录的托管登录页面的选项，以及在 Amazon SDK 中构建自己的逻辑和前端的选项。

所有用户池（无论您是否具有域）都可以在用户池 API 中对用户进行身份验证。如果您向用户池添加域，则可以使用[用户池端点](https://docs.amazonaws.cn/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html)。用户池 API 支持针对 API 请求的各种授权模型和请求流程。

为了验证用户的身份，Amazon Cognito 支持多种身份验证流程，这些流程除了密码之外，还结合了其他类型的质询，例如电子邮件和短信一次性密码以及通行密钥。

**Topics**
+ [实现身份验证流程](#authentication-implement)
+ [有关用户池身份验证的需知信息](#authentication-flow-things-to-know)
+ [身份验证会话示例](#amazon-cognito-user-pools-authentication-flow)
+ [为托管登录配置身份验证方法](authentication-flows-selection-managedlogin.md)
+ [在中管理身份验证方法 Amazon SDKs](authentication-flows-selection-sdk.md)
+ [身份验证流程](amazon-cognito-user-pools-authentication-flow-methods.md)
+ [API 和 SDK 身份验证的授权模型](authentication-flows-public-server-side.md)

## 实现身份验证流程
<a name="authentication-implement"></a>

无论您是实现[托管登录](authentication-flows-selection-managedlogin.md)，还是使用用于身份验证的 S Amazon DK 的[自定义应用程序前端](authentication-flows-selection-sdk.md)，都必须针对要实现的身份验证类型配置应用程序客户端。以下信息介绍了如何在[应用程序客户端](user-pool-settings-client-apps.md)和应用程序中设置身份验证流程。

------
#### [ App client supported flows ]

您可以在 Amazon Cognito 控制台中为应用程序客户端配置支持的流程，也可以使用软件开发工具包中的 API 来配置支持的流程。 Amazon 在完成应用程序客户端的配置以支持这些流程后，即可在您的应用程序中部署它们。

以下过程展示了如何使用 Amazon Cognito 控制台为应用程序客户端配置可用的身份验证流程。

**为应用程序客户端配置身份验证流程（使用控制台）**

1. 登录 Amazon 并导航到 [Amazon Cognito 用户池控制台](https://console.amazonaws.cn/cognito/v2/idp)。选择一个用户池或新建一个。

1. 在您的用户池配置中，选择**应用程序客户端**菜单。选择一个应用程序客户端或新建一个。

1. 在**应用程序客户端信息**下，选择**编辑**。

1. 在**应用程序客户端流程**下，选择要支持的身份验证流程。

**为应用程序客户端配置身份验证流程（使用 API/SDK）**  
要使用 Amazon Cognito API 为应用程序客户端配置可用的身份验证流程，请在[CreateUserPoolClient](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#CognitoUserPools-CreateUserPoolClient-request-ExplicitAuthFlows)或[UpdateUserPoolClient](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html#CognitoUserPools-UpdateUserPoolClient-request-ExplicitAuthFlows)请求`ExplicitAuthFlows`中设置值。以下是为客户端预置安全远程密码（SRP）和基于选择的身份验证的示例。

```
"ExplicitAuthFlows": [ 
   "ALLOW_USER_AUTH",
   "ALLOW_USER_SRP_AUTH
]
```

配置应用程序客户端支持的流程时，您可以指定以下选项和 API 值。


**应用程序客户端流程支持**  

| 身份验证流程 | 兼容性 | 控制台 | API  | 
| --- | --- | --- | --- | 
| [基于选择的身份验证](authentication-flows-selection-sdk.md#authentication-flows-selection-choice) | 服务器端、客户端 | 登录时选择身份验证类型 | ALLOW\$1USER\$1AUTH | 
| [使用永久密码登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-password) | 客户端 | 使用用户名和密码登录 | ALLOW\$1USER\$1PASSWORD\$1AUTH | 
| [使用永久密码和安全有效载荷登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-srp) | 服务器端、客户端 | 使用安全远程密码（SRP）登录 | ALLOW\$1USER\$1SRP\$1AUTH | 
| [刷新令牌](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-refresh) | 服务器端、客户端 | 从现有的经过身份验证的会话中获取新的用户令牌 | ALLOW\$1REFRESH\$1TOKEN\$1AUTH | 
| [服务器端身份验证](authentication-flows-public-server-side.md#amazon-cognito-user-pools-server-side-authentication-flow) | 服务器端 | 使用服务器端管理凭证登录 | ALLOW\$1ADMIN\$1USER\$1PASSWORD\$1AUTH | 
| [自定义身份验证](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-custom) | 服务器端和客户端定制应用程序。与托管登录不兼容。 | 通过 Lambda 触发器使用自定义身份验证流程登录 | ALLOW\$1CUSTOM\$1AUTH | 

------
#### [ Implement flows in your application ]

托管登录会自动将您配置的身份验证选项显示在登录页面中。在定制的应用程序中，需通过声明初始身份验证流程来启动身份验证。
+ 要为用户从一系列流程选项中进行选择，请使用 `USER_AUTH` 流程声明[基于选择的身份验证](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)。该流程提供了客户端身份验证流程中不可用的身份验证方法，例如[通行密钥](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passkey)和[无密码](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)身份验证。
+ 要预先选择身份验证流程，请使用应用程序客户端中可用的任何其他流程来声明[基于客户端的身份验证](authentication-flows-selection-sdk.md#authentication-flows-selection-client)。

当用户登录时，您的[InitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-AuthFlow)或[AdminInitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html#CognitoUserPools-AdminInitiateAuth-request-AuthFlow)请求的正文必须包含一个`AuthFlow`参数。

基于选择的身份验证：

```
"AuthFlow": "USER_AUTH"
```

使用 SRP 的基于客户端的身份验证：

```
"AuthFlow": "USER_SRP_AUTH"
```

------

## 有关用户池身份验证的需知信息
<a name="authentication-flow-things-to-know"></a>

在使用 Amazon Cognito 用户池设计身份验证模型时，请考虑以下信息。

**托管登录与托管 UI 中的身份验证流程**  
[托管登录](cognito-user-pools-managed-login.md)提供的身份验证选项比经典托管 UI 更多。例如，无密码身份验证和通行密钥身份验证仅在托管登录中可用。

**自定义身份验证流程仅在 Amazon SDK 身份验证中可用**  
您无法在托管登录或经典托管 UI 中执行*自定义身份验证流程*，也无法[使用 Lambda 触发器进行自定义身份验证](user-pool-lambda-challenge.md)。自定义身份验证可在使用进行[身份验证时使用 Amazon SDKs](authentication-flows-selection-sdk.md)。

**通过外部身份提供者（IdP）登录的托管登录**  
在使用[身份验证](authentication-flows-selection-sdk.md)时，您无法通过[第三方 IdPs](cognito-user-pools-identity-federation.md)登录用户 Amazon SDKs。您必须实现托管登录或经典托管用户界面，重定向到 IdPs，然后在应用程序中使用 OIDC 库处理生成的身份验证对象。有关托管登录的更多信息，请参阅[用户池托管登录](cognito-user-pools-managed-login.md)。

**无密码身份验证对其他用户功能的影响**  
在用户池和应用程序客户端中激活使用[一次性密码](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)或[通行密钥](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passkey)的无密码登录，会影响用户的创建和迁移。当无密码登录启用时：  

1. 管理员无需密码即可创建用户。默认的邀请消息模板将不再包含 `{###}` 密码占位符。有关更多信息，请参阅 [以管理员身份创建用户账户](how-to-create-user-accounts.md)。

1. 对于基于 SDK 的[SignUp](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)操作，用户在注册时无需提供密码。而在托管登录和托管 UI 中，即使允许无密码身份验证，在注册页面中仍会要求用户输入密码。有关更多信息，请参阅 [注册并确认用户账户](signing-up-users-in-your-app.md)。

1. 从 CSV 文件导入的用户，只要其属性中包含可用于无密码登录选项的电子邮件地址或电话号码，即可立即使用无密码方式登录，而无需重置密码。有关更多信息，请参阅 [通过 CSV 文件将用户导入用户池中](cognito-user-pools-using-import-tool.md)。

1. 无密码身份验证不会调用[用户迁移 Lambda 触发器](user-pool-lambda-migrate-user.md)。

1. 使用一次性密码 (OTP) 第一因素登录的用户无法在会话中添加[多重身份验证 (MFA)](user-pool-settings-mfa.md) 因素。如果配置了带有用户验证功能的密钥，则可以满足 MFA 要求。`MULTI_FACTOR_WITH_USER_VERIFICATION`

**Passkey 依赖方 URLs 不能出现在公共后缀列表中**  
您可以使用自己拥有的域名（例如 `www.example.com`）作为通行密钥配置中的依赖方（RP）ID。此配置旨在支持运行在您自有域上的定制应用程序。[公共后缀列表](https://publicsuffix.org/)（PSL）包含受保护的高层级域。当您尝试将 RP URL 设置为 PSL 中的域时，Amazon Cognito 会返回错误。

**Topics**
+ [身份验证会话流程持续时间](#authentication-flow-session-duration)
+ [失败登录尝试的锁定行为](#authentication-flow-lockout-behavior)

### 身份验证会话流程持续时间
<a name="authentication-flow-session-duration"></a>

根据用户池的功能，您的应用程序可能需要在从 Amazon Cognito 获取令牌之前，对 `InitiateAuth` 和 `RespondToAuthChallenge` 进行多次质询响应。Amazon Cognito 在对每个请求的响应中都包含一个会话字符串。要将您的 API 请求合并到身份验证流程中，请在每个后续请求中包含来自上一个请求的响应中的会话字符串。默认情况下，在会话字符串过期之前，您的用户有三分钟时间完成每项质询。要调整此时段，请更改您的应用程序客户端的 **Authentication flow session duration**（身份验证流程会话持续时间）。以下过程介绍如何在应用程序客户端配置中更改此设置。

**注意**  
**身份验证流程会话持续时间**设置适用于使用 Amazon Cognito 用户池 API 进行身份验证。托管登录将多重身份验证的会话持续时间设置为 3 分钟，并将密码重置验证码的会话持续时间设置为 8 分钟。

------
#### [ Amazon Cognito console ]

**配置应用程序客户端身份验证流程会话持续时间（Amazon Web Services 管理控制台）**

1. 在您的用户池中的**应用程序集成**选项卡上，从**应用程序客户端和分析**容器中选择您的应用程序客户端的名称。

1. 在**应用程序客户端信息**容器中选择**编辑**。

1. 将**身份验证流程会话持续时间**的值更改为短信和电子邮件 MFA 验证码所需的有效期，以分钟为单位。这还会更改任何用户在您的应用程序客户端中必须完成任何身份验证质询的时间。

1. 选择**保存更改**。

------
#### [ User pools API ]

**配置应用程序客户端身份验证流程会话持续时间 (Amazon Cognito API)**

1. 使用 `DescribeUserPoolClient` 请求中您的现有用户池设置准备 `UpdateUserPoolClient` 请求。您的 `UpdateUserPoolClient` 请求必须包含所有现有的应用程序客户端属性。

1. 将 `AuthSessionValidity` 的值更改为 SMS MFA 代码所需的有效期，以分钟为单位。这还会更改任何用户在您的应用程序客户端中必须完成任何身份验证质询的时间。

------

有关应用程序客户端的更多信息，请参阅[特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。

### 失败登录尝试的锁定行为
<a name="authentication-flow-lockout-behavior"></a>

当用户连续五次输入错误密码尝试登录时（无论这些请求是通过未经身份验证的 API 操作还是通过 IAM 授权的 API 操作发起的），Amazon Cognito 会将该用户锁定一秒钟。然后，每多一次失败的尝试，锁定持续时间将增加一倍，最长约为 15 分钟。

在锁定期内进行的尝试会产生 `Password attempts exceeded` 异常，不会影响后续锁定期的持续时间。对于累计 *n* 次的失败登录尝试（不包括 `Password attempts exceeded` 异常），Amazon Cognito 会将您的用户锁定 *2^(n-5)* 秒。要将锁定重置为其 *n=0* 初始状态，用户必须在锁定期到期后才能成功登录，或者在锁定后连续 15 分钟的任何时间内都不得发起任何登录尝试。此行为随时可能会发生变化。此行为不适用于自定义质询，除非它们还执行基于密码的身份验证。

## 身份验证会话示例
<a name="amazon-cognito-user-pools-authentication-flow"></a>

下图和 step-by-step指南说明了用户登录应用程序的典型场景。示例应用程序向用户提供多种登录选项。用户通过输入凭证选择其中一种，随后提供额外的身份验证因素，最终完成登录。

![\[一个流程图，显示一个应用程序，该应用程序提示用户输入并使用 S Amazon DK 登录。\]](http://docs.amazonaws.cn/cognito/latest/developerguide/images/authentication-api-userauth.png)


设想一个应用程序，其登录页面允许用户通过用户名和密码登录、请求通过电子邮件发送的一次性验证码，或选择指纹验证选项。

1. **登录提示**：您的应用程序显示一个主页，其中包含一个*登录*按钮。

1. **请求登录**：用户选择*登录*。您的应用程序从 Cookie 或缓存中检索其用户名，或提示其输入用户名。

1. **请求选项**：您的应用程序请求用户的登录选项，方法是使用 `USER_AUTH` 流程发起 `InitiateAuth` API 请求，获取用户的可用登录方式。

1. **发送登录选项**：Amazon Cognito 返回 `PASSWORD`、`EMAIL_OTP` 和 `WEB_AUTHN`。该响应包含一个会话标识符，供您在下一个响应中回传。

1. **显示选项**：您的应用程序显示 UI 元素，供用户选择输入用户名和密码、获取一次性验证码，或扫描指纹。

1. **选择 option/Enter 凭据**：用户输入其用户名和密码。

1. **发起身份验证**：您的应用程序通过 `RespondToAuthChallenge` API 请求提交用户的登录信息，确认使用用户名密码进行登录，并提供相应的用户名和密码。

1. **验证凭证**：Amazon Cognito 确认用户提供的凭证。

1. **额外质询**：该用户已配置使用于身份验证器应用程序进行多重身份验证。Amazon Cognito 返回 `SOFTWARE_TOKEN_MFA` 质询。

1. **质询提示**：您的应用程序显示一个表单，请求用户输入其身份验证器应用程序生成的基于时间的一次性密码（TOTP）。

1. **回答质询**：用户提交该 TOTP。

1. **响应质询**：您的应用程序在另一个 `RespondToAuthChallenge` 请求中提供用户的 TOTP。

1. **验证质询响应**：Amazon Cognito 确认用户提交的验证码，并确定您的用户池未针对当前用户配置额外的质询。

1. **发行令牌**：Amazon Cognito 会返回 ID、访问权限和刷新 JSON 网络令牌 () JWTs。用户的初始身份验证完成。

1. **存储令牌**：您的应用程序缓存用户的令牌，以便后续引用用户数据、授权资源访问，并在令牌过期时进行更新。

1. **呈现授权内容**：您的应用程序根据用户的身份和角色判断其资源访问权限，并提供相应的应用程序内容。

1. **访问内容**：用户已登录并开始使用该应用程序。

1. **使用过期令牌请求内容**：稍后，用户请求一个需要授权的资源。但用户缓存的令牌已过期。

1. **刷新令牌**：您的应用程序使用用户保存的刷新令牌发起 `InitiateAuth` 请求。

1. **发行令牌**：亚马逊 Cognito 会返回新的 ID 和访问权限。 JWTs用户的会话在无需再次输入凭证的情况下安全地完成刷新。

您可以使用 [Amazon Lambda 触发器](cognito-user-pools-working-with-lambda-triggers.md)来自定义用户进行身份验证的方式。作为身份验证流程的一部分，这些触发器将发布并验证自己的质询。

您还可以在安全后端服务器上对用户使用管理员身份验证流程。您可以使用[用户迁移身份验证流程](cognito-user-pools-using-import-tool.md)来进行用户迁移，而无需用户重置其密码。