

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

# Amazon Cognito 用户群体
<a name="cognito-user-pools"></a>

Amazon Cognito 用户池是用于 Web 和移动应用程序身份验证和授权的用户目录。从应用程序的角度来看，Amazon Cognito 用户池是 OpenID Connect（OIDC）身份提供者（IdP）。用户池为安全性、身份联合验证、应用程序集成和用户体验自定义添加了多层附加功能。

例如，您可以验证用户的会话是否来自可信来源。您可以将 Amazon Cognito 目录与外部身份提供者相结合。使用您的首选 AWS SDK，您可以选择最适合您的应用程序的 API 授权模式。您还可以添加用于修改或彻底修改 Amazon Cognito 原定设置行为的 AWS Lambda 函数。

![\[大致地概述用户池工作原理的示意图。客户可以通过使用 AWS SDK 构建的应用程序进行登录，也可以使用用户池中内置的 OIDC IdP 进行登录。用户池还可以统一多个社交身份提供者、OpenID Connect 和 SAML 2.0 身份提供者的登录流程。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/scenario-authentication-cup.png)


**Topics**
+ [功能](#cognito-user-pools-features)
+ [用户池功能计划](cognito-sign-in-feature-plans.md)
+ [Amazon Cognito 用户池安全最佳实践](user-pool-security-best-practices.md)
+ [使用 Amazon Cognito 用户池进行身份验证](authentication.md)
+ [使用第三方身份提供者进行用户池登录](cognito-user-pools-identity-federation.md)
+ [用户池托管登录](cognito-user-pools-managed-login.md)
+ [使用 Lambda 触发器自定义用户池工作流](cognito-user-pools-working-with-lambda-triggers.md)
+ [管理用户池中的用户](managing-users.md)
+ [了解用户池 JSON 网络令牌 (JWTs)](amazon-cognito-user-pools-using-tokens-with-identity-providers.md)
+ [在成功登录后访问资源](accessing-resources.md)
+ [作用域、M2M 和资源服务器](cognito-user-pools-define-resource-servers.md)
+ [配置用户池功能](user-pools-configure-features.md)
+ [使用 Amazon Cognito 用户池安全功能](managing-security.md)
+ [用户池端点和托管登录参考](cognito-userpools-server-contract-reference.md)

## 功能
<a name="cognito-user-pools-features"></a>

Amazon Cognito 用户池具有以下功能。

### 注册
<a name="cognito-user-pools-sign-up"></a>

Amazon Cognito 用户池具有用户驱动、管理员驱动和编程方法，可将用户配置文件添加到您的用户池。Amazon Cognito 用户池支持以下注册模式。您可以在应用程序中使用这些模型的任意组合。

**重要**  
如果您在用户池中激活用户注册，则互联网上的任何人都可以注册账户并登录您的应用程序。除非您开放您的应用程序供公开注册，否则不要在用户池中启用自助注册。要更改此设置，请在用户池控制台的 “**身份验证**” 下的 “**注册**” 菜单中更新**自助服务**注册，或者更新[ CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [ UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API [ AllowAdminCreateUserOnly](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUserConfigType.html#CognitoUserPools-Type-AdminCreateUserConfigType-AllowAdminCreateUserOnly)请求中的值。  
有关可以在用户池中设置的安全功能的信息，请参阅[使用 Amazon Cognito 用户池安全功能](managing-security.md)。

1. 用户可以在应用程序中输入其信息，并创建用户池原生的用户配置文件。您可以调用 API 注册操作在用户池中注册用户。您可以向任何人开放这些注册操作，也可以使用客户密钥或 AWS 凭据对其进行授权。

1. 您可以将用户重定向到第三方 IdP，他们可以授权该第三方 IdP 将其信息传递给 Amazon Cognito。Amazon Cognito 将 OIDC 身份令牌、 OAuth 2.0 `userInfo` 数据和 SAML 2.0 断言处理到您的用户池中的用户个人资料中。您可以根据属性映射规则控制您希望 Amazon Cognito 接收的属性。

1. 您可以跳过公共注册或联合身份验证注册，并根据自己的数据来源和模式来创建用户。在 Amazon Cognito 控制台或 API 中直接添加用户。从 CSV 文件导入用户。运行一个 just-in-time AWS Lambda 函数，在现有目录中查找您的新用户，并根据现有数据填充他们的用户配置文件。

用户注册后，您可以将他们添加到 Amazon Cognito 在访问令牌和 ID 令牌中列出的组。在将 ID 令牌传递给身份池时，还可以将用户池组链接到 IAM 角色。

**相关主题**
+ [管理用户池中的用户](managing-users.md)
+ [了解 API、OIDC 和托管登录页面身份验证](authentication-flows-public-server-side.md#user-pools-API-operations)
+ [使用 Amazon Cognito 身份提供商的代码示例 AWS SDKs](service_code_examples_cognito-identity-provider.md)

### 登录
<a name="cognito-user-pools-sign-in"></a>

Amazon Cognito 可以是应用程序的独立用户目录和身份提供者（IdP）。您的用户可以通过 Amazon Cognito 托管的托管登录页面进行登录，也可以通过采用 Amazon Cognito 用户池 API 构建的定制用户身份验证服务进行登录。定制前端背后的应用程序层可以使用多种方法中的任何一种来授权后端的请求，以确认有效的请求。

用户可以使用用户名和密码、通行密钥以及通过电子邮件或短信接收的一次性密码进行注册和登录。您可以提供以下功能：与外部用户目录整合登录、登录后的多重身份验证（MFA）、信任已记住的设备，以及您自行设计的自定义身份验证流程。

要使用外部目录（可选择与 Amazon Cognito 内置的用户目录结合使用）登录用户，您可以添加以下集成。

1. 使用 OAuth 2.0 社交登录登录并导入客户用户数据。亚马逊 Cognito 支持在 2.0 之前使用谷歌、Facebook、亚马逊和苹果登录。 OAuth 

1. 使用 SAML 和 OIDC 登录进行登录并导入工作和学校用户数据。您也可以将 Amazon Cognito 配置为接受来自任何 SAML 或 OpenID Connect（OIDC）身份提供者（IdP）的声明。

1.  将外部用户配置文件链接到原生用户配置文件。关联的用户可以使用第三方用户身份登录，并获得您分配给内置目录中的用户的访问权限。

**相关主题**
+ [使用第三方身份提供者进行用户池登录](cognito-user-pools-identity-federation.md)
+ [将联合用户与现有用户配置文件关联](cognito-user-pools-identity-federation-consolidate-users.md)

**Machine-to-machine 授权**  
有些会话不是 human-to-machine互动。您可能需要一个能够通过自动化流程向 API 授权请求的服务账户。要生成访问令牌以 machine-to-machine进行 OAuth 2.0 范围的授权，您可以添加生成[客户端凭据](https://www.rfc-editor.org/rfc/rfc6749#section-4.4)授权的应用程序客户端。

**相关主题**
+ [作用域、M2M 和资源服务器](cognito-user-pools-define-resource-servers.md)

### 托管登录
<a name="cognito-user-pools-hosted-ui"></a>

如果您不想构建用户界面，则可以向用户提供自定义的托管登录页面。托管登录是一组用于注册、登录、多重身份验证（MFA）和密码重置的网页。您可以将托管登录添加到现有域中，也可以在 AWS 子域中使用前缀标识符。

**相关主题**
+ [用户池托管登录](cognito-user-pools-managed-login.md)
+ [配置用户池域](cognito-user-pools-assign-domain.md)

### 安全性
<a name="cognito-user-pools-security"></a>

您的本地用户可以通过短信或电子邮件消息中的代码，或用于生成多重身份验证（MFA）代码的应用程序，提供额外的身份验证因素。您可以构建在应用程序中设置和处理 MFA 的机制，也可以让托管登录来管理 MFA。当您的用户从可信设备登录时，Amazon Cognito 用户池可以绕过 MFA。

如果您不想最初就要求用户提供 MFA，则可以有条件地提出要求。借助自适应身份验证，Amazon Cognito 可以检测潜在的恶意活动，并要求用户设置 MFA 或阻止登录。

如果进入用户池的网络流量可能是恶意的，则可以对其进行监控并使用 AWS WAF 网络采取措施 ACLs。

**相关主题**
+ [向用户池添加 MFA](user-pool-settings-mfa.md)
+ [具备威胁防护的高级安全功能](cognito-user-pool-settings-threat-protection.md)
+ [将 AWS WAF Web ACL 与用户池关联](user-pool-waf.md)

### 自定义客户体验
<a name="cognito-user-pools-custom-user-experience"></a>

在用户注册、登录或配置文件更新的大多数阶段，您可以自定义 Amazon Cognito 处理请求的方式。使用 Lambda 触发器，您可以根据自定义条件修改 ID 令牌或拒绝注册请求。您可以创建自己的自定义身份验证流程。

您可以上传自定义 CSS 和徽标，为用户提供熟悉的托管登录外观。

**相关主题**
+ [使用 Lambda 触发器自定义用户池工作流](cognito-user-pools-working-with-lambda-triggers.md)
+ [自定义身份验证质询 Lambda 触发器](user-pool-lambda-challenge.md)
+ [将品牌应用于托管登录页面](managed-login-branding.md)

### 监控和分析
<a name="cognito-user-pools-monitoring-and-analytics"></a>

Amazon Cognito 用户池将 API 请求（包括对托管登录的请求）记录到 AWS CloudTrail。您可以在 Service Quotas 控制台中查看亚马逊 CloudWatch 日志中的性能指标， CloudWatch 使用 Lambda 触发器将自定义日志推送到，监控电子邮件和短信的传送情况，以及监控 API 请求量。

借助增值版[功能计划](cognito-sign-in-feature-plans.md)，您可以利用自动学习技术监控用户身份验证尝试中的泄露迹象，并立即对风险进行补救。这些高级安全功能还可以将用户活动记录到您的用户池中，也可以记录到 Amazon S3、 CloudWatch 日志或 Amazon Data Firehose 中。

还可以将 API 请求中的设备和会话数据记录到 Amazon Pinpoint 活动中。借助 Amazon Pinpoint，您可以根据对用户活动的分析，从应用程序发送推送通知。

**相关主题**
+ [亚马逊 Cognito 正在登录 AWS CloudTrail](logging-using-cloudtrail.md)
+ [跟踪和 Service Quotas 中的配额 CloudWatch 和使用情况](tracking-quotas-and-usage-in-cloud-watch-and-service-quotas.md)
+ [从 Amazon Cognito 用户池导出日志](exporting-quotas-and-usage.md)
+ [使用 Amazon Pinpoint 进行用户池分析](cognito-user-pools-pinpoint-integration.md)

### Amazon Cognito 身份池集成
<a name="cognito-user-pools-identity-pools-integration"></a>

Amazon Cognito 的另一半是身份池。身份池提供证书，用于授权和监控您的用户向（例如 Amazon DynamoDB 或 Amazon S3）发出的 API 请求。 AWS 服务您可以构建基于身份的访问策略，根据您在用户池中对用户进行分类的方式来保护您的数据。身份池还可以接受来自各种身份提供者的令牌和 SAML 2.0 断言，与用户池身份验证无关。

**相关主题**
+ [登录后 AWS 服务 使用身份池进行访问](amazon-cognito-integrating-user-pools-with-identity-pools.md)
+ [Amazon Cognito 身份池](cognito-identity.md)

# 用户池功能计划
<a name="cognito-sign-in-feature-plans"></a>

了解成本是准备实施 Amazon Cognito 用户池身份验证的一个关键步骤。Amazon Cognito 提供针对用户池的功能计划。每个计划均包含一组特定功能，并按活跃用户每月收取费用。每个功能计划都比之前的功能计划解锁了更多功能。

用户池提供多种可打开或关闭的功能。例如，您可以开启多重身份验证 (MFA) 和关闭使用第三方身份提供商登录 ()。IdPs某些变更需要您切换功能计划。用户池的以下特征决定了每月向您 AWS 收取的使用费用。
+ 您选择的功能
+ 您的应用程序每秒向用户池 API 发出的请求数
+ 一个月内有身份验证、更新或查询活动的用户数，也称为[每月活跃用户](quotas.md#monthly-active-users)或 MAUs
+ 来自第三方 SAML 2.0 或 OpenID Connect (OIDC) 的每月活跃用户数 IdPs
+ 使用客户端凭证授予授权的应用程序客户端和用户池的 machine-to-machine数量

有关用户池定价的最新信息，请参阅 [Amazon Cognito 定价](https://aws.amazon.com/cognito/pricing)。

功能计划的选择适用于单个用户池。同一 AWS 账户 中的不同用户池可以选用不同的功能计划。您无法为同一用户池内的不同应用程序客户端分别应用不同的功能计划。新用户池的默认功能计划为基础版。

您可以随时在功能计划之间切换，以满足应用程序的要求。计划之间的某些变更可能需要您关闭当前启用的功能。有关更多信息，请参阅 [关闭功能以更改功能计划](feature-plans-deactivate.md)。用户池功能计划

**精简版**  
精简版是一种低成本的功能计划，适用于每月活跃用户数较少的用户池。该功能计划足以支持具备基本身份验证功能的用户目录，包含登录功能和经典托管 UI，这是托管登录之前的一个更轻量、可定制性较低的版本。许多较新的功能，例如访问令牌自定义和通行密钥身份验证，都未包含在精简版功能计划中。

**基础版**  
基础版具有所有最新的用户池身份验证功能。该计划为您的应用程序添加了新的选项，无论您的登录页面是托管登录还是自定义登录。基础版具有高级身份验证功能，例如[基于选择的登录](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)和[电子邮件 MFA](user-pool-settings-mfa-sms-email-message.md)。

**增值版**  
增值版包含基础版计划中的所有功能，并添加了用于保护用户的高级安全功能。该计划可监控用户登录、注册和密码管理请求，寻找泄露迹象。例如，用户池可以检测用户是否从异常位置登录，或是否使用了已被公开泄露的密码。  
使用增值版功能计划的用户池会生成包含用户活动详情和风险评估的日志。当您将这些日志导出到外部服务时，可以自行对其进行使用情况和安全性分析。

**注意**  
此前，部分用户池功能包含在*高级安全功能*定价结构中。此结构中包含的功能现已纳入基础版或增值版功能计划中。

**Topics**
+ [选择功能计划](#cognito-sign-in-feature-plans-choose)
+ [按计划划分的功能](#cognito-sign-in-feature-plans-list)
+ [基础版计划的功能](feature-plans-features-essentials.md)
+ [增值版计划功能](feature-plans-features-plus.md)
+ [关闭功能以更改功能计划](feature-plans-deactivate.md)

## 选择功能计划
<a name="cognito-sign-in-feature-plans-choose"></a>

------
#### [ AWS 管理控制台 ]

选择功能计划的步骤

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或创建一个用户池。

1. 选择**设置**菜单并查看**功能计划**选项卡。

1. 查看精简版、基础版和增值版功能计划中可供您使用的功能。

1. 要更改计划，请选择**切换到基础版**或**切换到增值版**。要切换到**精简版**计划，请选择**其他计划**，然后选择**与精简版对比**。

1. 在下一个屏幕上，查看您的选择并选择**确认**。

------
#### [ CLI/API/SDK ]

[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)和[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)操作在`UserPoolTier`参数中设置您的功能计划。如果您未指定 `UserPoolTier` 的值，则用户池将默认使用 `Essentials`。如果将 `AdvancedSecurityMode` 设置为 `AUDIT` 或 `ENFORCED`，则用户池的层级必须为 `PLUS`，如果未指定，则默认为 `PLUS`。

有关语法[， CreateUserPool请参阅中的示例](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#API_CreateUserPool_Examples)。 CreateUserPool有关各种编程语言[中此函数的链接， AWS SDKs 请参阅](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#API_CreateUserPool_SeeAlso) of 中的。

```
"UserPoolTier": "PLUS"
```

在中 AWS CLI，此选项是`--user-pool-tier`参数。

```
--user-pool-tier PLUS
```

有关更多信息 [create-user-pool](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/create-user-pool.html)，请参阅 AWS CLI 命令参考[update-user-pool](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/update-user-pool.html)中的和。

------

## 按计划划分的功能
<a name="cognito-sign-in-feature-plans-list"></a>


**用户池中的功能和计划**  

| 功能 | 说明 | 功能计划 | 
| --- | --- | --- | 
| 防范使用不安全的密码 | 在运行时检查纯文本密码是否有泄露迹象 | 增值版 | 
| 防范恶意登录尝试 | 在运行时检查会话属性以了解是否存在泄露迹象 | 增值版 | 
| 记录和分析用户活动 | 生成用户身份验证会话属性和风险评分的日志 | 增值版 | 
| 导出用户活动日志 | 将用户会话和风险日志推送到外部 AWS 服务 | Plus | 
| 使用可视化编辑器自定义托管登录页面 | 使用 Amazon Cognito 控制台中的可视化编辑器，将品牌和样式应用于您的托管登录页面 | 基础版 \$1 增值版 | 
| 带有电子邮件一次性代码的 MFA | 请求或要求本地用户在用户名身份验证后提供额外的电子邮件消息登录因素 | 基础版 \$1 增值版 | 
| 在运行时自定义访问令牌作用域和声明 | 使用 Lambda 触发器扩展用户池访问令牌的授权功能 | 基础版 \$1 增值版 | 
| 使用一次性密码进行无密码登录 | 允许用户通过电子邮件或短信接收一次性密码，作为他们的第一个身份验证因素 | 基础版 \$1 增值版 | 
| 使用硬件或软件身份验证器进行密钥登录 FIDO2  | 允许用户使用存储在 FIDO2 身份验证器上的加密密钥作为他们的第一个身份验证因素 | 基础版 \$1 增值版 | 
| 注册和登录 | 执行身份验证操作并允许新用户在您的应用程序中注册账户。 | 精简版 \$1 基础版 \$1 增值版 | 
| 用户组 | 创建用户的逻辑分组并为身份池操作分配默认的 IAM 角色。 | 精简版 \$1 基础版 \$1 增值版 | 
| 使用社交、SAML 和 OIDC 身份提供者登录 | 为用户提供直接登录或使用其首选提供商登录的选项。 | 精简版 \$1 基础版 \$1 增值版 | 
| OAuth 2.0/OIDC 授权服务器 | 充当 OIDC 颁发者。 | 精简版 \$1 基础版 \$1 增值版 | 
| 登录页面 | 用于身份验证的一系列托管网页。基础版和增值版提供托管登录。所有功能层级均提供经典托管 UI。 | 精简版 \$1 基础版 \$1 增值版 | 
| 密码、自定义、刷新令牌和 SRP 身份验证 | 在应用程序中提示用户输入用户名和密码。 | 精简版 \$1 基础版 \$1 增值版 | 
| Machine-to-machine (M2M) 带有客户凭证 | 颁发访问令牌以授权非人类实体。 | 精简版 \$1 基础版 \$1 增值版 | 
| 使用资源服务器进行 API 授权 | 颁发具有自定义作用域的访问令牌，以授权对外部系统的访问。 | 精简版 \$1 基础版 \$1 增值版 | 
| 用户导入 | 设置从 CSV 文件导入任务，并在用户登录时对其进行 just-in-time迁移。 | 精简版 \$1 基础版 \$1 增值版 | 
| 使用身份验证器应用程序和短信一次性代码进行 MFA | 请求或要求本地用户在用户名身份验证后提供额外的短信或身份验证器应用程序登录因素 | 精简版 \$1 基础版 \$1 增值版 | 
| 在运行时自定义 ID 令牌作用域和声明 | 使用 Lambda 触发器扩展用户池身份（ID）令牌的身份验证功能 | 精简版 \$1 基础版 \$1 增值版 | 
| 使用 Lambda 触发器执行自定义运行时操作 | 使用执行外部操作和影响身份验证的 Lambda 函数，在运行时自定义登录流程 | 精简版 \$1 基础版 \$1 增值版 | 
| 使用 CSS 自定义托管登录页面 | 下载 CSS 模板并更改托管登录页面中的一些样式 | 精简版 \$1 基础版 \$1 增值版 | 

# 基础版计划的功能
<a name="feature-plans-features-essentials"></a>

基础版功能计划包含 Amazon Cognito 用户池大多数先进且最新的功能。当您从精简版计划切换到基础版计划时，将获得托管登录页面的新功能、通过电子邮件一次性密码进行多重身份验证的功能、强化的密码策略，以及自定义访问令牌。要继续 up-to-date使用新的用户池功能，请为您的用户池选择 Essentials 套餐。

以下各节简要概述了您可以通过基础版计划向应用程序添加的功能。有关详细信息，请参阅以下页面。

**其他资源**
+ 访问令牌自定义：[令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md)
+ 电子邮件 MFA：[短信和电子邮件消息 MFA](user-pool-settings-mfa-sms-email-message.md)
+ 密码历史记录：[密码、账户恢复和密码策略](managing-users-passwords.md)
+ 增强型 UI：[将品牌应用于托管登录页面](managed-login-branding.md)

**Topics**
+ [访问令牌自定义](#features-access-token-customization)
+ [电子邮件 MFA](#features-email-mfa)
+ [防止密码重用](#features-password-reuse)
+ [托管登录提供的托管式登录与授权服务器](#features-enhanced-ui)
+ [基于选择的身份验证](#features-user-auth)

## 访问令牌自定义
<a name="features-access-token-customization"></a>

用户池[访问令牌](https://datatracker.ietf.org/doc/html/rfc6749#section-1.4)向应用程序授予以下权限：[访问 API](cognito-user-pools-define-resource-servers.md)、从 [userInfo 端点](userinfo-endpoint.md)检索用户属性或为外部系统建立[组成员关系](cognito-user-pools-user-groups.md)。在高级场景中，您可能需要将应用程序在运行时确定的其他临时参数添加到用户池目录中的默认访问令牌数据中。例如，您可能需要使用 [Amazon Verified Permissions](amazon-cognito-authorization-with-avp.md) 验证用户的 API 权限，并相应地调整访问令牌中的范围。

基础版计划在[令牌生成前触发器](user-pool-lambda-pre-token-generation.md)的现有功能基础上进一步增强。在较低层级的计划中，您可以使用额外的声明、角色和组成员资格来自定义 ID 令牌。基础版添加了触发器输入事件的新版本，能够自定义访问令牌声明、角色、组成员资格和作用域。在事件版本三中， machine-to-machine（M2M）[客户端凭证授予](federation-endpoints-oauth-grants.md)可自定义访问令牌。

**自定义访问令牌**

1. 选择基础版或增值版功能计划。

1. 为触发器创建 Lambda 函数。要使用我们的示例函数，[请为其配置 Node.js](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html)。

1. 使用我们的[示例代码](user-pool-lambda-pre-token-generation.md#aws-lambda-triggers-pre-token-generation-example-version-2-overview)填充您的 Lambda 函数，或者自己编写函数。您的函数必须处理来自 Amazon Cognito 的请求对象，并返回您想要包括的更改。

1. 将您的新函数作为[版本 2 或 3](user-pool-lambda-pre-token-generation.md#user-pool-lambda-pre-token-generation-event-versions) 令牌生成前触发器来分配。版本 2 事件用于自定义用户身份的访问令牌。版本 3 用于自定义用户和机器身份的访问令牌。

**了解详情**
+ [自定义访问令牌](user-pool-lambda-pre-token-generation.md#user-pool-lambda-pre-token-generation-accesstoken)
+ [如何在 Amazon Cognito 用户池中自定义访问令牌](https://aws.amazon.com/blogs/security/how-to-customize-access-tokens-in-amazon-cognito-user-pools/)

## 电子邮件 MFA
<a name="features-email-mfa"></a>

可以将 Amazon Cognito 用户池配置为使用电子邮件作为多重身份验证（MFA）的第二个因素。通过电子邮件 MFA，Amazon Cognito 可以向用户发送一封包含验证码的电子邮件，用户必须输入该验证码才能完成身份验证过程。这样就为用户登录流程额外增加了一层重要的安全保护。要启用基于电子邮件的 MFA，必须将用户池配置为使用 [Amazon SES 电子邮件发送配置](user-pool-email.md#user-pool-email-developer)，而不是默认的电子邮件配置。

当您的用户选择通过电子邮件进行 MFA 时，每当用户尝试登录时，Amazon Cognito 都会向其注册的电子邮件地址发送一次性验证码。然后，用户必须将此验证码提供给用户池，这样才能完成身份验证流程并获得访问权限。这样可以确保即使用户的用户名和密码遭到泄露，他们还必须提供额外的因素（通过电子邮件发送的验证码），然后才能访问您的应用程序资源。

有关更多信息，请参阅 [短信和电子邮件消息 MFA](user-pool-settings-mfa-sms-email-message.md)。下面概述了如何设置用户池和用户以使用电子邮件 MFA。

**在 Amazon Cognito 控制台中设置电子邮件 MFA**

1. 选择基础版或增值版功能计划。

1. 在用户池的**登录**菜单中，编辑**多重身份验证**。

1. 选择要设置的 **MFA 强制执行**级别。使用**需要 MFA** 选项时，API 中的用户会自动收到质询，要求他们使用 MFA 进行设置、确认和登录。在需要 MFA 的用户池中，托管登录会提示用户选择和设置 MFA 因素。使用**可选 MFA** 选项时，您的应用程序必须为用户提供选项来设置 MFA 和设置用户电子邮件 MFA 首选项。

1. 在 **MFA 方法**下，选择**电子邮件消息**作为其中一个选项。

**了解详情**
+ [短信和电子邮件消息 MFA](user-pool-settings-mfa-sms-email-message.md)

## 防止密码重用
<a name="features-password-reuse"></a>

默认情况下，Amazon Cognito 用户池密码策略会设置密码长度和字符类型要求以及临时密码到期时间。基础版计划增加了强制执行密码历史记录的功能。当用户尝试重置其密码时，您的用户池会阻止用户将其设置为以前的密码。有关配置密码策略的更多信息，请参阅[添加用户池密码要求](managing-users-passwords.md#user-pool-settings-policies)。下面概述了如何使用密码历史记录策略来设置用户池。

**在 Amazon Cognito 控制台中设置密码历史记录**

1. 选择基础版或增值版功能计划。

1. 在用户池的**身份验证方法**菜单中，找到**密码策略**，然后选择**编辑**。

1. 配置其他可用选项，并为**防止使用之前的密码**设置一个值。

**了解详情**
+ [密码、账户恢复和密码策略](managing-users-passwords.md)

## 托管登录提供的托管式登录与授权服务器
<a name="features-enhanced-ui"></a>

Amazon Cognito 用户池具有支持以下功能的可选网页：OpenID Connect (OIDC) IdP、 IdPs第三方的服务提供商或依赖方，以及用于注册和登录的公共用户交互页面。这些页面统称为*托管登录*。当您为用户池选择域时，Amazon Cognito 会自动激活这些页面。精简版计划提供托管 UI，而基础版计划则支持这一高级版本的注册和登录页面。

托管登录页面具有简洁的 up-to-date界面，具有更多用于自定义品牌和样式的功能和选项。基础版计划是可启用托管登录的最低计划级别。

**在 Amazon Cognito 控制台中设置托管登录**

1. 从**设置**菜单中，选择基础版或增值版功能计划。

1. 在**域**菜单中，[将域分配给](cognito-user-pools-assign-domain.md)您的用户池，然后选择**托管登录**的**品牌版本**。

1. 在**托管登录**菜单的**样式**选项卡下，选择**创建样式**并将样式分配给应用程序客户端，或者新建一个应用程序客户端。

**了解详情**
+ [用户池托管登录](cognito-user-pools-managed-login.md)

## 基于选择的身份验证
<a name="features-user-auth"></a>

基础版层级引入了一种新的*身份验证流程*，用于增强型 UI 和基于 SDK 的 API 操作中的身份验证操作。该流程称为*基于选择的身份验证*。基于选择的身份验证是一种方法，在这种方法中，用户的身份验证流程并非始于应用程序端声明的登录方式，而是先查询可用的登录方式，再由用户从中进行选择。您可以将用户池配置为支持基于选择的身份验证，并启用用户名密码、无密码和通行密钥身份验证。在 API 中，这就是 `USER_AUTH` 流程。

**在 Amazon Cognito 控制台中设置基于选择的身份验证**

1. 选择基础版或增值版功能计划。

1. 在用户池的**登录**菜单中，编辑**基于选择的登录选项**。选择并配置要在基于选择的身份验证中启用的身份验证方法。

1. 在用户池的**身份验证方法**菜单中，编辑登录操作的配置。

**了解详情**
+ [使用 Amazon Cognito 用户池进行身份验证](authentication.md)

# 增值版计划功能
<a name="feature-plans-features-plus"></a>

增值版功能计划为 Amazon Cognito 用户池提供高级安全功能。这些功能会在运行时记录并分析用户上下文，从设备、位置、请求数据和密码中识别潜在的安全问题。然后，它们会通过阻止访问或为用户账户增加安全防护的自动响应措施来缓解这些潜在风险。您也可以将安全日志导出到 Amazon S3、Amazon Data Firehose 或亚马逊 CloudWatch 日志以供进一步分析。

当您从基础版计划切换到增值版计划时，将保留基础版中的所有功能，并额外获得以下功能：包括威胁防护在内的安全选项集，也称为*高级安全功能*。要将您的用户池配置为自动应对身份验证前端中的威胁，请为您的用户池选择增值版计划。

以下各节简要概述了您可以通过增值版计划向应用程序添加的功能。有关详细信息，请参阅以下页面。

**其他资源**
+ 自适应身份验证：[使用自适应身份验证](cognito-user-pool-settings-adaptive-authentication.md)
+ 已泄露的凭证：[使用凭证遭泄露检测功能](cognito-user-pool-settings-compromised-credentials.md)
+ 日志导出：[从 Amazon Cognito 用户池导出日志](exporting-quotas-and-usage.md)

**Topics**
+ [威胁防护：自适应身份验证](#features-adaptive-authentication)
+ [威胁防护：凭证遭泄露检测](#features-compromised-credentials)
+ [威胁防护：用户活动日志记录](#features-user-logs)

## 威胁防护：自适应身份验证
<a name="features-adaptive-authentication"></a>

增值版计划包括*自适应身份验证* 功能。激活此功能后，您的用户池将对每个用户身份验证会话进行风险评估。根据生成的风险评级，对于登录时风险级别超过您设定阈值的用户，您可以阻止身份验证或推送 MFA。使用自适应身份验证，您的用户池和应用程序会自动为您怀疑其账户受到攻击的用户阻止或设置 MFA。您还可以就用户池中的风险评级提供反馈，以调整未来的评级。

**在 Amazon Cognito 控制台中设置自适应身份验证**

1. 选择增值版功能计划。

1. 在用户池的**威胁防护**菜单中，编辑**威胁防护**下的**标准和自定义身份验证**。

1. 将标准或自定义身份验证的**强制执行模式**设置为**全功能**。

1. 在**自适应身份验证**下，为不同风险级别配置自动风险响应。

**了解详情**
+ [使用自适应身份验证](cognito-user-pool-settings-adaptive-authentication.md)
+ [在应用程序中收集威胁防护的数据](user-pool-settings-viewing-threat-protection-app.md)

## 威胁防护：凭证遭泄露检测
<a name="features-compromised-credentials"></a>

增值版计划包括*凭证遭泄露检测* 功能。此功能可防止使用不安全的密码以及这种做法造成的意外访问应用程序的威胁。当您允许用户使用用户名和密码登录时，他们可能会重复使用他们在其他地方使用的密码。该密码可能已被泄露，或者只是属于常见易猜的密码。使用凭证遭泄露检测功能，您的用户池可以读取用户提交的密码，并将其与密码数据库进行比较。如果该操作判定密码很可能已遭泄露，您可以将用户池配置为阻止登录，然后在应用程序中为该用户启动密码重置。

在新用户注册、现有用户登录以及用户尝试重置密码时，凭证遭泄露检测功能可对不安全的密码做出响应。使用此功能，无论用户在何处输入不安全的密码，您的用户池都可以阻止或警告使用不安全密码的登录行为。

**在 Amazon Cognito 控制台中设置凭证遭泄露检测**

1. 选择增值版功能计划。

1. 在用户池的**威胁防护**菜单中，编辑**威胁防护**下的**标准和自定义身份验证**。

1. 将标准或自定义身份验证的**强制执行模式**设置为**全功能**。

1. 在**已泄露的凭证**下，配置您要检查的身份验证操作的类型，以及要从用户池中获得的自动响应。

**了解详情**
+ [使用凭证遭泄露检测功能](cognito-user-pool-settings-compromised-credentials.md)

## 威胁防护：用户活动日志记录
<a name="features-user-logs"></a>

增值版计划增加了日志记录功能，可提供安全分析以及用户身份验证尝试的详细信息。您可以查看风险评估结果、用户 IP 地址、用户代理以及有关连接到您的应用程序的设备的其他信息。您可以使用内置的威胁防护功能基于这些信息采取行动，也可以分析自己系统中的日志并采取适当的措施。您可以将威胁防护中的日志导出到 Amazon S3、 CloudWatch 日志或 Amazon DynamoDB。

**在 Amazon Cognito 控制台中设置用户活动日志记录**

1. 选择增值版功能计划。

1. 在用户池的**威胁防护**菜单中，编辑**威胁防护**下的**标准和自定义身份验证**。

1. 将标准或自定义身份验证的**强制执行模式**设置为**仅限审计**。这是日志的最低设置。您还可以在**全功能**模式下将其激活此模式并配置其他威胁防护功能。

1. 要将日志导出到其他日志以 AWS 服务 供第三方分析，请转到用户池的 “**日志流**” 菜单并设置导出目的地。

**了解详情**
+ [导出用户身份验证事件](cognito-user-pool-settings-adaptive-authentication.md#user-pool-settings-adaptive-authentication-event-user-history-exporting)
+ [从 Amazon Cognito 用户池导出日志](exporting-quotas-and-usage.md)

# 关闭功能以更改功能计划
<a name="feature-plans-deactivate"></a>

功能计划为您的用户池增加了配置选项。只有在相关功能计划处于活动状态时，您才能配置和使用这些功能。例如，您可以在增值版和基础版计划中配置访问令牌自定义功能，但不能在精简版计划中配置。要停用这些特征，必须停用每个活动组件。Amazon Cognito 控制台**设置**菜单中的**切换到**选项会告知您必须先停用哪些功能，然后才能更改功能计划。在本章中，您可以了解停用特征对用户池配置所作的更改，以及如何单独关闭这些特征。

**访问令牌自定义**  
要切换到不包含访问令牌自定义功能的计划，您必须从用户池中移除[令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md#user-pool-lambda-pre-token-generation-accesstoken)。要在不自定义访问令牌的情况下添加新的令牌生成前触发器，请为该触发器分配新函数并对 `V1_0` 事件进行配置。这些版本一触发器事件只能处理 ID 令牌的更改。  
要手动停用访问令牌自定义，请移除令牌生成前触发器，然后添加一个新的版本一触发器。

**威胁防护**  
要切换到没有威胁防护功能的计划，请停用用户池的**威胁防护**菜单中的所有功能。

**日志导出**  
要切换到不支持导出日志的计划，请从用户池的**日志流式传输**菜单中停用此功能。您的用户池不再生成本地或导出的用户活动日志。您也可以发送 [SetLogDeliveryConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetLogDeliveryConfiguration.html)API 请求，删除任何`EventSource`值为的配置`UserActivity`。

**电子邮件 MFA**  
要切换到不包含电子邮件 MFA 功能的计划，请转到用户池的**登录**菜单。编辑**多重身份验证**并取消选择**电子邮件消息**作为可用的 **MFA 方法**之一。

# Amazon Cognito 用户池安全最佳实践
<a name="user-pool-security-best-practices"></a>

本页介绍了可以实施以防范常见威胁的安全最佳实践。您选择的配置将取决于每个应用程序的使用案例。建议您至少对管理操作应用最低权限，并采取措施保护应用程序和用户密钥。您可以采取的另一个高级但有效的步骤是配置 AWS WAF Web 并将其应用 ACLs 于您的用户池。

## 在网络层面保护您的用户池
<a name="user-pool-security-best-practices-network"></a>

AWS WAF web ACLs 可以保护您使用 Amazon Cognito 构建的身份验证机制的性能和成本。借助 Web ACLs，您可以在 API 和托管登录请求之前实施防护措施。Web ACLs 创建网络层和应用层过滤器，这些过滤器可以根据您设计的规则丢弃流量或要求使用验证码。只有在请求满足您的 Web ACL 规则中的条件后，才会传递到您的 Amazon Cognito 资源。有关更多信息，请参阅 [AWS WAF web ACLs](user-pool-waf.md)。

## 防止短信滥用
<a name="user-pool-security-best-practices-sms"></a>

如果您允许在用户池中进行公开注册，则可以使用 Amazon Cognito 以短信形式发送的代码来配置账户验证。SMS 消息可能与不想要的活动相关联，从而增加您的 AWS 账单。请配置您的基础设施，使其在遭遇欺诈时具备抵御能力，避免发送短信。有关更多信息，请查看 AWS 博客中的以下帖子。
+ [Reduce risks of user sign-up fraud and SMS pumping with Amazon Cognito user pools](https://aws.amazon.com/blogs/security/reduce-risks-of-user-sign-up-fraud-and-sms-pumping-with-amazon-cognito-user-pools/)
+ [防范短信抽水：新 AWS 功能可帮助抵御人为膨胀的流量](https://aws.amazon.com/blogs/messaging-and-targeting/defending-against-sms-pumping-new-aws-features-to-help-combat-artificially-inflated-traffic/)

## 了解公共身份验证
<a name="user-pool-security-best-practices-public-operations"></a>

Amazon Cognito 用户池具有客户身份和访问管理（CIAM）功能，支持面向公众的使用案例，即用户可自行注册账户并访问您的应用程序。当用户池允许自助注册时，它将接受来自公共互联网的用户账户请求。自助服务请求来自和之类的 API 操作 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)，[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)以及用户与托管登录的交互。您可以配置用户池以减少可能来自公共请求的滥用行为，或者完全禁用公共身份验证操作。

以下设置是您可以在用户池和应用程序客户端中管理公共和内部身份验证请求的一些方法。


**影响公共用户池访问的用户池设置示例**  

| 设置 | 可用选项 | 配置位置 | 对公共身份验证的影响 | 控制台设置 | API 操作和参数 | 
| --- | --- | --- | --- | --- | --- | 
| [自助注册](user-pool-settings-admin-create-user-policy.md) | 允许用户以管理员身份注册账户或创建用户账户。 | 用户池 | 阻止公开注册 | 注册 - 自助注册 |  [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-AdminCreateUserConfig), [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#CognitoUserPools-UpdateUserPool-request-AdminCreateUserConfig) `AdminCreateUserConfig` – `AllowAdminCreateUserOnly`  | 
| [管理员确认](signing-up-users-in-your-app.md#signing-up-users-in-your-app-and-confirming-them-as-admin) | 向新用户发送确认码或要求管理员进行确认。 | 用户池 | 防止在没有管理员操作的情况下确认注册 | 注册 - Cognito 辅助验证和确认 |  [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-AccountRecoverySetting), [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#CognitoUserPools-UpdateUserPool-request-AccountRecoverySetting) `AccountRecoverySettings` – `admin_only`  | 
| [用户披露](cognito-user-pool-managing-errors.md) | 在登录和密码重置时发送“未找到用户”消息，或者防止披露。 | 应用程序客户端 | 防止猜测登录名、电子邮件地址或电话号码 | 应用程序客户端 - 防止用户已存在错误 |  [CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#CognitoUserPools-CreateUserPoolClient-request-PreventUserExistenceErrors), [UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html#CognitoUserPools-UpdateUserPoolClient-request-PreventUserExistenceErrors) `PreventUserExistenceErrors`  | 
| [客户端密钥](user-pool-settings-client-apps.md#user-pool-settings-client-app-client-types) | 注册、登录、重置密码时需要或不需要密钥哈希 | 应用程序客户端 | 防范来自未经授权来源的身份验证请求 | 应用程序客户端 - 客户端密钥 |  [CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#CognitoUserPools-CreateUserPoolClient-request-GenerateSecret) `GenerateSecret`  | 
| [Web ACLs](user-pool-waf.md) | 针对身份验证请求启用或不启用网络防火墙 | 用户池 | 根据管理员定义的请求特征和 IP 地址规则限制或阻止访问 | AWS WAF – WAF 设置 |  [AssociateWebACL](https://docs.aws.amazon.com/waf/latest/APIReference/API_AssociateWebACL.html#WAF-AssociateWebACL-request-ResourceArn) `ResourceArn`  | 
| [外部 IdP](cognito-user-pools-identity-provider.md) | 允许用户在第三方 IdPs、用户池目录或两者中登录 | 应用程序客户端 | 排除[本地用户](cognito-terms.md#terms-localuser)或[联合用户](cognito-terms.md#terms-federateduser)进行注册和登录。 | 应用程序客户端 - 身份提供者 |  [CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#CognitoUserPools-CreateUserPoolClient-request-SupportedIdentityProviders), [UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html#CognitoUserPools-UpdateUserPoolClient-request-SupportedIdentityProviders) `SupportedIdentityProviders`  | 
| [授权服务器](cognito-user-pools-assign-domain.md) | 托管或不托管用于身份验证的公开网页 | 用户池 | 关闭公开网页，只允许基于 SDK 的身份验证 | 域： |  [CreateUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolDomain.html) 创建任何用户池域都会使公开网页变得可用。  | 
| [威胁防护](cognito-user-pool-settings-threat-protection.md) | 启用或禁用对恶意活动迹象或不安全密码的监控 | 用户池或应用程序客户端 | 当用户显示泄露迹象时，可以自动阻止登录或要求进行 MFA | 威胁防护 - 保护设置 |  [SetRiskConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetRiskConfiguration.html) `SetRiskConfiguration` 的参数用于定义您的威胁防护设置。  | 

## 使用客户端密钥保护机密客户端
<a name="user-pool-security-best-practices-client-secret"></a>

客户端密钥是与[应用程序客户端](user-pool-settings-client-apps.md)关联的可选字符串。向具有客户端密钥的应用程序客户端发出的所有身份验证请求，都必须包含由用户名、客户端 ID 和客户端密钥生成的[密钥哈希](signing-up-users-in-your-app.md#cognito-user-pools-computing-secret-hash)。那些不知道客户端密钥的用户从一开始就被应用程序拒之门外。

但是，客户端密钥存在局限性。如果您在公共客户端软件中嵌入了客户端密钥，则您的客户端密钥将暴露于外部检查之下。这会使攻击者能够在您的应用程序客户端中创建用户、提交密码重置请求以及执行其他操作。只有当应用程序是唯一有权访问该密钥的实体时，才必须实施客户端密钥。通常，这种情况仅适用于服务器端的机密客户端应用程序。需要客户端密钥的 [M2M 应用程序](cognito-user-pools-define-resource-servers.md)也是如此。将客户端密钥存储在加密的本地存储器中或 AWS Secrets Manager。切勿让您的客户端密钥在公共互联网上暴露可见。

## 保护其他密钥
<a name="user-pool-security-best-practices-manage-secrets"></a>

您基于 Amazon Cognito 用户池构建的身份验证系统可能会处理私有数据、密码和 AWS 凭证。以下是处理应用程序可能访问的密钥的一些最佳实践。

**密码**  
用户在登录您的应用程序时可能会输入密码。Amazon Cognito 提供刷新令牌，您的应用程序可以使用这些令牌在没有新密码提示的情况下继续使用过期的用户会话。不要在本地存储中放置任何密码或密码哈希。设计您的应用程序时，应将密码视为不透明数据，仅将其传递至用户池。  
[最佳做法是使用密钥实现无密码身份验证。WebAuthn](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passkey)如果您必须使用密码，请使用[安全远程密码（SRP）身份验证流程](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-srp)和[多重身份验证（MFA）](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-mfa)。

**AWS 证书**  
管理身份验证和用户池管理操作需要使用 AWS 凭据进行身份验证。要在应用程序中实现这些操作，请授予对[临时 AWS 证书](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html)的安全访问权限。仅向在您控制的服务器组件上运行的应用程序授予凭证访问权限。不要将包含 AWS 凭据的应用程序放在公共版本控制系统上，例如。 GitHub不要在公共客户端应用程序中对 AWS 凭据进行编码。

**PKCE 代码验证程序**  
[代码交换证明密钥（PKCE）](using-pkce-in-authorization-code.md)用于通过用户池授权服务器进行的 OpenID Connect（OIDC）授权码授予流程。当应用程序请求授权码时，它们会与您的用户池共享代码验证程序密钥。要将授权码交换为令牌，客户端必须重新确认其知晓该代码验证程序。这种做法可以防止颁发带有被拦截的授权码的令牌。  
客户端必须针对每个授权请求生成一个新的随机代码验证程序。使用静态或可预测的代码验证程序意味着攻击者只需拦截硬编码的验证程序和授权码即可。设计您的应用程序时，应确保不向用户暴露代码验证程序的值。

## 用户池管理最低权限
<a name="user-pool-security-best-practices-least-privilege"></a>

IAM 策略可以定义主体对 Amazon Cognito 用户池管理和管理身份验证操作的访问级别。例如：
+ 对于 Web 服务器，授予使用管理 API 操作进行身份验证的权限。
+ 对于管理您的 AWS IAM Identity Center 用户池的用户 AWS 账户，请授予用户池维护和报告的权限。

在 IAM 策略中，Amazon Cognito 的资源粒度仅限于[两种资源类型](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoncognitoidentity.html#amazoncognitoidentity-resources-for-iam-policies)：用户池和身份池。请注意，您无法针对单个应用程序客户端设置管理权限。在配置用户池时需知晓，您授予的权限对于所有应用程序客户端均有效。如果您的组织拥有多个应用程序租户，并且您的安全模型要求在租户之间分离管理职责，则可以实施[每个用户池一个租户的多租户架构](bp_user-pool-based-multi-tenancy.md)。

尽管您可以创建包含用户身份验证操作（如 `InitiateAuth`）权限的 IAM 策略，但这些权限实际上不会生效。[公开的以及令牌授权的 API 操作](authentication-flows-public-server-side.md)不受 IAM 权限的约束。在可用的用户池身份验证操作中，您只能向*管理类* 服务器端操作（例如 `AdminInitiateAuth`）授予权限。

您可以使用最低权限 `Action` 列表来限制用户池的管理级别。以下示例策略适用于可以管理资源服务器 IdPs、应用程序客户端和用户池域的管理员，但不能管理用户或用户池。

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

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "UserPoolClientAdministrator",
      "Action": [
        "cognito-idp:CreateIdentityProvider",
        "cognito-idp:CreateManagedLoginBranding",
        "cognito-idp:CreateResourceServer",
        "cognito-idp:CreateUserPoolDomain",
        "cognito-idp:DeleteIdentityProvider",
        "cognito-idp:DeleteResourceServer",
        "cognito-idp:DeleteUserPoolDomain",
        "cognito-idp:DescribeIdentityProvider",
        "cognito-idp:DescribeManagedLoginBranding",
        "cognito-idp:DescribeManagedLoginBrandingByClient",
        "cognito-idp:DescribeResourceServer",
        "cognito-idp:DescribeUserPool",
        "cognito-idp:DescribeUserPoolClient",
        "cognito-idp:DescribeUserPoolDomain",
        "cognito-idp:GetIdentityProviderByIdentifier",
        "cognito-idp:GetUICustomization",
        "cognito-idp:ListIdentityProviders",
        "cognito-idp:ListResourceServers",
        "cognito-idp:ListUserPoolClients",
        "cognito-idp:ListUserPools",
        "cognito-idp:SetUICustomization",
        "cognito-idp:UpdateIdentityProvider",
        "cognito-idp:UpdateManagedLoginBranding",
        "cognito-idp:UpdateResourceServer",
        "cognito-idp:UpdateUserPoolClient",
        "cognito-idp:UpdateUserPoolDomain"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:cognito-idp:us-west-2:123456789012:userpool/us-west-2_EXAMPLE"
    }
  ]
}
```

------

以下示例策略为服务器端应用程序授予用户和组管理以及身份验证权限。

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

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "UserAdminAuthN",
      "Action": [
        "cognito-idp:AdminAddUserToGroup",
        "cognito-idp:AdminConfirmSignUp",
        "cognito-idp:AdminCreateUser",
        "cognito-idp:AdminDeleteUser",
        "cognito-idp:AdminDeleteUserAttributes",
        "cognito-idp:AdminDisableProviderForUser",
        "cognito-idp:AdminDisableUser",
        "cognito-idp:AdminEnableUser",
        "cognito-idp:AdminForgetDevice",
        "cognito-idp:AdminGetDevice",
        "cognito-idp:AdminGetUser",
        "cognito-idp:AdminInitiateAuth",
        "cognito-idp:AdminLinkProviderForUser",
        "cognito-idp:AdminListDevices",
        "cognito-idp:AdminListGroupsForUser",
        "cognito-idp:AdminListUserAuthEvents",
        "cognito-idp:AdminRemoveUserFromGroup",
        "cognito-idp:AdminResetUserPassword",
        "cognito-idp:AdminRespondToAuthChallenge",
        "cognito-idp:AdminSetUserMFAPreference",
        "cognito-idp:AdminSetUserPassword",
        "cognito-idp:AdminSetUserSettings",
        "cognito-idp:AdminUpdateAuthEventFeedback",
        "cognito-idp:AdminUpdateDeviceStatus",
        "cognito-idp:AdminUpdateUserAttributes",
        "cognito-idp:AdminUserGlobalSignOut",
        "cognito-idp:AssociateSoftwareToken",
        "cognito-idp:ListGroups",
        "cognito-idp:ListUsers",
        "cognito-idp:ListUsersInGroup",
        "cognito-idp:RevokeToken",
        "cognito-idp:UpdateGroup",
        "cognito-idp:VerifySoftwareToken"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:cognito-idp:us-west-2:123456789012:userpool/us-west-2_EXAMPLE"
    }
  ]
}
```

------

## 保护和验证令牌
<a name="user-pool-security-best-practices-secure-tokens"></a>

令牌可以包含对组成员资格的内部引用，以及您可能不想向最终用户披露的用户属性。请勿将 ID 令牌和访问令牌存储在本地存储中。刷新令牌使用只有您的用户池才能访问的密钥进行加密，并且对用户和应用程序不透明。当用户注销或您出于安全原因认为不应该持久化用户会话时，请[撤销刷新令牌](token-revocation.md)。

使用访问令牌，仅向独立验证令牌有效且未过期的系统授予访问权限。有关验证资源，请参阅[验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。

## 确定要信任的身份提供者
<a name="user-pool-security-best-practices-trusted-idps"></a>

使用 [SAML](cognito-user-pools-saml-idp.md) 或 [OIDC](cognito-user-pools-oidc-idp.md) 身份提供商 (IdPs) 配置用户池时， IdPs 您可以创建新用户、设置用户属性和访问您的应用程序资源。SAML 和 OIDC 提供商通常用于 business-to-business (B2B) 或企业场景，在这种场景中，您或您的直接客户控制提供商的成员资格和配置。

[社交提供商](cognito-user-pools-social-idp.md)向互联网上的任何人提供用户账户，且相比企业级提供商，您对其的控制力较弱。只有当你准备好允许公众客户登录和访问应用程序 IdPs 中的资源时，才能在应用程序客户端中激活 social。

## 了解作用域对用户配置文件访问的影响
<a name="user-pool-security-best-practices-scopes"></a>

您可以在向用户池授权服务器发起的身份验证请求中申请访问控制作用域。这些作用域可以授予您的用户访问外部资源的权限，也可以授予用户查看和修改自己的用户配置文件的权限。配置应用程序客户端，使其支持应用程序运行所需的最小范围。

该`aws.cognito.signin.user.admin`作用域存在于 SDK 身份验证通过以下操作颁发的所有访问令牌中[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)。它专为应用程序中的用户配置文件自助操作而设计。您也可以从授权服务器申请此作用域。此作用域是令牌授权的操作（如和）所必需的。[UpdateUserAttributes[GetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html)这些操作的效果受应用程序客户端的读取和写入权限的限制。

`openid`、`profile`、`email` 和 `phone` 作用域用于授权向用户池授权服务器上的 [userInfo 端点](userinfo-endpoint.md)发起的请求。它们定义了端点可返回的属性。当仅请求 `openid` 作用域（不包含其他作用域）时，会返回所有可用的属性；但当请求中包含其他作用域时，响应将被限制为仅包含这些额外作用域所对应的属性。`openid` 作用域还表示请求 ID 令牌；如果在向 [对端点授权](authorization-endpoint.md)发起的请求中省略此作用域，Amazon Cognito 将仅颁发访问令牌，以及在适用时颁发刷新令牌。有关更多信息，请参阅[应用程序客户端术语](user-pool-settings-client-apps.md#cognito-user-pools-app-idp-settings-about)中的 **OpenID Connect 作用域**。

## 清理用户属性的输入
<a name="user-pool-security-best-practices-sanitize-inputs"></a>

可能用作分发方式和用户名的用户属性（例如 `email`）具有[格式限制](user-pool-settings-attributes.md#cognito-user-pools-standard-attributes)。其他属性则可使用字符串、布尔值或数字数据类型。字符串类型的属性值支持多种输入形式。请配置您的应用程序，防止恶意数据写入用户目录或 Amazon Cognito 向用户发送的消息。在将用户提交的字符串属性值提交至 Amazon Cognito 之前，请在应用程序中对其进行客户端验证。

用户池根据您指定的属性映射将[属性从映射 IdPs ](cognito-user-pools-specifying-attribute-mapping.md)到您的用户池。请仅将安全且可预测的 IdP 属性映射到用户池的字符串类型属性。

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

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

所有用户池（无论您是否具有域）都可以在用户池 API 中对用户进行身份验证。如果您向用户池添加域，则可以使用[用户池端点](https://docs.aws.amazon.com/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)
+ [在中管理身份验证方法 AWS 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 AWS DK 的[自定义应用程序前端](authentication-flows-selection-sdk.md)，都必须针对要实现的身份验证类型配置应用程序客户端。以下信息介绍了如何在[应用程序客户端](user-pool-settings-client-apps.md)和应用程序中设置身份验证流程。

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

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

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

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

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

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

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

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

**为应用程序客户端配置身份验证流程（使用 API/SDK）**  
要使用 Amazon Cognito API 为应用程序客户端配置可用的身份验证流程，请在[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#CognitoUserPools-CreateUserPoolClient-request-ExplicitAuthFlows)或[UpdateUserPoolClient](https://docs.aws.amazon.com/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.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-AuthFlow)或[AdminInitiateAuth](https://docs.aws.amazon.com/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 更多。例如，无密码身份验证和通行密钥身份验证仅在托管登录中可用。

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

**通过外部身份提供者（IdP）登录的托管登录**  
在使用[身份验证](authentication-flows-selection-sdk.md)时，您无法通过[第三方 IdPs](cognito-user-pools-identity-federation.md)登录用户 AWS 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.aws.amazon.com/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 ]

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

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 AWS DK 登录。\]](http://docs.aws.amazon.com/zh_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用户的会话在无需再次输入凭证的情况下安全地完成刷新。

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

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

# 为托管登录配置身份验证方法
<a name="authentication-flows-selection-managedlogin"></a>

当您希望用户登录、注销或重置密码时，可以调用[托管登录页面](cognito-user-pools-managed-login.md)，这是用户池身份验证的 Web 前端。在此模式下，您的应用程序导入 OIDC 库，以处理在用户池托管登录页面上进行的基于浏览器的身份验证尝试。用户可用的身份验证方式取决于您的用户池配置和应用程序客户端的配置。在应用程序客户端中实现 `ALLOW_USER_AUTH` 流程后，Amazon Cognito 会提示用户从可用选项中选择一种登录方式。如果实现 `ALLOW_USER_PASSWORD_AUTH` 并分配一个 SAML 提供商，则登录页面会向用户提供输入用户名和密码或通过其 IdP 进行登录的选项。

Amazon Cognito 用户池控制台可帮助您快速为应用程序设置托管登录身份验证。创建新的用户池时，请指定您要开发的平台，控制台将为您提供实现 OIDC 的示例，以及带有用于实现登录和注销流程的入门代码的 OAuth 库。您可以使用多种 OIDC 依赖方实现来构建托管登录。建议您尽可能使用[经过认证的 OIDC 依赖方库](https://openid.net/developers/certified-openid-connect-implementations/)。有关更多信息，请参阅 [用户池入门](getting-started-user-pools.md)。

通常，OIDC 信赖方库会定期检查用户池的`.well-known/openid-configuration`终端节点，以确定发行者， URLs 例如令牌端点和授权端点。作为最佳实践，只要存在相应选项，就应实现这种自动发现行为。手动配置颁发者端点可能引入错误。例如，您可能会更改用户池的域。而 `openid-configuration` 的路径并不与用户池域链接，因此能够自动发现服务端点的应用程序将自动适配您的域变更。

## 托管登录的用户池设置
<a name="authentication-flows-selection-managedlogin-settings"></a>

您可能希望为应用程序启用多个身份提供者的登录方式，或者将 Amazon Cognito 用作独立的用户目录。您还可能希望收集用户属性、设置并提示 MFA，或要求使用电子邮件地址作为用户名。您无法直接编辑托管登录和托管 UI 中的字段。相反，托管登录身份验证流程的处理方式由您的用户池配置自动决定。

以下用户池配置项决定了 Amazon Cognito 在托管登录和托管 UI 中向用户展示的身份验证方法。

------
#### [ User pool options (Sign-in menu) ]

以下选项位于 Amazon Cognito 控制台中用户池的**登录**菜单中。

**Cognito 用户池登录选项**  
提供用户名选项。您的托管登录和托管 UI 页面仅接受您所选格式的用户名。例如，当您将用户池设置为使用**电子邮件**作为唯一登录选项时，托管登录页面就只接受电子邮件格式的用户名。

**必需的属性**  
当您在用户池中将某个属性设置为必填项时，托管登录会在用户注册时提示其提供该属性的值。

**基于选择的登录选项**  
[基于选择的身份验证](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)等身份验证方法。这些方法仅适用于配置了[托管登录域](managed-login-branding.md)且[功能计划](cognito-sign-in-feature-plans.md)高于**精简版**层级的用户池。

**多重身份验证**  
托管登录和托管 UI 负责处理 [MFA](user-pool-settings-mfa.md) 的注册和身份验证操作。当您的用户池要求使用 MFA 时，登录页面会自动提示用户设置额外的身份验证因素。对于已配置 MFA 的用户，登录页面也会提示其输入 MFA 验证码以完成身份验证。当用户池中关闭或设为可选 MFA 时，登录页面不会提示用户设置 MFA。

**用户账户恢复**  
用户池的自助[账户恢复]()设置决定了登录页面是否显示供用户重置密码的链接。

------
#### [ User pool options (Domain menu) ]

以下选项位于 Amazon Cognito 控制台中用户池的**域**菜单中。

**域：**  
您选择的用户池域决定了在调用用户浏览器进行身份验证时，用户所打开链接的路径。

**品牌版本**  
您选择的品牌版本决定了用户池域显示的是托管登录还是托管 UI。

------
#### [ User pool options (Social and external providers menu) ]

以下选项位于 Amazon Cognito 控制台中用户池的**社交和外部提供商**菜单中。

**提供商**  
对于用户池中的每个应用程序客户端，您添加到用户池中的身份提供者 (IdPs) 可以处于活动状态或非活动状态。

------
#### [ App client options ]

以下选项位于 Amazon Cognito 控制台中用户池的**应用程序客户端**菜单中。要查看这些选项，请从列表中选择一个应用程序客户端。

**快速设置指南**  
快速设置指南包含适用于各种开发人员环境的代码示例。它们包含将托管登录身份验证与您的应用程序集成所需的库。

**应用程序客户端信息**  
编辑此配置以设置 IdPs 为当前应用程序客户端所代表的应用程序分配的设置。在托管登录页面上，Amazon Cognito 会向用户显示相应的选项。这些选项由已分配的身份验证方法和 IdP 决定。例如，如果您分配了一个名为 `MySAML` 的 SAML 2.0 IdP 以及本地用户池登录，则托管登录页面将显示身份验证方法提示以及一个用于 `MySAML` 的按钮。

**身份验证设置**  
编辑此配置可设置应用程序的身份验证方法。在托管登录页面上，Amazon Cognito 会向用户显示相应的选项。这些选项由用户池作为 IdP 的可用性以及您所分配的身份验证方法决定。例如，如果您分配了基于选择的 `ALLOW_USER_AUTH` 身份验证，则托管登录页面将显示可用选项，例如输入电子邮件地址或使用通行密钥登录。托管登录页面还会为分配的用户呈现按钮 IdPs。

**登录页面**  
使用此选项卡中提供的选项，可设置托管登录或托管 UI 用户交互式页面的视觉效果。有关更多信息，请参阅 [将品牌应用于托管登录页面](managed-login-branding.md)。

------

# 在中管理身份验证方法 AWS SDKs
<a name="authentication-flows-selection-sdk"></a>

Amazon Cognito 用户池中的用户可以通过多种初始登录选项（也称为*因素*）进行登录。对于某些因素，用户还可以继续完成多重身份验证（MFA）。这些第一重因素包括用户名和密码、一次性密码、通行密钥以及自定义身份验证。有关更多信息，请参阅 [身份验证流程](amazon-cognito-user-pools-authentication-flow-methods.md)。当您的应用程序具有内置 UI 组件并导入 S AWS DK 模块时，您必须构建用于身份验证的应用程序逻辑。此时，您必须从两种主要方法中选择其一，并通过此方法确定要实现的身份验证机制。

您可以实现*基于客户端的身份验证*，即由您的应用程序（或客户端）在一开始就声明所使用的身份验证类型。另一种选择是*基于选择的身份验证*，即您的应用程序先收集用户名，然后请求该用户可用的身份验证类型。您可以根据需求，在同一个应用程序中同时实现这两种模式，或在不同的应用程序客户端之间分别使用。每种方法都有其独有的功能，例如：基于客户端的身份验证支持自定义身份验证，而基于选择的身份验证则支持无密码身份验证。

在使用用户池 API 的 AWS SDK 实现进行身份验证的自定义应用程序中，您的 API 请求结构必须与用户池配置、应用程序客户端配置和客户端首选项保持一致。如果 `InitiateAuth` 会话以 `AuthFlow` 值为 `USER_AUTH` 开始，则启动基于选择的身份验证。Amazon Cognito 会在 API 响应中返回一个质询，内容为用户的首选身份验证方法或可用选项列表。如果会话以 `AuthFlow` 值为 `CUSTOM_AUTH` 开始，则直接进入基于 Lambda 触发器的自定义身份验证流程。

有些身份验证方法固定为两种流程中的一种，有些方法在两种流程中都可用。

**Topics**
+ [基于选择的身份验证](#authentication-flows-selection-choice)
+ [基于客户端的身份验证](#authentication-flows-selection-client)

## 基于选择的身份验证
<a name="authentication-flows-selection-choice"></a>

您的应用程序可以在基于选择的身份验证中请求以下身份验证方法。在[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-AuthParameters)或的`PREFERRED_CHALLENGE`参数中声明这些选项 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html#CognitoUserPools-AdminInitiateAuth-request-AuthParameters)，或者在[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html#CognitoUserPools-RespondToAuthChallenge-request-ChallengeName)或的`ChallengeName`参数中声明这些选项[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html#CognitoUserPools-AdminRespondToAuthChallenge-request-ChallengeName)。

1. `EMAIL_OTP` 和 `SMS_OTP`

   [使用一次性密码进行无密码登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)

1. `WEB_AUTHN`

   [使用密钥进行无密码登录 WebAuthn](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passkey)

1. `PASSWORD`

   [使用永久密码登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-password)

   [使用永久密码和安全有效载荷登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-srp)

   [登录后进行 MFA](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-mfa)

要在其 API 上下文中查看这些选项，请参阅`ChallengeName`中的[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html#CognitoUserPools-RespondToAuthChallenge-request-ChallengeName)。

基于选择的登录会发出一个质询以响应您的初始请求。该质询要么验证所请求的选项是否可用，要么提供一份可用选项列表。您的应用程序可将这些选项显示给用户，用户随后输入其首选登录方式的凭证，并通过响应质询继续完成身份验证。

您的身份验证流程中有以下基于选择的选项。此类请求均要求您的应用程序首先收集用户名，或从缓存中获取用户名。

1. 仅使用 `USERNAME` 作为 `AuthParameters` 来请求选项。Amazon Cognito 返回 `SELECT_CHALLENGE` 质询。随后，您的应用程序可以提示用户选择一种质询方式，并将该选择作为响应返回给用户池。

1. 通过在 `PREFERRED_CHALLENGE` 的 `AuthParameters` 以及您首选质询（如有）的参数来请求一个首选质询。例如，如果您请求的 `PREFERRED_CHALLENGE` 为 `PASSWORD_SRP`，则还必须包含 `SRP_A`。如果您的用户、用户池和应用程序客户端都针对首选挑战进行了配置，则 Amazon Cognito 会以该挑战的下一步作为响应，例如`PASSWORD_VERIFIER`在`PASSWORD_SRP`流程中或`EMAIL_OTP`和`SMS_OTP`流程[CodeDeliveryDetails](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CodeDeliveryDetailsType.html)中。如果首选质询不可用，Amazon Cognito 将返回 `SELECT_CHALLENGE`，并附带一份可用质询列表。

1. 首先让用户登录，然后再请求其基于选择的身份验证选项。使用已登录用户的访问令牌的[GetUserAuthFactors](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAuthFactors.html)请求会返回他们可用的基于选择的身份验证因素和 MFA 设置。通过此身份验证选项，用户可先使用用户名和密码登录，随后启用其他形式的身份验证。您也可以使用此操作，为已通过首选质询完成登录的用户检查其他可用选项。

要[为应用程序客户端配置](authentication.md#authentication-implement)基于选择的身份验证，请在允许的身份验证流程中添加 `ALLOW_USER_AUTH`。您还必须在用户池配置中选择要允许的基于选择的身份验证因素。以下流程说明了如何选择基于选择的身份验证因素。

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

**在用户池中配置基于选择的身份验证选项**

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

1. 在用户池配置中，选择**登录**菜单。找到**基于选择的登录选项**，然后选择**编辑**。

1. **密码**选项始终可用。这包括 `PASSWORD` 和 `PASSWORD_SRP` 流程。选择要添加到用户选项中的**其他选项**。您可以为 `WEB_AUTHN` 添加**通行密钥**，为 `EMAIL_OTP` 添加**电子邮件消息一次性密码**，为 `SMS_OTP` 添加 **SMS 消息一次性密码**。

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

------
#### [ API/SDK ]

以下部分[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)请求正文配置了基于选择的身份验证的所有可用选项。

```
"Policies": {
    "SignInPolicy": {
        "AllowedFirstAuthFactors": [
            "PASSWORD",
            "WEB_AUTHN",
            "EMAIL_OTP",
            "SMS_OTP"
        ]
    }
},
```

------

## 基于客户端的身份验证
<a name="authentication-flows-selection-client"></a>

基于客户端的身份验证支持以下身份验证流程。在[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-AuthFlow)或的`AuthFlow`参数中声明这些选项[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html#CognitoUserPools-AdminInitiateAuth-request-AuthFlow)。

1. `USER_PASSWORD_AUTH` 和 `ADMIN_USER_PASSWORD_AUTH`

   [使用永久密码登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-password)

   [登录后进行 MFA](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-mfa)

   此身份验证流程在基于选择的身份验证中等同于 `PASSWORD`。

1. `USER_SRP_AUTH`

   [使用永久密码和安全有效载荷登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-srp)

   [登录后进行 MFA](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-mfa)

   此身份验证流程在基于选择的身份验证中等同于 `PASSWORD_SRP`。

1. `REFRESH_TOKEN_AUTH`

   [刷新令牌](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-refresh)

   此身份验证流程仅在基于客户端的身份验证中可用。

1. `CUSTOM_AUTH`

   [自定义身份验证](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-custom)

   此身份验证流程仅在基于客户端的身份验证中可用。

对于基于客户端的身份验证，Amazon Cognito 假设您已在用户开始身份验证流程之前确定了其希望使用的身份验证方式。确定用户要提供的登录因素的逻辑必须通过默认设置或自定义提示来确定，然后在首次向用户池发起的请求中声明。`InitiateAuth` 请求需声明一个与所列选项之一直接对应的登录 `AuthFlow`，例如 `USER_SRP_AUTH`。通过该声明，该请求还包含启动身份验证所需的参数，例如 `USERNAME`、`SECRET_HASH` 和 `SRP_A`。Amazon Cognito 可能会在该请求之后返回额外的质询，例如针对 SRP 的 `PASSWORD_VERIFIER`，或针对使用 TOTP MFA 的密码登录的 `SOFTWARE_TOKEN_MFA`。

要[为应用程序客户端配置](authentication.md#authentication-implement)基于客户端的身份验证，请在允许的身份验证流程中添加 `ALLOW_USER_AUTH` 之外的任何身份验证流程。示例包括 `ALLOW_USER_PASSWORD_AUTH`、`ALLOW_CUSTOM_AUTH`、`ALLOW_REFRESH_TOKEN_AUTH`。允许基于客户端的身份验证流程无需额外的用户池配置。

# 身份验证流程
<a name="amazon-cognito-user-pools-authentication-flow-methods"></a>

Amazon Cognito 用户池的身份验证过程最好可以描述为一个*流程*：用户首先做出初始选择，提交凭证，并响应额外的质询。当您在应用程序中实现托管登录身份验证时，Amazon Cognito 会自动管理这些提示和质询的流程。当您在应用程序后端使用 S AWS DK 实现流程时，必须构造请求逻辑，提示用户输入并响应挑战。

作为应用程序管理员，您的用户特征、安全需求和授权模型将帮助您确定允许用户如何登录。请思考以下问题。
+ 我是否要允许用户使用[其他身份提供者的凭据登录 (IdPs)](#amazon-cognito-user-pools-authentication-flow-methods-federated)？
+ [用户名和密码](#amazon-cognito-user-pools-authentication-flow-methods-password)是否足以作为身份证明？
+ 我的用户名密码身份验证请求是否可能被拦截？ 我的应用程序是否应该直接传输密码，还是应[通过哈希和加密盐协商完成身份验证](#amazon-cognito-user-pools-authentication-flow-methods-srp)？
+ 我是否要允许用户跳过密码输入，[直接接收一次性密码](#amazon-cognito-user-pools-authentication-flow-methods-passwordless)进行登录？
+ 我是否希望允许用户使用[指纹、面部识别或硬件安全密钥](#amazon-cognito-user-pools-authentication-flow-methods-passkey)登录？
+ 我是否需要启用[多重身份验证（MFA）](#amazon-cognito-user-pools-authentication-flow-methods-mfa)？如果需要，应在何时执行？
+ 我是否希望[在不重复提示输入凭证的情况下持久化用户会话](#amazon-cognito-user-pools-authentication-flow-methods-refresh)？
+ 我是否希望[将授权模型扩展到](#amazon-cognito-user-pools-authentication-flow-methods-custom) Amazon Cognito 内置功能之外？

当您回答了这些问题后，就可以学习如何激活相关功能，并在应用程序发起的身份验证请求中加以实现。

为用户设置登录流程后，您可以通过 API 操作请求来检查其当前状态的 MFA [和](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)基于选择的身份验证因素。[GetUserAuthFactors](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAuthFactors.html)此操作需要使用已登录用户的访问令牌进行授权，并返回该用户的身份验证因素及 MFA 设置。

**Topics**
+ [使用第三方登录 IdPs](#amazon-cognito-user-pools-authentication-flow-methods-federated)
+ [使用永久密码登录](#amazon-cognito-user-pools-authentication-flow-methods-password)
+ [使用永久密码和安全有效载荷登录](#amazon-cognito-user-pools-authentication-flow-methods-srp)
+ [使用一次性密码进行无密码登录](#amazon-cognito-user-pools-authentication-flow-methods-passwordless)
+ [使用密钥进行无密码登录 WebAuthn](#amazon-cognito-user-pools-authentication-flow-methods-passkey)
+ [登录后进行 MFA](#amazon-cognito-user-pools-authentication-flow-methods-mfa)
+ [刷新令牌](#amazon-cognito-user-pools-authentication-flow-methods-refresh)
+ [自定义身份验证](#amazon-cognito-user-pools-authentication-flow-methods-custom)
+ [用户迁移身份验证流程](#amazon-cognito-user-pools-user-migration-authentication-flow)

## 使用第三方登录 IdPs
<a name="amazon-cognito-user-pools-authentication-flow-methods-federated"></a>

Amazon Cognito 用户池充当 “用苹果登录”、“用亚马逊登录” 和 OpenID Connect (OIDC) 服务之间的 IdPs身份验证会话的中间代理。此过程也称为*联合登录* 或*联合身份验证*。联合身份验证不使用您在应用程序客户端中配置的任何内置身份验证流程。相反，您可以将已配置的用户池分配 IdPs 给您的应用程序客户端。当用户在托管登录页面选择其 IdP，或您的应用程序通过重定向到该 IdP 的登录页面来发起会话时，联合登录便会触发。

通过联合登录，您将主要身份验证因素和 MFA 身份验证因素委托给用户的 IdP。除非您[将联合用户与本地用户关联](cognito-user-pools-identity-federation-consolidate-users.md)，否则 Amazon Cognito 不会为该联合用户添加本节中提到的其他高级身份验证流程。未关联的联合用户虽有用户名，但其本质上是映射属性数据的存储，通常不会独立于基于浏览器的流程用于登录。

**实现资源**
+ [使用第三方身份提供者进行用户池登录](cognito-user-pools-identity-federation.md)

## 使用永久密码登录
<a name="amazon-cognito-user-pools-authentication-flow-methods-password"></a>

在 Amazon Cognito 用户池中，每个用户都有一个用户名。这可能是电话号码、电子邮件地址，或由用户选择或管理员提供的标识符。此类用户可使用用户名和密码登录，并可选择性地提供 MFA。用户池可通过公开的或经 IAM 授权的 API 操作及 SDK 方法执行用户名密码登录。您的应用程序可以直接将密码发送至用户池进行身份验证。您的用户池会使用其他质询或 JSON Web 令牌 (JWTs) 作为成功身份验证的结果进行响应。

------
#### [ Activate password sign-in ]

要激活使用用户名和密码的[基于客户端的身份验证](authentication-flows-selection-sdk.md#authentication-flows-selection-client)，请配置您的应用程序客户端以允许该方式。在 Amazon Cognito 控制台中，导航到用户池配置中**应用程序**下的**应用程序客户端**菜单。要为客户端移动应用程序或原生应用程序启用明文密码登录，请编辑应用程序客户端，并在**身份验证流程**下选择**使用用户名和密码登录：ALLOW\$1USER\$1PASSWORD\$1AUTH**。要为服务器端应用程序启用明文密码登录，请编辑应用程序客户端，并选择**使用服务器端管理凭证登录：ALLOW\$1ADMIN\$1USER\$1PASSWORD\$1AUTH**。

要激活使用用户名和密码的[基于选择的身份验证](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)，请配置您的应用程序客户端以允许该方式。编辑应用程序客户端，然后选择**基于选择的登录：ALLOW\$1USER\$1AUTH**。

![\[一张来自 Amazon Cognito 控制台的屏幕截图，展示了为应用程序客户端选择明文密码身份验证流程的选项。选项 ALLOW_USER_PASSWORD_AUTH、ALLOW_ADMIN_USER_PASSWORD_AUTH 和 ALLOW_USER_AUTH 已选中。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/screenshot-choose-password-admin-password-and-user-auth.png)


要验证密码身份验证在基于选择的身份验证流程中是否可用，请导航到**登录菜单**，查看**基于选择的登录选项**下的部分。如果**密码**在**可用选项**下可见，则可以使用明文密码身份验证进行登录。**密码**选项包括明文和 SRP 用户名密码身份验证变体。

![\[一张来自 Amazon Cognito 控制台的屏幕截图，展示了用户池在 USER_AUTH 基于选择的登录配置中的密码身份验证选项。“密码”选项显示为已启用。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/screenshot-password-flow-in-user-auth.png)


在[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)或[UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)请求中`ExplicitAuthFlows`使用您的首选 username-and-password身份验证选项进行配置。

```
"ExplicitAuthFlows": [ 
   "ALLOW_USER_PASSWORD_AUTH",
   "ALLOW_ADMIN_USER_PASSWORD_AUTH",
   "ALLOW_USER_AUTH"
]
```

在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)请求中，`Policies`使用您想要支持的基于选择的身份验证流程进行配置。`AllowedFirstAuthFactors` 中的 `PASSWORD` 值同时包括明文密码和 SRP 身份验证流程选项。

```
"Policies": {
   "SignInPolicy": {
      "AllowedFirstAuthFactors": [
         "PASSWORD",
         "EMAIL_OTP",
         "WEB_AUTHN"
      ]
   }
}
```

------
#### [ Choice-based sign-in with a password ]

要使用用户名密码身份验证让用户登录应用程序，请按以下方式配置您的[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)请求的正文。如果当前用户符合使用用户名密码身份验证的条件，该登录请求将成功，或继续进入下一个质询。否则，系统将返回一份可用的主要因素身份验证质询列表。以下参数集合是登录所需的最低要求。此外还支持其他参数。

```
{
   "AuthFlow": "USER_AUTH",
   "AuthParameters": { 
      "USERNAME" : "testuser",
      "PREFERRED_CHALLENGE" : "PASSWORD",
      "PASSWORD" : "[User's password]"
   },
   "ClientId": "1example23456789"
}
```

您也可以省略 `PREFERRED_CHALLENGE` 值，然后将收到一个响应，其中包含该用户符合条件的登录因素列表。

```
{
   "AuthFlow": "USER_AUTH",
   "AuthParameters": { 
      "USERNAME" : "testuser"
   },
   "ClientId": "1example23456789"
}
```

如果您未提交首选质询，或所提交的用户不符合其首选质询的条件，Amazon Cognito 将在 `AvailableChallenges` 中返回一个可用选项列表。如果`AvailableChallenges`包含 o `ChallengeName` `PASSWORD` f，则可以使用以下格式的[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)或[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)质询响应继续进行身份验证。您必须传递一个 `Session` 参数，将该质询响应与初始登录请求的 API 响应关联起来。以下参数集合是登录所需的最低要求。此外还支持其他参数。

```
{
   "ChallengeName": "PASSWORD",
   "ChallengeResponses": { 
      "USERNAME" : "testuser",
      "PASSWORD" : "[User's Password]"
   },
   "ClientId": "1example23456789",
   "Session": "[Session ID from the previous response"
}
```

对于符合条件且成功的首选质询请求，以及 `PASSWORD` 质询响应，Amazon Cognito 会返回令牌，或要求用户完成额外的质询，例如多重身份验证（MFA）。

------
#### [ Client-based sign-in with a password ]

要使用用户名密码身份验证让用户登录到客户端应用程序，请按以下方式配置请求的正文。[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)以下参数集合是登录所需的最低要求。此外还支持其他参数。

```
{
   "AuthFlow": "USER_PASSWORD_AUTH",
   "AuthParameters": { 
      "USERNAME" : "testuser",
      "PASSWORD" : "[User's password]"
   },
   "ClientId": "1example23456789"
}
```

要使用用户名密码身份验证让用户登录服务器端应用程序，请按以下方式配置请求的正文。[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)您的应用程序必须使用 AWS 凭证签署此请求。以下参数集合是登录所需的最低要求。此外还支持其他参数。

```
{
   "AuthFlow": "ADMIN_USER_PASSWORD_AUTH",
   "AuthParameters": { 
      "USERNAME" : "testuser",
      "PASSWORD" : "[User's password]"
   },
   "ClientId": "1example23456789"
}
```

对于成功的请求，Amazon Cognito 会返回令牌，或要求用户完成额外的质询，例如多重身份验证（MFA）。

------

## 使用永久密码和安全有效载荷登录
<a name="amazon-cognito-user-pools-authentication-flow-methods-srp"></a>

用户池中的另一种用户名密码登录方式是使用安全远程密码（SRP）协议。该选项会发送对密码的“知识证明”，即一个密码哈希值和一个加密盐，供用户池进行验证。由于发送给 Amazon Cognito 的请求中不包含任何可读的密钥信息，因此您的应用程序是能够处理用户输入密码的唯一实体。SRP 身份验证涉及数学计算，建议使用 SDK 中可导入的现有组件来实现。SRP 通常在客户端应用程序（如移动应用程序）中实现。有关该协议的更多信息，请参阅 [The Stanford SRP Homepage](http://srp.stanford.edu/)。[维基百科](https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol)也提供了相关资源和示例。此外，[多种公开的库](https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol#Implementations)可用于在您的身份验证流程中执行 SRP 计算。

Amazon Cognito 身份验证 initiate-challenge-respond顺序使用 SRP 验证用户及其密码。您必须先配置用户池和应用程序客户端以支持 SRP 身份验证，然后在应用程序中实现登录请求与质询响应的逻辑。您的 SRP 库可生成随机数和计算值，用以向用户池证明您持有用户的密码。应用程序需将这些计算得出的值填入 Amazon Cognito 用户池 API 操作或 SDK 方法中用于身份验证的 JSON 格式的 `AuthParameters` 和 `ChallengeParameters` 字段。

------
#### [ Activate SRP sign-in ]

要激活使用用户名和 SRP 的[基于客户端的身份验证](authentication-flows-selection-sdk.md#authentication-flows-selection-client)，请配置您的应用程序客户端以允许该方式。在 Amazon Cognito 控制台中，导航到用户池配置中**应用程序**下的**应用程序客户端**菜单。要为客户端移动应用程序或原生应用程序启用 SRP 登录，请编辑应用程序客户端，并在**身份验证流程**下选择**使用安全远程密码（SRP）登录：ALLOW\$1USER\$1SRP\$1AUTH**。

要激活使用用户名和 SRP 的[基于选择的身份验证](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)，请编辑您的应用程序客户端，并选择**基于选择的登录：ALLOW\$1USER\$1AUTH**。

![\[一张来自 Amazon Cognito 控制台的屏幕截图，展示了为应用程序客户端选择安全远程密码身份验证流程的选项。选项 ALLOW_USER_SRP_AUTH 和 ALLOW_USER_AUTH 已选中。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/screenshot-choose-SRP-and-user-auth.png)


要验证 SRP 身份验证在基于选择的身份验证流程中是否可用，请导航到**登录菜单**，查看**基于选择的登录选项**下的部分。如果**密码**在**可用选项**下可见，则可以使用 SRP 身份验证进行登录。**密码**选项包括明文和 SRP 用户名密码身份验证变体。

![\[一张来自 Amazon Cognito 控制台的屏幕截图，展示了用户池在 USER_AUTH 基于选择的登录配置中的密码身份验证选项。“密码”选项显示为已启用。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/screenshot-password-flow-in-user-auth.png)


在[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)或[UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)请求中`ExplicitAuthFlows`使用您的首选 username-and-password身份验证选项进行配置。

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

在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)请求中，`Policies`使用您想要支持的基于选择的身份验证流程进行配置。`AllowedFirstAuthFactors` 中的 `PASSWORD` 值同时包括明文密码和 SRP 身份验证流程选项。

```
"Policies": {
   "SignInPolicy": {
      "AllowedFirstAuthFactors": [
         "PASSWORD",
         "EMAIL_OTP",
         "WEB_AUTHN"
      ]
   }
}
```

------
#### [ Choice-based sign-in with SRP ]

要让用户通过 SRP 使用用户名密码身份验证登录应用程序，请按以下方式配置您的[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)请求的正文。如果当前用户符合使用用户名密码身份验证的条件，该登录请求将成功，或继续进入下一个质询。否则，系统将返回一份可用的主要因素身份验证质询列表。以下参数集合是登录所需的最低要求。此外还支持其他参数。

```
{
   "AuthFlow": "USER_AUTH",
   "AuthParameters": { 
      "USERNAME" : "testuser",
      "PREFERRED_CHALLENGE" : "PASSWORD_SRP",
      "SRP_A" : "[g^a % N]"
   },
   "ClientId": "1example23456789"
}
```

您也可以省略 `PREFERRED_CHALLENGE` 值，然后将收到一个响应，其中包含该用户符合条件的登录因素列表。

```
{
   "AuthFlow": "USER_AUTH",
   "AuthParameters": { 
      "USERNAME" : "testuser"
   },
   "ClientId": "1example23456789"
}
```

如果您未提交首选质询，或所提交的用户不符合其首选质询的条件，Amazon Cognito 将在 `AvailableChallenges` 中返回一个可用选项列表。如果`AvailableChallenges`包含 o `ChallengeName` `PASSWORD_SRP` f，则可以使用以下格式的[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)或[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)质询响应继续进行身份验证。您必须传递一个 `Session` 参数，将该质询响应与初始登录请求的 API 响应关联起来。以下参数集合是登录所需的最低要求。此外还支持其他参数。

```
{
   "ChallengeName": "PASSWORD_SRP",
   "ChallengeResponses": { 
      "USERNAME" : "testuser",
      "SRP_A" : "[g^a % N]"
   },
   "ClientId": "1example23456789",
   "Session": "[Session ID from the previous response"
}
```

Amazon Cognito 会对符合条件的首选质询请求以及 `PASSWORD_SRP` 质询响应返回一个 `PASSWORD_VERIFIER` 质询。您的客户必须完成 SRP 计算并回应[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)或[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)请求中的质疑。

```
{
   "ChallengeName": "PASSWORD_VERIFIER",
   "ChallengeResponses": { 
      "PASSWORD_CLAIM_SIGNATURE" : "string",
      "PASSWORD_CLAIM_SECRET_BLOCK" : "string",
      "TIMESTAMP" : "string"
   },
   "ClientId": "1example23456789",
   "Session": "[Session ID from the previous response]"
}
```

在成功响应 `PASSWORD_VERIFIER` 质询后，Amazon Cognito 会颁发令牌，或要求用户完成另一项必需的质询，例如多重身份验证（MFA）。

------
#### [ Client-based sign-in with SRP ]

SRP 身份验证更常用于客户端身份验证，而非服务器端。但是，您可以将 SRP 身份验证与[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)和[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)一起使用。要将用户登录到应用程序，请按如下方式配置 `InitiateAuth` 或 `AdminInitiateAuth` 请求的正文。以下参数集合是登录所需的最低要求。此外还支持其他参数。

客户端通过将生成元 *g*（模 N）的幂次提升到一个秘密随机整数 *a* 来生成 `SRP_A`。

```
{
   "AuthFlow": "USER_SRP_AUTH",
   "AuthParameters": { 
      "USERNAME" : "testuser",
      "SRP_A" : "[g^a % N]"
   },
   "ClientId": "1example23456789"
}
```

Amazon Cognito 以 `PASSWORD_VERIFIER` 质询进行响应。您的客户必须完成 SRP 计算并回应[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)或[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)请求中的质疑。

```
{
   "ChallengeName": "PASSWORD_VERIFIER",
   "ChallengeResponses": { 
      "PASSWORD_CLAIM_SIGNATURE" : "string",
      "PASSWORD_CLAIM_SECRET_BLOCK" : "string",
      "TIMESTAMP" : "string"
   },
   "ClientId": "1example23456789",
   "Session": "[Session ID from the previous response]"
}
```

在成功响应 `PASSWORD_VERIFIER` 质询后，Amazon Cognito 会颁发令牌，或要求用户完成另一项必需的质询，例如多重身份验证（MFA）。

------

## 使用一次性密码进行无密码登录
<a name="amazon-cognito-user-pools-authentication-flow-methods-passwordless"></a>

密码可能会丢失或被盗。您可能希望仅验证用户是否能够访问已验证的电子邮件地址、电话号码或身份验证器应用程序。解决方法是采用*无密码* 登录。应用程序可以提示用户输入其用户名、电子邮件地址或电话号码。随后，Amazon Cognito 会生成一个一次性密码（OTP），即一个用户必须确认的验证码。用户成功提交该验证码后，身份验证即完成。

一次性密码 (OTP) 身份验证流程与用户池中必需的多因素身份验证 (MFA) 不兼容。当您设置为时，带有用户验证的密钥身份验证可以满足 MFA 要求。`FactorConfiguration` `MULTI_FACTOR_WITH_USER_VERIFICATION`如果 MFA 在您的用户池中是可选的，则激活 MFA 的用户将无法使用 OTP 第一因素登录。在 MFA 为可选的用户池中，没有 MFA 偏好的用户可以使用无密码身份验证因素进行登录。有关更多信息，请参阅 [有关用户池 MFA 的需知信息](user-pool-settings-mfa.md#user-pool-settings-mfa-prerequisites)。

当用户在无密码身份验证流程中正确输入其通过短信或电子邮件收到的验证码时，除了完成用户身份验证外，您的用户池还会将该用户原先未验证的电子邮件地址或电话号码属性标记为已验证。无论您是否将用户池配置为[自动验证](signing-up-users-in-your-app.md)电子邮件地址或电话号码，该用户的状态都会从 `UNCONFIRMED` 变更为 `CONFIRMED`。

**启用无密码登录后的新选项**  
当您在用户池中激活无密码身份验证时，某些用户流程的工作方式会发生变化。

1. 用户在注册时无需设置密码，并在登录时选择一个无密码身份验证因素。您也可以以管理员身份创建不带密码的用户。

1. [通过 CSV 文件导入](cognito-user-pools-using-import-tool.md)的用户可以立即使用无密码身份验证因素登录，无需在登录前设置密码。

1. 没有密码的用户可以提交不带`PreviousPassword`参数[ChangePassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ChangePassword.html)的 API 请求。

**使用自动登录 OTPs**  
通过电子邮件或短信注册并确认其用户帐户的用户 OTPs 可以使用与其确认消息匹配的无密码因素自动登录。在托管登录 UI 中，完成账户确认且符合使用确认码传送方式进行 OTP 登录的条件的用户，在提供确认码后会自动进入首次登录流程。在带有 AWS SDK 的自定义应用程序中，将以下参数传递给[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)或[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)操作。
+ [ConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html)API 响应中的`Session`参数作为`Session`请求参数。
+ 其中[AuthFlow](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-AuthFlow)之一`USER_AUTH`。

您可以传递值为 `EMAIL_OTP` 或 `SMS_OTP` 的 [PREFERRED\$1CHALLENGE](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-AuthParameters)，但这不是必需的。`Session` 参数提供身份验证的证明，当您传入有效的会话代码时，Amazon Cognito 会忽略 `AuthParameters`。

登录操作将返回表示身份验证成功的响应，如果满足以下条件 [AuthenticationResult](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AuthenticationResultType.html)，则不会再进行其他质询。
+ `Session` 代码有效且未过期。
+ 用户符合使用 OTP 身份验证方法的条件。

------
#### [ Activate passwordless sign-in ]

**控制台**  
要激活无密码登录，请先配置您的用户池，以允许使用一种或多种无密码类型作为主要登录方式，然后配置您的应用程序客户端以允许 `USER_AUTH` 身份验证流程。在 Amazon Cognito 控制台中，导航到用户池配置中**身份验证**下的**登录**菜单。编辑**基于选择的登录选项**，然后选择**电子邮件消息一次性密码**或 **SMS 消息一次性密码**。您可以同时激活这两个选项。保存更改。

导航到**应用程序客户端**菜单，然后选择一个应用程序客户端或新建一个。选择**编辑**，然后选择**登录时选择身份验证类型：ALLOW\$1USER\$1AUTH**。

**API/SDK**  
在用户池 API 中，`SignInPolicy`使用[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)请求中的相应无密码选项进行配置。

```
"SignInPolicy": { 
    "AllowedFirstAuthFactors": [ 
        "EMAIL_OTP",
        "SMS_OTP"
    ]
}
```

使用[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)或[UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)请求中的必填选项配置您的应用程序客户端`ExplicitAuthFlows`。

```
"ExplicitAuthFlows": [ 
   "ALLOW_USER_AUTH"
]
```

------
#### [ Sign in with passwordless ]

无密码登录没有可在和中指定的[基于客户端`AuthFlow`的](authentication-flows-selection-sdk.md#authentication-flows-selection-client)登录方式。[InitiateAuth[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)OTP 身份验证仅在[基于选择](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)`AuthFlow`的情况下可用`USER_AUTH`，您可以在其中请求首选登录选项或从用户的登录选项中选择无密码选项。[AvailableChallenges](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-response-AvailableChallenges)要将用户登录到应用程序，请按如下方式配置 `InitiateAuth` 或 `AdminInitiateAuth` 请求的正文。以下参数集合是登录所需的最低要求。此外还支持其他参数。

在此示例中，我们不知道用户想要通过哪种方式登录。如果我们添加一个 `PREFERRED_CHALLENGE` 参数并且用户可以使用该首选质询，则 Amazon Cognito 将返回该质询。

```
{
   "AuthFlow": "USER_AUTH",
   "AuthParameters": { 
      "USERNAME" : "testuser"
   },
   "ClientId": "1example23456789"
}
```

您也可以在本例中向 `AuthParameters` 添加 `"PREFERRED_CHALLENGE": "EMAIL_OTP"` 或 `"PREFERRED_CHALLENGE": "SMS_OTP"`。如果用户符合该首选方式的使用条件，您的用户池会立即向该用户的电子邮件地址或电话号码发送验证码，并返回 `"ChallengeName": "EMAIL_OTP"` 或 `"ChallengeName": "SMS_OTP"`。

如果您没有指定首选质询，Amazon Cognito 会返回一个 `AvailableChallenges` 参数。

```
{
   "AvailableChallenges": [ 
      "EMAIL_OTP", 
      "SMS_OTP",
      "PASSWORD"
    ],
   "Session": "[Session ID]"
}
```

该用户符合以下登录方式的条件：通过电子邮件消息 OTP 进行无密码登录、通过短信 OTP 进行无密码登录以及使用用户名密码登录。您的应用程序可以提示用户选择其中一种方式，也可以根据内部逻辑自动做出选择。然后，它继续执行选择挑战的[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)或[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)请求。假设用户希望使用电子邮件消息一次性密码完成无密码身份验证。

```
{
   "ChallengeName": "SELECT_CHALLENGE",
   "ChallengeResponses": { 
      "USERNAME" : "testuser",
      "ANSWER" : "EMAIL_OTP" 
   },
   "ClientId": "1example23456789",
   "Session": "[Session ID from the previous response]"
}
```

Amazon Cognito 会返回一个 `EMAIL_OTP` 质询，并向该用户已验证的电子邮件地址发送一个验证码。随后，您的应用程序必须再次对该质询作出响应。

如果您之前请求了 `EMAIL_OTP` 作为 `PREFERRED_CHALLENGE`，那么这同样会是接下来的质询响应步骤。

```
{
   "ChallengeName": "EMAIL_OTP",
   "ChallengeResponses": {
      "USERNAME" : "testuser", 
      "EMAIL_OTP_CODE" : "123456" 
   },
   "ClientId": "1example23456789",
   "Session": "[Session ID from the previous response]"
}
```

------

## 使用密钥进行无密码登录 WebAuthn
<a name="amazon-cognito-user-pools-authentication-flow-methods-passkey"></a>

通行密钥是安全的，对用户施加的工作量相对较低。通行密钥登录利用*身份验证器*，即用户可用于身份验证的外部设备。常规密码容易使用户面临钓鱼攻击、密码猜测和凭证盗用等漏洞。而使用通行密钥，您的应用程序可以利用手机及其他与信息系统连接或内置的设备中的高级安全措施。常见的通行密钥登录工作流通常始于向您的设备发起一次调用，以触发您的密码或*凭证* 管理器，例如 iOS 钥匙串或 Google Chrome 密码管理器。设备上的凭证管理器会提示用户选择一个通行密钥，并通过已有的凭据或设备解锁机制进行授权。现代手机配备了人脸识别、指纹识别、解锁图案等机制，其中一些机制可同时满足强身份验证中的*所知因素* 和*所有因素* 原则。在使用生物识别进行通行密钥身份验证的情况下，通行密钥还体现了*所是因素*.这一身份验证因素。

您可能希望用指纹、面部识别或安全密钥身份验证来替代密码。这是*密钥*或*WebAuthn*身份验证。应用程序开发人员通常允许用户在首次使用密码登录后注册生物识别设备。通过 Amazon Cognito 用户池，您的应用程序可以为用户配置此登录选项。当您的用户池设置为时，密钥身份验证可以满足多因素身份验证 (MFA) 要求。`FactorConfiguration` `MULTI_FACTOR_WITH_USER_VERIFICATION`在此配置中，带有用户验证的密钥身份验证算作多因素身份验证。

一次性密码 (OTP) 身份验证流程与用户池中必需的多因素身份验证 (MFA) 不兼容。当您设置为时，带有用户验证的密钥身份验证可以满足 MFA 要求。`FactorConfiguration` `MULTI_FACTOR_WITH_USER_VERIFICATION`如果 MFA 在您的用户池中是可选的，则激活 MFA 的用户将无法使用 OTP 第一因素登录。在 MFA 为可选的用户池中，没有 MFA 偏好的用户可以使用无密码身份验证因素进行登录。有关更多信息，请参阅 [有关用户池 MFA 的需知信息](user-pool-settings-mfa.md#user-pool-settings-mfa-prerequisites)。

### 通行密钥是什么？
<a name="amazon-cognito-user-pools-authentication-flow-methods-passkey-what-are"></a>

Passkeys 无需记住复杂的密码或输入 OTPs，从而简化了用户体验。Passkeys 基于[万维网联盟](https://www.w3.org/TR/webauthn-3/) (W3C) WebAuthn 和 FIDO（Fast Identity Online）联盟起草的 CTAP2 标准。*浏览器和平台实施这些标准，提供 APIs 网络或移动应用程序以启动密钥注册或身份验证过程，还提供用户界面供用户选择密钥身份验证器并与之交互。*

当用户在网站或应用程序中注册身份验证器时，身份验证器会创建公私密钥对。 WebAuthn 浏览器和平台将公钥提交给网站或应用程序的应用程序后端。身份验证器保留有关用户和应用程序的私钥 IDs、密钥和元数据。当用户希望使用已注册的身份验证器在注册的应用程序中进行身份验证时，该应用程序会生成一个随机质询。对该质询的响应是由身份验证器使用其为该用户和应用程序所保存的私有密钥生成的质询数字签名，并附带相关元数据。浏览器或应用程序平台接收到该数字签名后，会将其传递给应用程序后端。然后，应用程序使用之前存储的公有密钥来验证该签名。

**注意**  
您的应用程序不会收到用户向其身份验证器提供的任何身份验证密钥，也不会获得有关私有密钥的任何信息。

以下是一些当前市场上身份验证器的示例及其功能。某个身份验证器可能符合其中任意一类或多类。
+ 某些身份验证器在授予访问权限前会执行*用户验证*，使用的因素包括 PIN、面部或指纹等生物识别输入或密码，以确保只有合法用户才能授权操作。另一些身份验证器则不具备任何用户验证功能，还有一些在应用程序未要求时可以跳过用户验证。
+ 某些身份验证器（例如 YubiKey 硬件令牌）是便携式的。它们可通过 USB、蓝牙或 NFC 连接与设备通信。有些身份验证器则属于本地身份验证器，并与特定平台绑定，例如 PC 上的 Windows Hello 或 iPhone 上的 Face ID。如果设备足够小巧（如移动设备），设备绑定的身份验证器可由用户随身携带。有时，用户还能通过无线通信方式将硬件身份验证器连接到多个不同平台。例如，在桌面浏览器中，用户扫描一个二维码后，即可使用自己的智能手机作为通行密钥身份验证器。
+ 一些平台绑定的通行密钥会同步到云端，从而支持用户在多个设备上使用。例如，iPhone 上的 Face ID 通行密钥会将通行密钥元数据通过用户的 Apple 账户同步至 iCloud 钥匙串。这类通行密钥可在 Apple 设备之间实现无缝身份验证，不需要用户为每台设备单独注册。1Password、Dashlane 和 Bitwarden 等基于软件的身份验证器应用程序，也会在用户安装了该应用程序的所有平台上同步通行密钥。

 WebAuthn 用术语来说，网站和应用程序是*依赖方*。每个通行密钥都与一个特定的依赖方 ID 关联，依赖方 ID 是一个统一标识符，代表接受该通行密钥进行身份验证的网站或应用程序。开发人员必须谨慎选择其依赖方 ID，以确保身份验证的范围恰当。典型的依赖方 ID 是 Web 服务器的根域名。使用该依赖方 ID 规范的通行密钥可用于该域及其所有子域的身份验证。当用户尝试访问的网站 URL 与依赖方 ID 不匹配时，浏览器和平台会拒绝通行密钥身份验证。类似地，对于移动应用程序，只有当应用程序路径出现在由该应用程序在依赖方 ID 所指定的路径下公开提供的 `.well-known` 关联文件中时，通行密钥才能被使用。

通行密钥具有*可发现性*。浏览器或平台可以自动识别并使用它们，无需用户手动输入用户名。当用户访问支持通行密钥身份验证的网站或应用程序时，可以从浏览器或平台已知的通行密钥列表中进行选择，也可以扫描二维码。

### Amazon Cognito 如何实现通行密钥身份验证？
<a name="amazon-cognito-user-pools-authentication-flow-methods-passkey-cognito"></a>

通行密钥是一项可选功能，在除**精简版**外的所有[功能计划](cognito-sign-in-feature-plans.md)中均可用。它仅支持[基于选择的身份验证流程](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)。使用[托管登录](authentication-flows-selection-managedlogin.md)时，Amazon Cognito 会处理通行密钥身份验证的逻辑。您还可以使用中的 [Amazon Cognito 用户池 API 在 AWS SDKs](#amazon-cognito-user-pools-authentication-flow-methods)应用程序后端进行密钥身份验证。

Amazon Cognito 可以识别使用两种非对称加密算法 (-7) 和 ES256 (-257) 中的任何一种创建的密钥。 RS256大多数身份验证器都支持这两种算法。默认情况下，用户可以设置任意类型的身份验证器，例如硬件令牌、移动智能手机或软件身份验证器应用程序。Amazon Cognito 目前不支持[证明](https://csrc.nist.gov/glossary/term/attestation)强制执行。

在用户池中，您可以将用户验证配置为首选或必需。在未提供值的 API 请求中，该选项默认选择首选，而在 Amazon Cognito 控制台中，该选项也默认选择首选。当您将用户验证设置为首选时，用户可以设置不具备用户验证功能的身份验证器，且注册和身份验证操作可在不执行用户验证的情况下成功完成。要强制在通行密钥注册和身份验证过程中进行用户验证，请将此设置更改为必需。

您在通行密钥配置中设置的依赖方（RP）ID 是一项关键决策。如果您未另行指定，且您的[域品牌版本](managed-login-branding.md)使用的是托管登录，则用户池默认会将您的[自定义域](cognito-user-pools-add-custom-domain.md)作为预期的 RP ID。如果您没有配置自定义域，也未另行指定 RP ID，则用户池默认使用您的[前缀域](cognito-user-pools-assign-domain-prefix.md)作为 RP ID。您也可以将 RP ID 配置为任意一个不在公共后缀列表（PSL）中的域名。您的 RP ID 条目适用于托管登录和 SDK 身份验证中的通行密钥注册与身份验证。在移动应用程序中，通行密钥仅在 Amazon Cognito 能够在以您的 RP ID 为域的路径下找到 `.well-known` 关联文件时才能正常工作。作为最佳实践，请在您的网站或应用程序公开上线前，确定并设置好依赖方 ID 的值。如果您更改了 RP ID，用户必须使用新的 RP ID 重新注册。

每个用户最多可以注册 20 个通行密钥。用户必须至少成功登录过您的用户池一次后，才能注册通行密钥。托管登录能大幅简化通行密钥的注册流程。当您为用户池和应用程序客户端启用通行密钥身份验证后，使用托管登录域的用户池会在最终用户注册新用户账户后，自动提示其注册通行密钥。您也可以在任意时间引导用户的浏览器跳转至托管登录页面，以完成通行密钥注册。用户必须先提供用户名，Amazon Cognito 才能启动通行密钥身份验证。托管登录会自动处理这一过程。登录页面会先提示用户输入用户名，验证该用户是否已注册至少一个通行密钥，然后提示其使用通行密钥登录。同样地，在基于 SDK 的应用程序中，也必须先提示用户输入用户名，并在身份验证请求中提供该用户名。

当您为用户池配置通行密钥身份验证，并且同时拥有自定义域和前缀域时，RP ID 默认会使用您自定义域的完全限定域名（FQDN）。要在 Amazon Cognito 控制台中将前缀域设置为 RP ID，请删除您的自定义域，或将前缀域的 FQDN 作为**第三方域**手动输入。

------
#### [ Activate passkey sign-in ]

**控制台**  
要激活通行密钥登录，请先配置您的用户池，以允许使用一种或多种无密码类型作为主要登录方式，然后配置您的应用程序客户端以允许 `USER_AUTH` 身份验证流程。在 Amazon Cognito 控制台中，导航到用户池配置中**身份验证**下的**登录**菜单。编辑**基于选择的登录选项**，然后将**通行密钥**添加到**可用选项**列表中。

导航到**身份验证方法**菜单并编辑**通行密钥**。
+ **用户验证**是一项设置，用于控制您的用户池是否要求通行密钥设备执行额外的检查，以确认当前用户有权使用通行密钥。要鼓励用户配置设备以支持用户验证，但不强制要求，请选择**首选**。要仅支持具备用户验证功能的设备，请选择**必需**。有关更多信息，请参阅 w3.org 上的[用户验证](https://www.w3.org/TR/webauthn-2/#user-verification)。
+ **依赖方 ID 的域**是应用程序将在用户的通行密钥注册请求中传递的标识符。它设定了与用户通行密钥颁发者的信任关系的目标。您的依赖方 ID 可以是：您的用户池的域，前提是   
**Cognito 域名**  
您的用户池中的 Amazon Cognito [前缀域](cognito-user-pools-assign-domain-prefix.md)。  
**自定义域**  
您的用户池的[自定义域](cognito-user-pools-add-custom-domain.md)。  
**第三方域**  
指用于不使用用户池托管登录页面的应用程序的域。此设置通常与没有[域](cognito-user-pools-assign-domain.md)的用户池相关联，这些用户池在后端使用 S AWS DK 和用户池 API 进行身份验证。

导航到**应用程序客户端**菜单，然后选择一个应用程序客户端或新建一个。选择**编辑**，在**身份验证流程**下，选择**登录时选择身份验证类型：ALLOW\$1USER\$1AUTH**。

**API/SDK**  
在用户池 API 中，`SignInPolicy`使用[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)请求中的相应密钥选项进行配置。通行密钥身份验证的 `WEB_AUTHN` 选项必须至少附带一个其他选项。通行密钥注册需要现有的身份验证会话。

```
"SignInPolicy": { 
    "AllowedFirstAuthFactors": [ 
        "PASSWORD",
        "WEB_AUTHN"
    ]
}
```

在[SetUserPoolMfaConfig](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserPoolMfaConfig.html#CognitoUserPools-SetUserPoolMfaConfig-request-WebAuthnConfiguration)请求的`WebAuthnConfiguration`参数中配置您的用户验证首选项和 RP ID。其中，`RelyingPartyId`（即通行密钥身份验证结果的预期目标）可以是您的用户池前缀域、自定义域，或您自行指定的其他域。

```
"WebAuthnConfiguration": { 
   "RelyingPartyId": "example.auth.us-east-1.amazoncognito.com",
   "UserVerification": "preferred",
   "FactorConfiguration": "SINGLE_FACTOR"
}
```

使用[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)或[UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)请求中的必填选项配置您的应用程序客户端`ExplicitAuthFlows`。

```
"ExplicitAuthFlows": [ 
   "ALLOW_USER_AUTH"
]
```

------
#### [ Register a passkey (managed login) ]

托管登录负责处理用户通行密钥的注册。当您的用户池启用了通行密钥身份验证后，Amazon Cognito 会在用户注册新账户时提示其设置通行密钥。

当用户已完成注册但尚未设置通行密钥，或您作为管理员为其创建了账户时，Amazon Cognito 不会提示用户设置通行密钥。处于这种状态的用户必须先使用其他身份验证因素（例如密码或无密码 OTP）成功登录，才能注册通行密钥。

**注册通行密钥**

1. 将用户引导至您的[登录页面](authorization-endpoint.md)。

   ```
   https://auth.example.com/oauth2/authorize/?client_id=1example23456789&response_type=code&scope=email+openid+phone&redirect_uri=https%3A%2F%2Fwww.example.com
   ```

1. 处理用户的身份验证结果。在此示例中，Amazon Cognito 会将用户重定向到 `www.example.com`，并附带一个应用程序可用来换取令牌的授权码。

1. 将用户引导至您的注册通行密钥页面。用户浏览器中有一个 Cookie，用于维持其已登录会话。该通行密钥页面的 URL 需包含 `client_id` 和 `redirect_uri` 参数。Amazon Cognito 仅允许已通过身份验证的用户访问此页面。请先使用密码、电子邮件 OTP 或短信 OTP 让用户完成登录，然后调用符合以下模式的 URL。

   您还可以在此请求中添加其他[对端点授权](authorization-endpoint.md)参数，例如 `response_type` 和 `scope`。

   ```
   https://auth.example.com/passkeys/add?client_id=1example23456789&redirect_uri=https%3A%2F%2Fwww.example.com
   ```

------
#### [ Register a passkey (SDK) ]

您可以在[PublicKeyCreationOptions](https://www.w3.org/TR/webauthn-3/#dictdef-publickeycredentialcreationoptions)对象中使用元数据注册密钥凭证。您可以使用已登录用户的凭证生成该对象，并将其以 API 请求的形式提交给用户的通行密钥颁发者。颁发者将返回一个确认密钥注册的 [RegistrationResponseJSON](https://www.w3.org/TR/webauthn-3/#dictdef-registrationresponsejson) 对象。

要开始通行密钥注册过程，请使用现有登录选项登录用户。使用当前用户的访问[令牌授权[StartWebAuthnRegistration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_StartWebAuthnRegistration.html)](authentication-flows-public-server-side.md#user-pool-apis-auth-unauth-token-auth)的 API 请求进行授权。以下是一个示例 `GetWebAuthnRegistrationOptions` 请求的正文。

```
{
   "AccessToken": "eyJra456defEXAMPLE"
}
```

您的用户池返回的响应中包含 `PublicKeyCreationOptions` 对象。请将该对象以 API 请求的方式发送给用户的颁发者。此对象提供公有密钥和依赖方 ID 等信息。颁发者随后将返回一个 `RegistrationResponseJSON` 对象。

在 [CompleteWebAuthnRegistration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CompleteWebAuthnRegistration.html)API 请求中显示注册响应，再次使用用户的访问令牌进行授权。当您的用户池返回一个 HTTP 200 响应且正文为空时，即表示该用户的通行密钥已注册。

------
#### [ Sign in with a passkey ]

无密码登录没有你可以在和`AuthFlow`中指定的密码。[InitiateAuth[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)相反，您必须声明 `AuthFlow` 为 `USER_AUTH`，然后请求一个登录选项，或根据用户池返回的响应选择您的无密码登录方式。要将用户登录到应用程序，请按如下方式配置 `InitiateAuth` 或 `AdminInitiateAuth` 请求的正文。以下参数集合是登录所需的最低要求。此外还支持其他参数。

在此示例中，我们知道用户希望使用通行密钥登录，因此我们添加了一个 `PREFERRED_CHALLENGE` 参数。

```
{
   "AuthFlow": "USER_AUTH",
   "AuthParameters": { 
      "USERNAME" : "testuser",
      "PREFERRED_CHALLENGE" : "WEB_AUTHN"
   },
   "ClientId": "1example23456789"
}
```

Amazon Cognito 以 `WEB_AUTHN` 质询进行响应。您的应用程序必须对该质询作出响应。向用户的通行密钥提供商发起一个登录请求。它将返回一个 [AuthenticationResponseJSON](https://www.w3.org/TR/webauthn-3/#dictdef-authenticationresponsejson) 对象。

```
{
   "ChallengeName": "WEB_AUTHN",
   "ChallengeResponses": {
      "USERNAME" : "testuser", 
      "CREDENTIAL" : "{AuthenticationResponseJSON}" 
   },
   "ClientId": "1example23456789",
   "Session": "[Session ID from the previous response]"
}
```

------

## 登录后进行 MFA
<a name="amazon-cognito-user-pools-authentication-flow-methods-mfa"></a>

您可以设置用户在通过用户名密码流程完成登录后，被提示进行额外的验证，例如通过电子邮件消息、短信或验证码生成应用程序提供的一次性密码。MFA 不同于使用一次性密码的无密码登录。但是，当您在用户池中`FactorConfiguration`配置`MULTI_FACTOR_WITH_USER_VERIFICATION`为时，带有用户验证功能的密钥可以满足 MFA 要求。`WebAuthnConfiguration`对于基于密码的流程，用户池中的 MFA 是一种质询-响应模型，在这种模型中，用户首先证明自己知道密码，然后证明他们有权访问注册的第二要素设备。

**实现资源**
+ [向用户池添加 MFA](user-pool-settings-mfa.md)

## 刷新令牌
<a name="amazon-cognito-user-pools-authentication-flow-methods-refresh"></a>

当您希望用户在无需重新输入凭证的情况下保持登录状态时，*刷新令牌* 是您的应用程序可用于持久化用户会话的工具。应用程序可以向您的用户池提供刷新令牌，并将其兑换为新的 ID 令牌和访问令牌。通过令牌刷新，您可以在无需用户干预的情况下，确保已登录用户仍处于活跃状态、获取更新后的属性信息，并更新访问控制权限。

**实现资源**
+ [刷新令牌](amazon-cognito-user-pools-using-the-refresh-token.md)

## 自定义身份验证
<a name="amazon-cognito-user-pools-authentication-flow-methods-custom"></a>

您可能希望为用户配置一种此处未列出的身份验证方法。您可以使用带有 Lambda 触发器的*自定义身份验证* 来实现这一点。在一系列 Lambda 函数中，Amazon Cognito 会发出一个质询，向用户提出一个用户必须回答的问题，验证回答的准确性，并确定是否应发出另一个质询。这些问题和回答可以包括安全问题、对 CAPTCHA 服务的请求、对外部 MFA 服务 API 的请求，或按顺序组合使用以上所有方式。

**实现资源**
+ [自定义身份验证质询 Lambda 触发器](user-pool-lambda-challenge.md)

### 自定义身份验证流程
<a name="amazon-cognito-user-pools-custom-authentication-flow"></a>

Amazon Cognito 用户池实现了使用自定义身份验证流程，这可以帮助您使用 AWS Lambda 触发器创建基于质询/响应的身份验证模型。

自定义身份验证流程可以自定义质询和响应周期，以满足不同需求。该流程首先调用 `InitiateAuth` API 操作，该调用指示将使用的身份验证类型并提供了所有初始身份验证参数。Amazon Cognito 将使用以下类型的信息之一响应 `InitiateAuth` 调用：
+ 用户质询及会话和参数。
+ 错误（如果用户未能通过身份验证）
+ ID、访问和刷新令牌（如果 `InitiateAuth` 调用中提供的参数足以使用户登录）。（通常，用户或应用程序必须首先应答质询，但这必须由您的自定义代码决定。）

 如果 Amazon Cognito 使用质询响应 `InitiateAuth` 调用，则应用程序将收集更多输入并调用 `RespondToAuthChallenge` 操作。此调用提供质询响应并将其传回会话。Amazon Cognito 对 `RespondToAuthChallenge` 的响应类似于对 `InitiateAuth` 调用的响应。如果用户已登录，Amazon Cognito 会提供令牌，如果用户未登录，则 Amazon Cognito 会提供另一个质询或错误。如果 Amazon Cognito 返回另一质询，则序列重复，应用程序调用 `RespondToAuthChallenge` 直到用户成功登录或返回错误。有关 `InitiateAuth` 和 `RespondToAuthChallenge` API 操作的详细信息，请参阅 [API 文档](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html)。

### 自定义身份验证流程和质询
<a name="Custom-authentication-flow-and-challenges"></a>

应用程序可以启动自定义身份验证流程，具体方法是：调用 `InitiateAuth` 并将 `CUSTOM_AUTH` 用作 `Authflow`。借助自定义身份验证流程，三个 Lambda 触发器控制响应的质询和验证。
+ `DefineAuthChallenge` Lambda 触发器将以前的质询和响应的会话数组作为输入。然后，它生成下一个质询名称和布尔值，指示用户是否通过身份验证并且应被授予令牌。此 Lambda 触发器是一个状态机，可通过质询控制用户的路径。
+ `CreateAuthChallenge` Lambda 触发器将质询名称作为输入并生成质询和参数以评估响应。当 `DefineAuthChallenge` 返回 `CUSTOM_CHALLENGE` 作为下一次质询时，身份验证流程调用 `CreateAuthChallenge`。`CreateAuthChallenge` Lambda 触发器在质询元数据参数中传递下一个类型的质询。
+ `VerifyAuthChallengeResponse` Lambda 函数会评估响应并返回布尔值以表明响应是否有效。

自定义身份验证流程还可以使用内置质询的组合，例如 SRP 密码验证和通过短信进行的 MFA。它可以使用自定义质询，如验证码或秘密问题。

### 在自定义身份验证流程中使用 SRP 密码验证
<a name="Using-SRP-password-verification-in-custom-authentication-flow"></a>

如果您希望将 SRP 包含在自定义身份验证流程中，则您必须开始使用 SRP。
+ 要在自定义流程中启动 SRP 密码验证，应用程序将 `CUSTOM_AUTH` 作为 `Authflow` 来调用 `InitiateAuth`。在 `AuthParameters` 映射 中，来自应用程序的请求包括 `SRP_A:`（SRP A 值）和 `CHALLENGE_NAME: SRP_A`。
+ `CUSTOM_AUTH` 流会使用 `challengeName: SRP_A` 和 `challengeResult: true` 的初始会话调用 `DefineAuthChallenge` Lambda 触发器。您的 Lambda 函数使用 `challengeName: PASSWORD_VERIFIER`、`issueTokens: false` 和 `failAuthentication: false` 作出响应。
+  接下来，该应用程序必须使用 `challengeName: PASSWORD_VERIFIER` 和 `challengeResponses` 映射中 SRP 所需的其它参数调用 `RespondToAuthChallenge`。
+ 如果 Amazon Cognito 验证了密码，`RespondToAuthChallenge` 使用 `challengeName: PASSWORD_VERIFIER` 和 `challengeResult: true` 的第二个会话调用 `DefineAuthChallenge` Lambda 触发器。此时，`DefineAuthChallenge` Lambda 触发器可以使用 `challengeName: CUSTOM_CHALLENGE` 响应来开启自定义质询。
+ 如果为用户启用了 MFA，则在 Amazon Cognito 验证密码后，您的用户将被要求设置 MFA 或使用 MFA 登录。

**注意**  
Amazon Cognito 托管的登录网页无法激活 [自定义身份验证质询 Lambda 触发器](user-pool-lambda-challenge.md)。

有关 Lambda 触发器的更多信息，包括示例代码，请参阅[使用 Lambda 触发器自定义用户池工作流](cognito-user-pools-working-with-lambda-triggers.md)。

## 用户迁移身份验证流程
<a name="amazon-cognito-user-pools-user-migration-authentication-flow"></a>

用户迁移 Lambda 触发器可帮助您将用户从旧式用户管理系统迁移到您的用户池。如果选择 `USER_PASSWORD_AUTH` 身份验证流程，则用户在用户迁移过程中无需重置密码。此流程在身份验证期间通过加密的 SSL 连接向服务发送用户的密码。

所有用户均完成迁移后，请切换为更安全的 SRP 流程。SRP 流程不通过网络发送任何密码。

要了解有关 Lambda 触发器的更多信息，请参阅[使用 Lambda 触发器自定义用户池工作流](cognito-user-pools-working-with-lambda-triggers.md)。

有关使用 Lambda 触发器迁移用户的更多信息，请参阅[利用用户迁移 Lambda 触发器导入用户](cognito-user-pools-import-using-lambda.md)。

# API 和 SDK 身份验证的授权模型
<a name="authentication-flows-public-server-side"></a>

在开发支持用户池身份验证的应用程序之初，您必须根据您的应用程序类型选择合适的 API 授权模型。授权模型是一个用于对 Amazon Cognito 用户池 API 及 SDK 集成中的身份验证组件进行请求授权的系统。Amazon Cognito 提供三种授权模型：IAM 授权、公共访问和令牌授权。

在 IAM 授权的请求中，授权来自请求的 `Authorization` 标头中由一组 AWS IAM 凭证生成的签名。对于服务器端应用程序，这种做法通过 IAM 授权来保护身份验证操作。而在公共（未经身份验证的）身份验证请求中，则无需任何授权。这种方式适用于分发给用户的客户端应用程序。令牌授权的操作通常与公共操作结合使用，授权来自于请求的 `Authorization` 标头中包含的会话令牌或访问令牌。Amazon Cognito 身份验证通常要求您按顺序实现两个或更多 API 操作，而具体使用哪些 API 操作则取决于您的应用程序特性。公共客户端（应用程序分发给用户时使用）采用的是公共操作，也就是说，用户发起登录请求时，不需要获得授权。令牌授权操作用于在公共应用程序中延续用户的会话。而服务器端客户端（其中，应用程序逻辑托管在远程系统上）则通过对登录请求的 IAM 授权来保护身份验证操作。以下 API 操作组合及其对应的 SDK 方法，分别对应可用的多种授权模型。

每个公共身份验证操作都有某种形式的服务器端等效操作，例如[UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html)和。[AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)客户端操作由用户发起，通常需要用户确认，而服务器端操作则假定更改是由用户池管理员提交的，因此更改会立即生效。在此示例中，Amazon Cognito 向用户发送了一条包含确认码的消息，用户的访问令牌授权了提交验证码的[VerifyUserAttribute](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifyUserAttribute.html)请求。而服务器端应用程序则可以立即设置任意属性的值，但在更改用于登录的电子邮件地址或电话号码时，[需遵循特殊规则](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html#CognitoUserPools-AdminUpdateUserAttributes-request-UserAttributes)。

要比较 API 身份验证并查看 API 操作及其授权模型的完整列表，请参阅[了解 API、OIDC 和托管登录页面身份验证](#user-pools-API-operations)。

------
#### [ Client-side (public) authentication ]

以下是一个客户端应用程序中典型的请求序列

1. 公共[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)操作会提交主要证书，例如用户名和密码。

1. 令牌授权的[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)操作从`InitiateAuth`响应和质询的答案中提交*会话*令牌，例如 MFA。会话令牌授权表示属于 not-yet-complete身份验证周期一部分的请求。

1. 令牌授权[ConfirmDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmDevice.html)操作提交*访问*令牌并执行写入操作，将记住的设备添加到用户的个人资料中。访问令牌授权用于标识那些用户在完成身份验证后发起的自助操作请求。

有关更多信息，请参阅[客户端身份验证选项](#amazon-cognito-user-pools-client-side-authentication-flow)和[了解 API、OIDC 和托管登录页面身份验证](#user-pools-API-operations)。

------
#### [ Server-side authentication ]

以下是一个服务器端操作中典型的请求序列。每个请求都包含一个 [AWS 签名版本 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) 授权标头，该标头使用颁发给应用程序服务器的 IAM 机器凭证进行签名。

1. 该[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)操作会提交主要凭证，例如用户名和密码。

1. [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)操作提交质疑的答案，例如 MFA。

1. 该[AdminUpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateDeviceStatus.html)操作将`AdminInitiateAuth`[响应](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html#API_AdminInitiateAuth_ResponseSyntax)中的设备密钥设置为已记住的。

有关更多信息，请参阅[服务器端身份验证选项](#amazon-cognito-user-pools-server-side-authentication-flow)和[了解 API、OIDC 和托管登录页面身份验证](#user-pools-API-operations)。

------

用户通过应答连续的质询进行身份验证，直到身份验证失败或 Amazon Cognito 向用户颁发令牌。您可以在包含不同质询的流程中对 Amazon Cognito 重复这些步骤，以支持任何自定义身份验证流程。

**Topics**
+ [服务器端身份验证选项](#amazon-cognito-user-pools-server-side-authentication-flow)
+ [客户端身份验证选项](#amazon-cognito-user-pools-client-side-authentication-flow)
+ [了解 API、OIDC 和托管登录页面身份验证](#user-pools-API-operations)
+ [按授权模型分组的 API 操作列表](#user-pool-apis-auth-unauth)

## 服务器端身份验证选项
<a name="amazon-cognito-user-pools-server-side-authentication-flow"></a>

Web 应用程序及其他*服务器端* 应用程序在远程服务器上实现身份验证，客户端通过浏览器或 SSH 会话等远程显示应用程序加载这些服务器。服务器端应用程序通常具有以下特征。
+ 它们是使用 Java、Ruby 或 Node.js 等语言开发并部署在服务器上的应用程序。
+ 它们连接到可能包含客户端密钥的用户池[应用程序客户端](user-pool-settings-client-apps.md)，这类客户端称为*机密客户端*。
+ 他们有权访问 AWS 证书。
+ 它们调用[托管登录](cognito-user-pools-managed-login.md)实现身份验证，或在用户池 API 中使用 AWS SDK 调用 IAM 授权的操作。
+ 它们主要面向内部用户，也可能面向公众客户提供服务。

通过用户池 API 执行的服务器端操作可以使用密码、一次性密码或通行密钥作为主要的登录因素。对于服务器端应用程序，用户池身份验证与客户端应用程序的身份验证类似，但以下情况除外：
+ 服务器端应用程序发出 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)API 请求。此操作需要具有包含`cognito-idp:AdminInitiateAuth`和权限的 AWS 证书`cognito-idp:AdminRespondToAuthChallenge`。该操作返回必需的质询或身份验证结果。
+ 当应用程序收到质询时，它会发出 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)API 请求。此 `AdminRespondToAuthChallenge` API 操作也需要 AWS 凭证。

有关使用 AWS 凭证签署 Amazon Cognito API 请求的更多信息，请参阅*AWS 一般*参考中的[签名版本 4 签名流程](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)。

在 `AdminInitiateAuth` 响应 `ChallengeParameters` 中，`USER_ID_FOR_SRP` 属性（如果存在）包含用户的实际用户名而不是别名（如电子邮件地址或电话号码）。在 `AdminRespondToAuthChallenge` 调用的 `ChallengeResponses` 中，您必须在 `USERNAME` 参数中传递此用户名。

**注意**  
由于后端管理员实施使用管理员身份验证流程，该流程不支持“记住的设备”功能。在您启用设备跟踪时，管理员身份验证成功，但任何对刷新访问令牌的调用均会失败。

## 客户端身份验证选项
<a name="amazon-cognito-user-pools-client-side-authentication-flow"></a>

移动应用程序及其他*客户端* 应用程序类型安装在用户的设备上，并在本地执行身份验证逻辑和用户界面的逻辑。它们通常具有以下特征。
+ 它们使用 React Native、Flutter 和 Swift 等语言开发，并部署到用户设备上。
+ 它们连接到不包含客户端密钥的用户池[应用程序客户端](user-pool-settings-client-apps.md)，这类客户端称为*公共客户端*。
+ 他们无法访问授权 IAM 授权的 API 请求的 AWS 证书。
+ 他们调用[托管登录](cognito-user-pools-managed-login.md)进行身份验证，或者使用 SDK 在用户池 API 中使用公开和令牌授权的操作。 AWS 
+ 它们面向公众客户，允许任何人注册和登录。

通过用户池 API 执行的客户端操作可以使用密码、一次性密码或通行密钥作为主要的登录因素。以下过程适用于您使用[AWS Amplify](https://docs.amplify.aws/javascript/start/getting-started/)或创建的用户客户端应用程序。[AWS SDKs](https://aws.amazon.com/developer/tools/)

1. 用户将他们的用户名和密码输入到应用程序中。

1. 应用程序使用用户的用户名和安全远程密码（SRP）详细信息调用 `InitiateAuth` 操作。

   此 API 操作返回身份验证参数。
**注意**  
该应用程序使用内置的 Amazon Cognito SRP 功能生成 SRP 详细信息。 AWS SDKs

1. 应用程序调用 `RespondToAuthChallenge` 操作。如果调用成功，则 Amazon Cognito 返回用户的令牌，并且身份验证流程完成。

   如果 Amazon Cognito 需要另一个质询，则对 `RespondToAuthChallenge` 的调用不返回任何令牌。相反，调用会返回一个会话。

1. 如果 `RespondToAuthChallenge` 返回一个会话，应用程序将再次调用 `RespondToAuthChallenge`，这次使用会话和质询响应（例如，MFA 代码）。

## 了解 API、OIDC 和托管登录页面身份验证
<a name="user-pools-API-operations"></a>

Amazon Cognito 用户池是多种身份验证技术的组合。他们是外部身份提供商 (IdPs) 的依赖方。它们 IdPs 适用于使用 OpenID Connect (OIDC) 实现身份验证的应用程序。 SDKs它们作为 JSON Web 令牌 (JWTs) 的发行者提供身份验证，类似于 OIDC 身份验证，但使用的是其中的一部分 API 方法。 AWS SDKs它们也可以作为您应用程序的安全入口点。

当您想要注册、登录和管理用户池中的用户时，有两种选择。

1. 您的*托管登录页面* 和经典*托管 UI* 包括[托管登录用户交互式端点](managed-login-endpoints.md)以及处理 IdP 和依赖方角色的[联合端点](federation-endpoints.md)。它们构成了一个公开网页包，当您为用户池[选择域](cognito-user-pools-assign-domain.md)时，Amazon Cognito 会激活这些网页。要快速开始使用 Amazon Cognito 用户池的身份验证和授权功能，包括注册、登录、密码管理和多重身份验证（MFA）页面，请使用托管登录的内置用户界面。

   其他用户池端点便于使用第三方身份提供商进行身份验证（IdPs）。他们执行的服务包括以下各项。

   1. 服务提供商回调终端节点，用于来自您的经过身份验证的声明 IdPs，比如`saml2/idpresponse`和。`oauth2/idpresponse`当 Amazon Cognito 是您的应用程序和 IdP 之间的中间服务提供者（SP）时，回调端点代表服务。

   1. 提供有关您的环境的信息的端点，例如 `oauth2/userInfo` 和 `/.well-known/jwks.json`。您的应用在使用 OIDC 或 2.0 开发者库验证令牌或检索用户个人资料数据时会使用这些端点。 OAuth 

1. [Amazon Cognito 用户池 API](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html) 是一组用于您的 Web 或移动应用程序的工具，用于在您自己的自定义前端中收集登录信息之后验证用户身份。用户池 API 身份验证生成以下 JSON Web 令牌。

   1. 带有来自您的用户的可验证属性声明的身份令牌。

   1. 一种访问令牌，用于授权用户针对 [AWS 服务端点](https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html)创建经令牌授权的 API 请求。
**注意**  
默认情况下，来自用户池 API 身份验证的访问令牌仅包含 `aws.cognito.signin.user.admin` 作用域。要生成具有额外作用域的访问令牌（例如，授权对第三方 API 的请求），请在通过用户池端点进行身份验证期间请求作用域，或者在 [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md) 中添加自定义作用域。自定义访问令牌会增加您的 AWS 账单费用。

   1. 一种刷新令牌，用于授权请求新 ID 令牌和访问令牌，并刷新用户身份和访问控制属性。

您可以将通常通过用户池端点登录的联合用户与其配置文件位于用户池*本地* 的用户相关联。本地用户仅存在于您的用户池目录中，无需通过外部 IdP 进行联合身份验证。如果您在 [AdminLinkProviderForUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html)API 请求中将他们的联合身份关联到本地用户，则他们可以使用用户池 API 登录。有关更多信息，请参阅 [将联合用户与现有用户配置文件关联](cognito-user-pools-identity-federation-consolidate-users.md)。

Amazon Cognito 用户池 API 有双重用途。

1. 它创建和配置您的 Amazon Cognito 用户池资源。例如，您可以创建用户池、添加 AWS Lambda 触发器以及配置托管您的托管登录页面的用户池域。

1. 它还为本地用户和关联的用户执行注册、登录和其他用户操作。

**使用 Amazon Cognito 用户池 API 的示例场景**

1. 用户选择了您在应用程序中创建的“创建账户”按钮。他们输入电子邮件地址和密码。

1. 您的应用程序发送 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)API 请求并在您的用户池中创建了一个新用户。

1. 应用程序提示用户输入电子邮件确认码。用户输入他们在电子邮件中收到的代码。

1. 您的应用会发送包含用户确认码的 [ConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html)API 请求。

1. 应用程序提示您的用户输入用户名和密码，而用户输入其信息。

1. 您的应用程序发送 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 请求并存储 ID 令牌、访问令牌和刷新令牌。应用程序调用 OIDC 库来管理用户的令牌并为该用户维护持久会话。

在 Amazon Cognito 用户池 API 中，您无法登录通过 IdP 进行联合身份验证的用户。您必须通过用户池端点对这些用户进行身份验证。有关包含托管登录的用户池端点的更多信息，请参阅[用户池端点和托管登录参考](cognito-userpools-server-contract-reference.md)。

联合用户可以在托管登录中开始登录并选择其 IdP，您也可以跳过托管登录，将用户直接发送到您的 IdP 以进行登录。当您的 API 发送请求到 [对端点授权](authorization-endpoint.md) 且带有 IdP 参数时，Amazon Cognito 会以静默方式将用户重定向到 IdP 登录页面。

**托管登录页面的场景示例**

1. 用户选择了您在应用程序中创建的“创建账户”按钮。

1. 托管登录向用户提供您注册开发人员凭证使用的社交身份提供者列表。您的用户选择了 Apple。

1. 您的应用程序向 [对端点授权](authorization-endpoint.md) 发出请求，提供者名称为 `SignInWithApple`。

1. 用户的浏览器打开 Apple 身份验证页面。用户登录，并选择授权 Amazon Cognito 读取其个人资料信息。

1. Amazon Cognito 确认 Apple 访问令牌并查询用户的 Apple 个人资料。

1. 用户向您的应用程序出示 Amazon Cognito 授权码。

1. 应用程序中的 OIDC 库与 [令牌端点](token-endpoint.md) 交换授权码并存储用户池颁发的 ID 令牌、访问令牌和刷新令牌。应用程序使用 OIDC 库来管理用户的令牌并为该用户维护持久会话。

用户池 API 和托管登录页面支持多种应用场景，这些场景在本指南中均有说明。以下部分探讨了用户池 API 如何进一步划分为支持您的注册、登录和资源管理要求的类。

## 按授权模型分组的 API 操作列表
<a name="user-pool-apis-auth-unauth"></a>

Amazon Cognito 用户池 API 既是资源管理接口，也是面向用户的身份验证和授权接口，结合了其操作中遵循的授权模型。根据 API 操作，您可能需要使用 IAM 凭证、访问令牌、会话令牌、客户端密钥或者前面这些内容的组合提供授权。对于许多用户身份验证和授权操作，您可以选择请求的经过身份验证和未经身份验证的版本。对于分发给用户的应用程序（例如移动应用程序），最佳安全实践是提供未经身份验证的操作；您无需在代码中包含任何密钥。

您只能在 IAM policy 中为 [IAM 授权的管理操作](#user-pool-apis-auth-unauth-sigv4-management) 和 [IAM 授权的用户操作](#user-pool-apis-auth-unauth-sigv4-user) 分配权限。

### IAM 授权的管理操作
<a name="user-pool-apis-auth-unauth-sigv4-management"></a>

IAM 授权的管理操作会修改和查看您的用户池和应用程序客户端配置，就像您在 AWS 管理控制台中所做的那样。

例如，要在 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求中修改您的用户池，您必须出示 AWS 证书和 IAM 权限才能更新资源。

要在 AWS Command Line Interface (AWS CLI) 或 AWS 软件开发工具包中授权这些请求，请使用环境变量或向请求添加 IAM 证书的客户端配置来配置您的环境。有关更多信息，请参阅中的[AWS 使用您的 AWS 凭证进行访问*AWS 一般参考*](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys)。对于 Amazon Cognito 用户池 API，您也可以直接向[服务端点](https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html)发送请求。您必须使用在请求*标题中嵌入的 AWS 凭据对这些请求进行授权或签名*。有关更多信息，请参阅[签署 AWS API 请求](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)。


| IAM 授权的管理操作 | 
| --- |
| [AddCustomAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AddCustomAttributes.html) | 
| [CreateGroup](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateGroup.html) | 
| [CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html) | 
| [CreateResourceServer](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateResourceServer.html) | 
| [CreateUserImportJob](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserImportJob.html) | 
| [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html) | 
| [CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html) | 
| [CreateUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolDomain.html) | 
| [DeleteGroup](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteGroup.html) | 
| [DeleteIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteIdentityProvider.html) | 
| [DeleteResourceServer](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteResourceServer.html) | 
| [DeleteUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUserPool.html) | 
| [DeleteUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUserPoolClient.html) | 
| [DeleteUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUserPoolDomain.html) | 
| [DescribeIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeIdentityProvider.html) | 
| [DescribeResourceServer](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeResourceServer.html) | 
| [DescribeRiskConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeRiskConfiguration.html) | 
| [DescribeUserImportJob](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserImportJob.html) | 
| [DescribeUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPool.html) | 
| [DescribeUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPoolClient.html) | 
| [DescribeUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPoolDomain.html) | 
| [获取 CSVHeader](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetCSVHeader.html) | 
| [GetGroup](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetGroup.html) | 
| [GetIdentityProviderByIdentifier](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetIdentityProviderByIdentifier.html) | 
| [GetSigningCertificate](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetSigningCertificate.html) | 
| [获取 UICustomization](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUICustomization.html) | 
| [GetUserPoolMfaConfig](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserPoolMfaConfig.html) | 
| [ListGroups](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListGroups.html) | 
| [ListIdentityProviders](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListIdentityProviders.html) | 
| [ListResourceServers](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListResourceServers.html) | 
| [ListTagsForResource](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListTagsForResource.html) | 
| [ListUserImportJobs](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUserImportJobs.html) | 
| [ListUserPoolClients](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUserPoolClients.html) | 
| [ListUserPools](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUserPools.html) | 
| [ListUsers](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html) | 
| [ListUsersInGroup](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsersInGroup.html) | 
| [SetRiskConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetRiskConfiguration.html) | 
| [Set UICustomization](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUICustomization.html) | 
| [SetUserPoolMfaConfig](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserPoolMfaConfig.html) | 
| [StartUserImportJob](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_StartUserImportJob.html) | 
| [StopUserImportJob](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_StopUserImportJob.html) | 
| [TagResource](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_TagResource.html) | 
| [UntagResource](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UntagResource.html) | 
| [UpdateGroup](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateGroup.html) | 
| [UpdateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html) | 
| [UpdateResourceServer](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateResourceServer.html) | 
| [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html) | 
| [UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html) | 
| [UpdateUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolDomain.html) | 

### IAM 授权的用户操作
<a name="user-pool-apis-auth-unauth-sigv4-user"></a>

IAM 授权的用户操作注册、登录、管理凭证、修改和查看您的用户。

例如，您可以有一个服务器端应用程序层，为 Web 前端提供支持。您的服务器端应用程序是您信任的 OAuth 机密客户端，可以访问您的 Amazon Cognito 资源。要在应用程序中注册用户，您的服务器可以在 [AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html)API 请求中包含 AWS 凭据。有关 OAuth 客户端类型的更多信息，请参阅 * OAuth 2.0 授权框架中的*[客户端类型](https://www.rfc-editor.org/rfc/rfc6749#section-2.1)。

要在 AWS CLI 或 AWS SDK 中授权这些请求，请使用环境变量或向请求添加 IAM 证书的客户端配置来配置服务器端应用程序环境。有关更多信息，请参阅中的[AWS 使用您的 AWS 凭证进行访问*AWS 一般参考*](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys)。对于 Amazon Cognito 用户池 API，您也可以直接向[服务端点](https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html)发送请求。您必须使用在请求*标题中嵌入的 AWS 凭据对这些请求进行授权或签名*。有关更多信息，请参阅[签署 AWS API 请求](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)。

如果您的应用程序客户端有客户端密钥，则您必须提供 IAM 凭证，并在 `AuthParameters` 中提供 `SecretHash` 参数或 `SECRET_HASH` 值（取决于操作）。有关更多信息，请参阅 [计算密钥哈希值](signing-up-users-in-your-app.md#cognito-user-pools-computing-secret-hash)。


| IAM 授权的用户操作 | 
| --- |
| [AdminAddUserToGroup](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminAddUserToGroup.html) | 
| [AdminConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminConfirmSignUp.html) | 
| [AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html) | 
| [AdminDeleteUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDeleteUser.html) | 
| [AdminDeleteUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDeleteUserAttributes.html) | 
| [AdminDisableProviderForUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDisableProviderForUser.html) | 
| [AdminDisableUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDisableUser.html) | 
| [AdminEnableUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminEnableUser.html) | 
| [AdminForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminForgetDevice.html) | 
| [AdminGetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminGetDevice.html) | 
| [AdminGetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminGetUser.html) | 
| [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) | 
| [AdminLinkProviderForUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html) | 
| [AdminListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminListDevices.html) | 
| [AdminListGroupsForUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminListGroupsForUser.html) | 
| [AdminListUserAuthEvents](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminListUserAuthEvents.html) | 
| [AdminRemoveUserFromGroup](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRemoveUserFromGroup.html) | 
| [AdminResetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminResetUserPassword.html) | 
| [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) | 
| [AdminSetUserMFAPreference](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserMFAPreference.html) | 
| [AdminSetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserPassword.html) | 
| [AdminSetUserSettings](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserSettings.html) | 
| [AdminUpdateAuthEventFeedback](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateAuthEventFeedback.html) | 
| [AdminUpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateDeviceStatus.html) | 
| [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html) | 
| [AdminUserGlobalSignOut](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUserGlobalSignOut.html) | 

### 未经身份验证的用户操作
<a name="user-pool-apis-auth-unauth-unauth"></a>

未经身份验证的用户操作注册、登录以及为您的用户启动密码重置。当您希望 Internet 上的任何人都可以注册并登录您的应用程序时，请使用未经身份验证（*公开*）的 API 操作。

例如，要在您的应用程序中注册用户，您可以分发一个不提供任何密钥特权访问权限的 OAuth 公共客户端。您可以使用未经身份验证的 API 操作[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)注册此用户。

要在使用 AWS SDK 开发的公共客户端中发送这些请求，您无需配置任何凭据。对于没有额外授权的 Amazon Cognito 用户池 API，您也可以直接向[服务端点](https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html)发送请求。

如果您的应用程序客户端有客户端密钥，则您必须在 `AuthParameters` 中提供 `SecretHash` 参数或 `SECRET_HASH` 值（取决于操作）。有关更多信息，请参阅 [计算密钥哈希值](signing-up-users-in-your-app.md#cognito-user-pools-computing-secret-hash)。


| 未经身份验证的用户操作 | 
| --- |
| [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html) | 
| [ConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html) | 
| [ResendConfirmationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html) | 
| [ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html) | 
| [ConfirmForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html) | 
| [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) | 

### 经过令牌授权的用户操作
<a name="user-pool-apis-auth-unauth-token-auth"></a>

经过令牌授权的用户操作在用户已登录或开始登录流程之后，注销、管理其凭证、修改和查看用户。如果您不想在应用程序中分发密钥，并且想要使用用户自己的凭证授权请求，请使用经过令牌授权的 API 操作。如果用户已完成登录，则您必须使用访问令牌来授权其经过令牌授权的 API 请求。如果您的用户正在登录流程中，则您必须使用 Amazon Cognito 在对先前请求的响应中返回的会话令牌，授权其经过令牌授权的 API 请求。

例如，在公共客户端中，您可能希望更新用户的配置文件，限制用户仅对自己的配置文件具有写入权限。要进行此更新，您的客户端可以在 [UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html)API 请求中包含用户的访问令牌。

要在使用 AWS SDK 开发的公共客户端中发送这些请求，您无需配置任何凭据。在您的请求中包含 `AccessToken` 或 `Session` 参数。对于 Amazon Cognito 用户池 API，您也可以直接向[服务端点](https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html)发送请求。要向服务端点授权请求，请在请求的 POST 正文中包含访问令牌或会话令牌。

要签署经过令牌授权的操作的 API 请求，请将访问令牌作为 `Authorization` 标头包含在请求中，格式为 `Bearer <Base64-encoded access token>`。


| 经过令牌授权的用户操作 | AccessToken | 会话 | 
| --- |--- |--- |
| [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) |  | ✓ | 
| [ChangePassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ChangePassword.html) | ✓ |  | 
| [GetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html) | ✓ |  | 
| [StartWebAuthnRegistration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_StartWebAuthnRegistration.html) | ✓ |  | 
| [CompleteWebAuthnRegistration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CompleteWebAuthnRegistration.html) | ✓ |  | 
| [DeleteWebAuthnCredential](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteWebAuthnCredential.html) | ✓ |  | 
| [ListWebAuthnCredentials](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListWebAuthnCredentials.html) | ✓ |  | 
| [UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html) | ✓ |  | 
| [DeleteUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUserAttributes.html) | ✓ |  | 
| [DeleteUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUser.html) | ✓ |  | 
| [ConfirmDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmDevice.html) | ✓ |  | 
| [ForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgetDevice.html) | ✓ |  | 
| [GetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetDevice.html) | ✓ |  | 
| [ListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListDevices.html) | ✓ |  | 
| [UpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateDeviceStatus.html) | ✓ |  | 
| [GetUserAttributeVerificationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAttributeVerificationCode.html) | ✓ |  | 
| [VerifyUserAttribute](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifyUserAttribute.html) | ✓ |  | 
| [SetUserSettings](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserSettings.html) | ✓ |  | 
| [SetUserMFAPreference](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserMFAPreference.html) | ✓ |  | 
| [GlobalSignOut](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html) | ✓ |  | 
| [UpdateAuthEventFeedback](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateAuthEventFeedback.html) |  | ✓ | 
| [AssociateSoftwareToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AssociateSoftwareToken.html) | ✓ | ✓ | 
| [VerifySoftwareToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifySoftwareToken.html) | ✓ | ✓ | 
| [RevokeToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html)¹ |  |  | 
| [GetTokensFromRefreshToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetTokensFromRefreshToken.html)¹ |  |  | 

¹ `RevokeToken` 和 `GetTokensFromRefreshToken` 将刷新令牌作为授权参数。刷新令牌用作授权令牌和目标资源。

# 使用第三方身份提供者进行用户池登录
<a name="cognito-user-pools-identity-federation"></a>

您的应用程序用户可以通过用户池直接登录，也可以通过第三方身份提供者（IdP）进行联合身份验证。用户池管理处理通过Facebook、谷歌、亚马逊和苹果进行社交登录以及从OpenID Connect（OIDC）和SAML返回的代币的开销。 IdPs借助内置的托管网络用户界面，Amazon Cognito 为所有经过身份验证的用户提供令牌处理和管理。 IdPs这样，后端系统可以基于一组用户池令牌实现标准化。

## 联合登录在 Amazon Cognito 用户池中的工作方式
<a name="cognito-user-pools-identity-federation-how-it-works"></a>

通过第三方（联合身份验证）进行登录可在 Amazon Cognito 用户池中实现。此功能不依赖于通过 Amazon Cognito 身份池（联合身份）实现的联合身份验证。

![\[社交登录的身份验证概述\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/scenario-authentication-cup.png)


Amazon Cognito 是一个用户目录和 OAuth 2.0 身份提供商 (IdP)。当您以*本地用户*身份登录 Amazon Cognito 目录时，您的用户池是应用程序的 IdP。本地用户仅存在于您的用户池目录中，无需通过外部 IdP 进行联合身份验证。

当你将 Amazon Cognito 连接到社交、SAML 或 OpenID Connect (OIDC IdPs) 时，你的用户池充当了多个服务提供商和你的应用程序之间的桥梁。对于您的 IdP 而言，Amazon Cognito 是服务提供商 (SP)。你将 OIDC ID 令牌或 SAML 声明 IdPs 传递给 Amazon Cognito。Amazon Cognito 会在令牌或断言中读取有关您用户的声明，并将这些声明映射到用户池目录中的新用户配置文件。

然后，Amazon Cognito 在其自己的目录中为联合用户创建用户配置文件。Amazon Cognito 根据来自 IdP 的声明向用户添加属性。对于 OIDC 和社交身份提供者，则向 IDP 运营的公有 `userinfo` 端点添加属性。当映射的 IdP 属性发生变化时，用户的属性会在用户池中发生变化。您还可以添加更多属性，这些属性独立于 IdP 中的属性。

Amazon Cognito 为联合用户创建配置文件后，它会更改其功能并将自己显示为应用程序的 IdP（现在是 SP）。Amazon Cognito 是 OIDC 和 2.0 IdP 的组合。 OAuth 它生成访问令牌、ID 令牌和刷新令牌。有关令牌的更多信息，请参阅[了解用户池 JSON 网络令牌 (JWTs)](amazon-cognito-user-pools-using-tokens-with-identity-providers.md)。

您必须设计一个与 Amazon Cognito 集成的应用程序，以便对用户进行身份验证和授权，无论是联合用户还是本地用户。

## 应用程序作为 Amazon Cognito 的服务提供者的责任
<a name="cognito-user-pools-identity-federation-how-it-works-app-responsibilities"></a><a name="cognito-user-pools-identity-federation-how-it-works-app-responsibilities"></a>

**验证和处理令牌中的信息**  
在大多数情况下，Amazon Cognito 将经过身份验证的用户重新导向到它附加了授权码的应用程序 URL。您的应用程序[将此代码交换](https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html)为访问权限、ID 和刷新令牌。然后，它必须[检查令牌的有效性](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html)，并根据令牌中的声明向用户提供信息。

**使用 Amazon Cognito API 请求响应身份验证事件**  
您的应用程序必须与 [Amazon Cognito 用户池 API](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html) 和[身份验证 API 端点](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html)集成。身份验证 API 会将用户进行登录和注销，并管理令牌。用户池 API 具有多种操作，用于管理您的用户池、用户以及身份验证环境的安全性。当应用程序收到来自 Amazon Cognito 的响应时，它必须知道下一步该怎么做。

## 关于 Amazon Cognito 用户池第三方登录需要了解的事项
<a name="cognito-user-pools-identity-federation-how-it-works-considerations"></a><a name="cognito-user-pools-identity-federation-how-it-works-considerations"></a>
+ 如果您希望用户使用联合提供商登录，则必须选择域。这将设置[托管登录](cognito-userpools-server-contract-reference.md)页面。有关更多信息，请参阅 [使用您自己的域进行托管登录](cognito-user-pools-add-custom-domain.md)。
+ 您无法使用[ InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)和之类的 API 操作登录联合用户[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)。联合用户只能使用[登录端点](login-endpoint.md)或[对端点授权](authorization-endpoint.md)进行登录。
+ [对端点授权](authorization-endpoint.md) 是*重定向*端点。如果您在请求中提供 `idp_identifier` 或 `identity_provider` 参数，它将绕过托管登录，以静默方式重定向到您的 IdP。否则，将重定向到托管登录[登录端点](login-endpoint.md)。
+ 当托管登录将会话重定向到联合 IdP 时，Amazon Cognito 会在请求中包含 `user-agent` 标头 `Amazon/Cognito`。
+ Amazon Cognito 从固定标识符和 IdP 名称的组合中派生联合用户配置文件的 `username` 属性。要生成符合自定义要求的用户名，请创建到 `preferred_username` 属性的映射。有关更多信息，请参阅 [有关映射的需知信息](cognito-user-pools-specifying-attribute-mapping.md#cognito-user-pools-specifying-attribute-mapping-requirements)。

  示例：`MyIDP_bob@example.com`
+ Amazon Cognito 会为您添加到[用户池中的每个 OIDC SAMl 和社交 IdP 创建一个用户组](cognito-user-pools-user-groups.md)。该组的名称采用 `[user pool ID]_[IdP name]` 格式，例如 `us-east-1_EXAMPLE_MYSSO` 或 `us-east-1_EXAMPLE_Google`。每个自动生成的唯一 IdP 用户配置文件都会自动添加到该组。[关联用户](cognito-user-pools-identity-federation-consolidate-users.md)不会自动添加到该组，但您可以通过另外的流程将其配置文件添加到该组。
+ Amazon Cognito 将有关联合用户身份的信息记录到属性中，并在 ID 令牌中记录一个称为 `identities` 的声明。此声明包含用户的提供商以及提供商提供的唯一 ID。您无法直接在用户配置文件中更改 `identities` 属性。有关如何关联联合用户的更多信息，请参阅[将联合用户与现有用户配置文件关联](cognito-user-pools-identity-federation-consolidate-users.md)。
+ 当您在 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html) API 请求中更新 IdP 时，您的更改最多可能需要一分钟才能显示在托管登录中。
+ Amazon Cognito 支持在其自身与您的 IdP 之间最多 20 个 HTTP 重定向。
+ 当您的用户使用托管登录进行登录时，透明度浏览器会存储一个加密的登录会话 Cookie，用于记录用户登录时使用的客户端和提供者。如果用户尝试使用相同的参数再次登录，则托管登录会重复使用任何*未过期的*现有会话，并且用户无需再次提供凭证即可进行身份验证。如果用户使用不同的 IdP 再次登录，包括切换到本地用户池登录或从本地用户池登录进行切换，则他们必须提供凭证并生成新的登录会话。

  您可以将任何用户池分配 IdPs 给任何应用程序客户端，并且用户只能使用您分配给其应用程序客户端的 IdP 登录。

**Topics**
+ [联合登录在 Amazon Cognito 用户池中的工作方式](#cognito-user-pools-identity-federation-how-it-works)
+ [应用程序作为 Amazon Cognito 的服务提供者的责任](#cognito-user-pools-identity-federation-how-it-works-app-responsibilities)
+ [关于 Amazon Cognito 用户池第三方登录需要了解的事项](#cognito-user-pools-identity-federation-how-it-works-considerations)
+ [为用户池配置身份提供者](cognito-user-pools-identity-provider.md)
+ [将社交身份提供者与用户池配合使用](cognito-user-pools-social-idp.md)
+ [将 SAML 身份提供者与用户池配合使用](cognito-user-pools-saml-idp.md)
+ [将 OIDC 身份提供者与用户池配合使用](cognito-user-pools-oidc-idp.md)
+ [将 IdP 属性映射到配置文件和令牌](cognito-user-pools-specifying-attribute-mapping.md)
+ [将联合用户与现有用户配置文件关联](cognito-user-pools-identity-federation-consolidate-users.md)

# 为用户池配置身份提供者
<a name="cognito-user-pools-identity-provider"></a>

使用用户池，您可以通过各种外部身份提供商（IdPs）实现登录。指南的这一部分说明了如何在 Amazon Cognito 控制台中使用用户池设置这些身份提供者。或者，您可以使用用户池 API 和 AWS SDK 以编程方式添加用户池身份提供商。有关更多信息，请参阅 [CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)。

支持的身份提供者选项包括 Facebook、Google 和 Amazon 等社交提供者，以及 OpenID Connect（OIDC）和 SAML 2.0 提供者。在开始之前，请为自己设置 IdP 的管理凭证。对于每种类型的提供者，您都需要注册应用程序，获取必要的凭证，然后在用户池中配置提供者的详细信息。然后，您的用户可以使用已连接身份提供者的现有账户注册和登录您的应用程序。

“**身份验证**” 下的 “**社交和外部提供商**” 菜单可添加和更新用户池 IdPs。有关更多信息，请参阅 [使用第三方身份提供者进行用户池登录](cognito-user-pools-identity-federation.md)。

**Topics**
+ [使用社交 IdP 设置用户登录](#cognito-user-pools-facebook-provider)
+ [使用 OIDC IdP 设置用户登录](#cognito-user-pools-oidc-providers)
+ [使用 SAML IdP 设置用户登录](#cognito-user-pools-saml-providers)

## 使用社交 IdP 设置用户登录
<a name="cognito-user-pools-facebook-provider"></a>

您可以使用联合身份验证，将 Amazon Cognito 用户池与社交身份提供者（如 Facebook、Google 和 Login with Amazon）集成起来。

要添加社交身份提供者，您首先要通过该身份提供者创建一个开发人员账户。在拥有开发人员账户后，您应向身份提供者注册您的应用程序。该身份提供者将为您的应用程序创建应用程序 ID 和应用程序密钥，然后您在您的 Amazon Cognito 用户池中配置这些值。
+ [Google Identity Platform](https://developers.google.com/identity/)
+ [Facebook for Developers](https://developers.facebook.com/docs/facebook-login)
+ [Login with Amazon](https://developer.amazon.com/login-with-amazon)
+ [通过 Apple 登录](https://developer.apple.com/sign-in-with-apple/)

**将用户登录与社交 IdP 集成**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 在导航窗格中，选择 **用户池**，然后选择要编辑的用户池。

1. 选择**社交和外部提供商**菜单。

1. 选择 **Add an identity provider**（添加身份提供者），或者选择已配置的身份提供者（例如 **Facebook**、**Google**、**Amazon** 或 **Apple**），找到 **Identity provider information**（身份提供者信息），然后选择 **Edit**（编辑）。有关添加社交身份提供者的更多信息，请参阅[将社交身份提供者与用户池配合使用](cognito-user-pools-social-idp.md)。

1. 根据您选择的 IdP，完成以下步骤之一，从而输入社交身份提供者的信息：  
**Facebook、Google 和 Login with Amazon**  
输入您创建客户端应用程序时收到的应用程序密钥。  
**Sign In with Apple**  
输入您向 Apple 提供的服务 ID，以及创建应用程序客户端时收到的团队 ID、密钥 ID 和私有密钥。

1. 对于 **Authorize scopes**（授权范围），输入要映射到用户池属性的社交身份提供者范围的名称。范围定义了您要通过应用程序访问的用户属性（如名称和电子邮件）。输入范围时，根据您选择的 IdP 使用以下准则：
   + **Facebook** – 以英文逗号分隔范围。例如：

     `public_profile, email`
   + **Google、Login with Amazon 和 Sign In with Apple** – 以空格分隔范围。例如：
     + **Google:** `profile email openid`
     + **Login with Amazon:** `profile postal_code`
     + **通过 Apple 登录：**`name email`
**注意**  
对于 Sign in with Apple（控制台），请使用复选框以选择范围。

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

1. 在**应用程序客户端**菜单中，从列表中选择一个应用程序客户端，然后选择**编辑**。将新的社交身份提供商添加到 **Identity providers**（身份提供商）下的应用程序客户端。

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

有关社交的更多信息 IdPs，请参阅[将社交身份提供者与用户池配合使用](cognito-user-pools-social-idp.md)。

## 使用 OIDC IdP 设置用户登录
<a name="cognito-user-pools-oidc-providers"></a>

您可以将用户登录与 OpenID Connect (OIDC) 身份提供者 (IdP) 集成，例如 Salesforce 或 Ping Identity。

**向用户池添加 OIDC 提供者**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 从导航菜单中选择 **User Pools**（用户池）。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**社交和外部提供商**菜单，然后选择**添加身份提供者**。

1. 选择 **OpenID Connect** 身份提供者。

1. 在 **Provider name**（提供商名称）中输入一个唯一名称。

1. 将您从提供商那里收到的客户端 ID 输入到 **Client ID**（客户端 ID）。

1. 将您从提供商那里收到的客户端密钥输入到 **Client secret**（客户端密钥）。

1. 为该提供商输入 **Authorized scopes**（授权范围）。范围定义了应用程序将向您的提供商请求的用户属性组（例如 `name` 和 `email`）。按照 [OAuth 2.0](https://tools.ietf.org/html/rfc6749#section-3.3) 规范，作用域必须用空格分隔。

   您的用户必须同意向您的应用程序提供这些属性。

1. 请选择一个 **Attribute request method**（属性请求方法），以便为 Amazon Cognito 提供 HTTP 方法（GET 或 POST），Amazon Cognito 使用该方法从提供商运营的 **userInfo** 端点中获取用户的详细信息。

1. 请选择 **Setup method**（设置方法）并通过 **Auto fill through issuer URL**（自动填充发布者 URL）或 **Manual input**（手动输入）检索 OpenID Connect 端点。如果您的提供商拥有公共`.well-known/openid-configuration`终端节点，Amazon Cognito 可以在其中检索、、和`jwks_uri`终端节点 `authorization` `token``userInfo`，请 URLs 使用**自动填写发行者 URL**。

1. 输入 URLs 来自您的 IdP 的发卡机构 URL 或`authorization``token``userInfo`、、和`jwks_uri`终端节点。
**注意**  
您只能使用端口号 443 和 80 进行发现、自动填充和手动输入。 URLs如果您的 OIDC 提供商使用任何非标准 TCP 端口，则用户登录失败。  
发布者 URL 必须以 `https://` 开头，而且不得以 `/` 字符结尾。例如，Salesforce 使用以下 URL：  
`https://login.salesforce.com`   
与您的发卡机构 URL 关联的`openid-configuration`文档必须 URLs 为以下值提供 HTTPS：`authorization_endpoint``token_endpoint`、`userinfo_endpoint`、和`jwks_uri`。同样，当您选择 “**手动输入**” 时，只能输入 HTTPS URLs。

1. 默认情况下，**sub** OIDC 声明将映射到用户池 **Username**（用户名）属性中。您可以将其他 OIDC [声明](https://openid.net/specs/openid-connect-basic-1_0.html#StandardClaims)映射到用户池属性。输入 OIDC 声明，然后从下拉列表中选择对应的用户池属性。例如，声明 **email** 通常会映射到用户池属性 **Email**（电子邮件）。

1. 请将身份提供者的其它属性映射到您的用户池。有关更多信息，请参阅[指定适用于用户池的身份提供程序属性映射](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-specifying-attribute-mapping.html)。

1. 选择**创建**。

1. 在**应用程序客户端**菜单中，从列表中选择一个应用程序客户端。要将新 SAML 身份提供者添加到应用程序客户端，请导航到**登录页面**选项卡，然后选择**托管登录页面配置**上的**编辑**。

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

有关 OIDC 的更多信息 IdPs，请参阅。[将 OIDC 身份提供者与用户池配合使用](cognito-user-pools-oidc-idp.md)

## 使用 SAML IdP 设置用户登录
<a name="cognito-user-pools-saml-providers"></a>

您可以使用 Amazon Cognito 用户池的联合身份验证与 SAML 身份提供者（IdP）集成。您可以通过上传文件或输入元数据文档端点 URL 来提供元数据文档。有关获取第三方 SAML 的元数据文档的信息 IdPs，请参阅[配置第三方 SAML 身份提供者](cognito-user-pools-integrating-3rd-party-saml-providers.md)。

**在您的用户池中配置 SAML 2.0 身份提供商**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**社交和外部提供商**菜单，然后选择**添加身份提供者**。

1. 选择 **SAML** 身份提供者。

1. 输入以逗号分隔的 **Identifiers**（标识符）。标识符指示 Amazon Cognito 检查用户登录电子邮件地址，然后将用户引导到与其域对应的提供商。

1. 如果您希望 Amazon Cognito 在用户注销时向您的提供商发送已签名的注销请求，请选择 **Add sign-out flow**（添加注销流程）。配置 SAML 2.0 身份提供者，向您配置托管登录时 Amazon Cognito 创建的 `https://mydomain.auth.us-east-1.amazoncognito.com/saml2/logout` 端点发送注销响应。此 `saml2/logout` 端点使用 POST 绑定。
**注意**  
如果选择此选项，并且您的 SAML 身份提供者需要已签名的注销请求，则您还需要为您的 SAML IdP 配置 Amazon Cognito 提供的签名证书。  
SAML IdP 将处理已签名的注销请求并从 Amazon Cognito 会话中注销您的用户。

1. 选择 **Metadata document source**（元数据文档源）。如果您的身份提供商在公有 URL 上提供 SAML 元数据，则可以选择 **Metadata document URL**（元数据文档 URL），然后输入该公有 URL。否则，请选择 **Upload metadata document**（上载元数据文档），然后选择您之前从提供商下载的元数据文件。
**注意**  
如果您的提供商具有公有端点，建议您输入元数据文档 URL，而不是上载文件。如果您使用 URL，Amazon Cognito 会自动刷新元数据。通常，元数据刷新操作每 6 小时执行一次或在元数据过期前执行（以时间较早者为准）。

1. **Map attributes between your SAML provider and your app**（在 SAML 提供商和应用程序之间映射属性）将 SAML 提供程序属性映射到用户池中的用户配置文件。在属性映射中包含用户池必需属性。

   例如，当您选择 **User pool attribute**（用户池属性）`email` 时，按照您的身份提供者提供的 SAML 断言中显示的内容，输入 SAML 属性名称。您的身份提供商可能会提供示例 SAML 断言以供参考。一些身份提供者使用简单名称（如 `email`），另一些则使用类似于下面 URL 格式的属性名称：

   ```
   http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
   ```

1. 选择 **Create**（创建）。

**注意**  
如果您在使用 HTTPS 元数据端点 URL 创建 SAML IdP 时看见 `InvalidParameterException`，请确保元数据端点已正确设置 SSL，并且存在与之关联的有效 SSL 证书。此类异常的一个例子是 “从中检索元数据时出错*<metadata endpoint>*”。

**设置 SAML IdP 以添加签名证书**
+ 要获取包含 IdP 用于验证已签名注销请求的公钥的证书，请执行以下操作：

  1. 转到用户池的**社交和外部提供商**菜单。

  1. 选择 SAML 提供商。

  1. 选择**查看签名证书**。

有关 SAML 的更多信息， IdPs 请参阅[将 SAML 身份提供者与用户池配合使用](cognito-user-pools-saml-idp.md)。

# 将社交身份提供者与用户池配合使用
<a name="cognito-user-pools-social-idp"></a>

您的 Web 和移动应用程序用户可以通过社交身份提供者 (IdP)（例如 Facebook、Google、Amazon 和 Apple）进行登录。利用内置托管 Web UI，Amazon Cognito 将为所有经过身份验证的用户提供令牌处理和管理。这样，后端系统可以基于一组用户池令牌实现标准化。您必须启用托管登录才能与受支持的社交身份提供者集成。当 Amazon Cognito 构建您的托管登录页面时，它会创建 OAuth 2.0 个终端节点，Amazon Cognito 和您的 OIDC 以及 IdPs 社交使用这些终端节点来交换信息。有关更多信息，请参阅 [Amazon Cognito 用户池 Auth API 参考](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html)。

你可以在中添加社交 IdP AWS 管理控制台，也可以使用 CLI 或 Amazon Cognito AP AWS I。

**注意**  
通过第三方（联合身份验证）进行登录可在 Amazon Cognito 用户池中实现。此功能不依赖于通过 Amazon Cognito 身份池（联合身份）实现的联合身份验证。

**Topics**
+ [设置社交 IdP 开发人员账户和应用程序](#cognito-user-pools-social-idp-step-1)
+ [使用社交 IdP 配置用户池](#cognito-user-pools-social-idp-step-2)
+ [测试社交 IdP 配置](#cognito-user-pools-social-idp-step-3)

## 设置社交 IdP 开发人员账户和应用程序
<a name="cognito-user-pools-social-idp-step-1"></a>

在使用 Amazon Cognito 创建社交 IdP 之前，必须向社交 IdP 注册应用程序才能接收客户端 ID 和客户端密钥。

------
#### [ Facebook ]

有关 Meta 开发人员账户配置和身份验证的最新信息，请参阅 [Meta 应用程序开发](https://developers.facebook.com/docs/development)。

**如何向 Facebook/Meta 注册应用程序**

1. 创建 [Facebook 开发人员账户](https://developers.facebook.com/docs/facebook-login)。

1. 使用 Facebook 凭证[登录](https://developers.facebook.com/)。

1. 在 **My Apps**（我的应用程序）菜单上，选择 **Create New App**（创建新的应用程序）。

1. 输入 Facebook 应用程序的名称，然后选择 **Create App ID**（创建应用程序 ID）。

1. 在左侧导航栏上，选择 **Settings**（设置），然后选择 **Basic**（基本）。

1. 记下 **App ID**（应用程序 ID）和 **App Secret**（应用程序密钥）。您将在下一节中使用它们。

1. 从页面底部选择 **\$1 Add Platform**（\$1 添加平台）。

1. 选择 **Website**（网站）。

1. 在 **Website**（网站）下，请在您的应用程序登录页面上将路径输入到 **Site URL**（站点 URL）中。

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com/login?response_type=code&client_id=1example23456789&redirect_uri=https://www.example.com
   ```

1. 选择 **Save changes**（保存更改）。

1. 在您的用户池域的根目录中，将路径输入到 **App Domains**（应用程序域）。

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com
   ```

1. 选择 **Save changes**（保存更改）。

1. 从导航栏中，选择 **Add Product**（添加产品），然后选择 **Facebook Login**（Facebook 登录）中的 **Set up**（设置）。

1. 从导航栏中，选择 **Facebook Login**（Facebook 登录），然后选择 **Settings**（设置）。

   在 “**有效 OAuth重定向**” 中输入您的用户池域的`/oauth2/idpresponse`终端节点路径 URIs。

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/idpresponse
   ```

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

------
#### [ Login with Amazon ]

有关 Login with Amazon 开发人员账户配置和身份验证的最新信息，请参阅 [Login with Amazon 文档](https://developer.amazon.com/docs/login-with-amazon/documentation-overview.html)。

**如何使用 Login with Amazon 注册应用程序**

1. 创建 [Amazon 开发人员账户](https://developer.amazon.com/login-with-amazon)。

1. 使用 Amazon 凭证[登录](https://developer.amazon.com/lwa/sp/overview.html)。

1. 您需要创建一个 Amazon 安全配置文件才能接收 Amazon 客户端 ID 和客户端密钥。

   从页面顶部的导航栏中选择 **Apps and Services**（应用程序和服务），然后选择 **Login with Amazon**。

1. 选择 **Create a Security Profile**（创建安全配置文件）。

1. 输入 **Security Profile Name**（安全配置文件名称）、**Security Profile Description**（安全配置文件描述）和 **Consent Privacy Notice URL**（同意隐私声明 URL）。

1. 选择 **Save**（保存）。

1. 选择 **Client ID**（客户端 ID）和 **Client Secret**（客户端密钥）以显示客户端 ID 和密钥。您将在下一节中使用它们。

1. 将鼠标悬停在齿轮图标上并选择 **Web Settings**（Web 设置），然后选择 **Edit**（编辑）。

1. 将用户池域输入到 **Allowed Origins**（允许的源）中。

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com
   ```

1. 在 “**允许的返回**” 中输入您的用户池域和`/oauth2/idpresponse`终端节点 URLs。

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/idpresponse
   ```

1. 选择**保存**。

------
#### [ Google ]

有关 Google Cloud 平台中 OAuth 2.0 的更多信息，请参阅 Google Workspace 开发者版文档中的[了解身份验证和授权](https://developers.google.com/workspace/guides/auth-overview)。

**如何向 Google 注册应用程序**

1. 创建 [Google 开发人员账户](https://developers.google.com/identity)。

1. 登录到 [Google Cloud Platform 控制台](https://console.cloud.google.com/home/dashboard)。

1. 从顶部导航栏中，选择 **Select a project**（选择项目）。如果您在 Google 平台中已经有项目，则此菜单会改为显示您的默认项目。

1. 选择 **NEW PROJECT**（新建项目）。

1. 输入产品的名称，然后选择 **CREATE**（创建）。

1. 在左侧导航栏上，选择**APIs 和服务**，然后选择 **Oauth 同意屏幕**。

1. 输入应用程序信息，**App domain**（应用程序域）、**Authorized domains**（已授权的域）和 **Developer contact information**（开发人员联系信息）。例如，您的 **Authorized domains**（已授权的域）必须包括 `amazoncognito.com` 和自定义域的根，例如 `example.com`。选择 **SAVE AND CONTINUE**（保存并继续）。

1. 1. 在 “**范围**” 下，选择 “**添加或移除范围**”，然后至少选择以下 OAuth 范围。

   1. `.../auth/userinfo.email`

   1. `.../auth/userinfo.profile`

   1. openid

1. 在 **Test users**（测试用户）下，选择 **Add users**（添加用户）。输入您的电子邮件地址和任何其他授权测试用户，然后选择 **SAVE AND CONTINUE**（保存并继续）。

1. 再次展开左侧导航栏，选择**APIs 和服务**，然后选择**凭证**。

1. 选择**创建凭据**，然后选择**OAuth 客户端 ID**。

1. 选择 **Application type**（应用程序类型）并为客户端提供 **Name**（名称）。

1. 在 “**授权 JavaScript 来源**” 下，选择 “**添加 URI**”。输入用户群体域。

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com
   ```

1. 在 “**授权重定向**” 下 URIs，选择 “**添加 URI**”。输入指向用户群体域的 `/oauth2/idpresponse` 端点的路径。

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/idpresponse
   ```

1. 选择 **CREATE**（创建）。

1. 安全地存储 Google 在 **Your client ID**（您的客户端 ID）和 **Your client secret**（您的客户端密钥）下显示的值。当您添加 Google IdP 时，请向 Amazon Cognito 提供这些值。

------
#### [ Sign in with Apple ]

有关设置 “使用 Apple 登录” 的 up-to-date更多信息，请参阅 Apple 开发者文档[中的配置环境以使用 Apple 登录](https://developer.apple.com/documentation/signinwithapple/configuring-your-environment-for-sign-in-with-apple)。

**如何通过 Sign in with Apple（SIWA）注册应用程序**

1. 创建 [Apple 开发人员账户](https://developer.apple.com/programs/enroll/)。

1. 使用 Apple 凭证[登录](https://developer.apple.com/account/#/welcome)。

1. 在左侧导航栏上，选择 **Certificates, Identifiers & Profiles**（证书、标识符和配置文件）。

1. 在左侧导航栏上，选择 **Identifiers (标识符)**。

1. 在 **Identifiers (标识符)** 页面上，选择 **\$1** 图标。

1. 在 “**注册新标识符**” 页面上，选择 “**应用程序**” IDs，然后选择 “**继续**”。

1. 在 **Select a type**（选择类型）页面上，选择 **App**（应用程序），然后选择 **Continue**（继续）。

1. 在 **Register an App ID**（注册应用程序 ID）页面上，执行以下操作：

   1. 在 **Description**（说明）下，输入说明。

   1. 在 **App ID Prefix**（应用程序 ID 前缀）下，输入 **Bundle ID**（捆绑包 ID）。记下 **App ID Prefix**（应用程序 ID 前缀）下的值。在[使用社交 IdP 配置用户池](#cognito-user-pools-social-idp-step-2)中选择 Apple 作为身份提供商后，您将使用此值。

   1. 在 **Capabilities**（功能）下，选择 **Sign In with Apple**，然后选择 **Edit**（编辑）。

   1. 在 “**使用 Apple 登录：应用程序 ID 配置**” 页面上，选择将应用程序设置为主应用程序或与其他应用程序分组 IDs，然后选择 “**保存**”。

   1. 选择 **Continue**（继续）。

1. 在 **Confirm your App ID**（确认您的应用程序 ID）页面上，选择 **Register**（注册）。

1. 在 **Identifiers (标识符)** 页面上，选择 **\$1** 图标。

1. 在 “**注册新标识符**” 页上，选择 “**服务**” IDs，然后选择 “**继续**”。

1. 在 **Register an Services ID**（注册服务 ID）页面上，执行以下操作：

   1. 在 **Description**（描述）下方，键入描述。

   1. 在 **Identifier**（标识符）下方，键入标识符。记下此服务 ID，因为在 中选择 Apple 作为身份提供者后需要此值[使用社交 IdP 配置用户池](#cognito-user-pools-social-idp-step-2)

   1. 选择 **Continue**（继续），然后选择 **Register**（注册）。

1. 从 Identifiers（标识符）页中选择您刚创建的 Services ID（服务 ID）。

   1. 选择 **Sign In with Apple**（使用苹果账号登录），然后选择 **Configure**（配置）。

   1. 在 **Web Authentication Configuration**（Web 身份验证配置）页上，选择您先前创建的应用程序 ID 作为 **Primary App ID**（主应用程序 ID）。

   1. 选择 “**网站**” 旁边的 “**\$1**” 图标 URLs。

   1. 在 **Domains and subdomains**（域名和子域）下，输入不带 `https://` 前缀的用户群体域。

      ```
      mydomain.auth.us-east-1.amazoncognito.com
      ```

   1. 在 **Return** 下 URLs，输入您的用户池域`/oauth2/idpresponse`终端节点的路径。

      ```
      https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/idpresponse
      ```

   1. 选择 **Next**（下一步），然后选择 **Done**（完成）。您不需要验证域。

   1. 选择 **Continue**（继续），然后选择 **Save**（保存）。

1. 在左侧导航栏上，选择 **Keys (密钥)**。

1. 在 **Keys**（密钥）页面上，选择 **\$1** 图标。

1. 在 **Register a New Key**（注册新密钥）页面上，执行以下操作：

   1. 在 **Key Name**（密钥名称）下，输入密钥名称。

   1. 选择 **Sign In with Apple**，然后选择 **Configure**（配置）。

   1. 在 **Configure Key**（配置密钥）页上，选择您先前创建的应用程序 ID 作为 **Primary App ID**（主应用程序 ID）。选择**保存**。

   1. 选择 **Continue**（继续），然后选择 **Register**（注册）。

1. 在 **Download Your Key**（下载您的密钥）页面上，选择 **Download**（下载）以下载私有密钥并记下显示的 **Key ID**（密钥 ID），然后选择 **Done**（完成）。在[使用社交 IdP 配置用户池](#cognito-user-pools-social-idp-step-2)中选择 Apple 作为身份提供商后，您将需要此私有密钥和在此页面上显示的 **Key ID**（密钥 ID）值。

------

## 使用社交 IdP 配置用户池
<a name="cognito-user-pools-social-idp-step-2"></a>

**要配置用户池社交 IdP，请使用 AWS 管理控制台**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或创建一个用户池。

1. 选择**社交和外部提供商**菜单，然后选择**添加身份提供者**。

1. 选择一个社交 IdP：**Facebook**、**Google**（谷歌）、**Login with Amazon**（使用亚马逊账号登录）或 **Sign in with Apple**（使用苹果账号登录）。

1. 根据您选择的社交 IdP，从以下步骤中进行选择：
   + **Google** 和 **Login with Amazon** – 输入在上一部分中生成的 **app client ID**（应用程序客户端 ID）和 **app client secret**（应用程序客户端密钥）。
   + **Facebook** – 输入在上一部分中生成的 **app client ID**（应用程序客户端 ID）和 **app client secret**（应用程序客户端密钥），然后选择 API 版本（例如，版本 2.12）。建议选择最新的可用版本，因为每个 Facebook API 版本都有一个生命周期和一个弃用日期。Facebook 的范围和属性可能因 API 版本而异。建议您使用 Facebook 测试您的社交身份登录，以确保联合身份认证会按预期运行。
   + **Sign In with Apple** – 输入在上一部分中生成的 **Services ID**（服务 ID）、**Team ID**（团队 ID）、**Key ID**（密钥 ID）和 **private key**（私有密钥）。

1. 输入要使用的 **Authorized scopes**（授权范围）的名称。范围定义了您要通过应用程序访问的用户属性（如 `name` 和 `email`）。对于 Facebook，这些属性应用逗号分隔。对于 Google 和 Login with Amazon，则应采用空格分隔。对于 Sign in with Apple，选中要访问的范围的复选框。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/cognito-user-pools-social-idp.html)

   您的应用程序用户需要同意向您的应用程序提供这些属性。关于社交服务提供商范围的更多信息，请参阅 Google、Facebook 和 Login with Amazon 或 Sign in with Apple 的文档。

   对于 Sign in with Apple，下面提供了可能不会返回范围的用户场景：
   + 终端用户离开 Apple 登录页面后出现故障（可能来自 Amazon Cognito 内部的故障或开发人员编写的任何内容）
   + 服务 ID 标识符用于用户池、 and/or 其他身份验证服务
   + 在最终用户登录之前，开发人员添加了其他范围（未检索到新信息）
   + 开发人员删除用户，然后用户再次登录，而没有从其 Apple ID 配置文件中删除该应用程序

1. 请将 IdP 的属性映射到您的用户池。有关更多信息，请参阅[指定适用于用户池的身份提供程序属性映射](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-specifying-attribute-mapping.html)。

1. 选择**创建**。

1. 在**应用程序客户端**菜单中，从列表中选择一个应用程序客户端。要将新社交身份提供者添加到该应用程序客户端，请导航到**登录页面**选项卡，然后选择**托管登录页面配置**上的**编辑**。

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

## 测试社交 IdP 配置
<a name="cognito-user-pools-social-idp-step-3"></a>

在您的应用程序中，您必须在用户的客户端中调用浏览器，这样他们才能使用社交服务提供商进行登录。完成前几节中的设置过程后，使用社交服务提供商测试登录。以下示例 URL 通过前缀域加载用户池的登录页面。

```
https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?response_type=code&client_id=1example23456789&redirect_uri=https://www.example.com
```

此链接是当您转到**应用程序客户端**菜单，选择应用程序客户端，导航到**登录页面**选项卡，然后选择**查看登录页面**时，Amazon Cognito 将您引导至的页面。有关用户池域的更多信息，请参阅 [配置用户池域](cognito-user-pools-assign-domain.md)。有关应用程序客户端（包括客户端 IDs 和回调）的更多信息 URLs，请参阅[特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。

以下链接示例通过 `identity_provider` 查询参数设置从[对端点授权](authorization-endpoint.md)到社交服务提供商的静默重定向。此 URL 会绕过使用托管登录的交互式用户池登录，直接转到 IdP 登录页面。

```
https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?identity_provider=Facebook|Google|LoginWithAmazon|SignInWithApple&response_type=code&client_id=1example23456789&redirect_uri=https://www.example.com
```

# 将 SAML 身份提供者与用户池配合使用
<a name="cognito-user-pools-saml-idp"></a>

可以选择允许 Web 和移动应用程序用户通过 SAML 身份提供者（IdP）[如 [Microsoft Active Directory 联合身份验证服务（ADFS）](https://msdn.microsoft.com/en-us/library/bb897402.aspx)或 [Shibboleth](http://www.shibboleth.net/)] 登录。您必须选择支持 [SAML 2.0 标准](http://saml.xml.org/saml-specifications)的 SAML IdP。

通过托管登录，Amazon Cognito 可以对本地和第三方 IdP 用户进行身份验证，并发放 JSON 网络令牌 ()。JWTs使用 Amazon Cognito 发放的令牌，您可以将多个身份源整合为适用于所有应用程序的通用 OpenID Connect（OIDC）标准。Amazon Cognito 可以处理来自第三方提供者的 SAML 断言，并将其转换为 SSO 标准。您可以在、通过 AWS CLI或使用 Amazon Cognito 用户池 API 创建和管理 SAML IdP。 AWS 管理控制台要在中创建您的第一个 SAML IdP AWS 管理控制台，请参阅。[在用户池中添加和力 SAML 身份提供者](cognito-user-pools-managing-saml-idp.md)

![\[SAML 登录的身份验证概述\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/scenario-authentication-saml.png)


**注意**  
通过第三方 IdP 登录进行联合身份验证是 Amazon Cognito 用户池的一项特征。Amazon Cognito 身份池（有时称为 Amazon Cognito 联合身份）是一种联合身份验证的实现，您必须在每个身份池中单独进行设置。用户池可以是身份池的第三方 IdP。有关更多信息，请参阅 [Amazon Cognito 身份池](cognito-identity.md)。

## IdP 配置的快速参考
<a name="cognito-user-pools-saml-idp-reference"></a>

您必须配置 SAML IdP，以便接受请求并向用户池发送响应。SAML IdP 的文档将包含相关信息，让您可以了解如何将用户池添加为 SAML 2.0 IdP 的依赖方或应用程序。接下来的文档将提供必须为 SP 实体 ID 和断言使用者服务（ACS）URL 提供的值。用户池 SAML 值快速参考

**SP 实体 ID**  

```
urn:amazon:cognito:sp:us-east-1_EXAMPLE
```

**ACS URL**  

```
https://Your user pool domain/saml2/idpresponse
```

您必须配置用户池来支持您的身份提供者。添加外部 SAML IdP 的大致步骤如下。

1. 从您的 IdP 下载 SAML 元数据，或检索元数据端点的 URL。请参阅[配置第三方 SAML 身份提供者](cognito-user-pools-integrating-3rd-party-saml-providers.md)。

1. 将新的 IdP 添加到用户池。上传 SAML 元数据或提供元数据 URL。请参阅[在用户池中添加和力 SAML 身份提供者](cognito-user-pools-managing-saml-idp.md)。

1. 将 IdP 分配给您的应用程序客户端。请参阅[特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。

**Topics**
+ [IdP 配置的快速参考](#cognito-user-pools-saml-idp-reference)
+ [关于 Amazon Cognito 用户 IdPs 池中 SAML 的注意事项](cognito-user-pools-saml-idp-things-to-know.md)
+ [SAML 用户名区分大小写](#saml-nameid-case-sensitivity)
+ [配置第三方 SAML 身份提供者](cognito-user-pools-integrating-3rd-party-saml-providers.md)
+ [在用户池中添加和力 SAML 身份提供者](cognito-user-pools-managing-saml-idp.md)
+ [SAML 会话在 Amazon Cognito 用户池中启动](cognito-user-pools-SAML-session-initiation.md)
+ [通过单点注销来注销 SAML 用户](cognito-user-pools-saml-idp-sign-out.md)
+ [SAML 签名和加密](cognito-user-pools-SAML-signing-encryption.md)
+ [SAML 身份提供者名称和标识符](cognito-user-pools-managing-saml-idp-naming.md)

# 关于 Amazon Cognito 用户 IdPs 池中 SAML 的注意事项
<a name="cognito-user-pools-saml-idp-things-to-know"></a>

实施 SAML 2.0 IdP 有一些要求和限制。实施 IdP 时，请参阅此部分。您还将找到一些有用的信息，可用于排查对用户池进行 SAML 联合身份验证期间的错误。

**Amazon Cognito 会为您处理 SAML 断言**  
Amazon Cognito 用户池支持 SAML 2.0 与 POST 绑定端点联合身份验证。这使您的应用程序不必检索或分析 SAML 断言响应，因为用户池直接通过用户代理从 IdP 接收 SAML 响应。您的用户池代表您的应用程序充当服务提供商（SP）。Amazon Cognito 支持 SP 发起和 IdP 发起的单点登录（SSO），如 [SAML V2.0 技术概览](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0-cd-02.html)的第 5.1.2 节和第 5.1.4 节中所述。

**提供有效的 IdP 签名证书**  
在用户池中配置 SAML IdP 时，SAML 提供者元数据中的签名证书不得过期。

**用户池支持多个签名证书**  
如果在 SAML 元数据中，您的 SAML IdP 包含多个签名证书，则在登录时，只要与 SAML 元数据中的任何证书匹配，您的用户池就会确定 SAML 断言有效。每份签名证书的长度不得超过 4096 个字符。

**维护中继状态参数**  
Amazon Cognito 和您的 SAML IdP 使用 `relayState` 参数维护会话信息。  

1. Amazon Cognito 支持大于 80 个字节的 `relayState` 值。虽然 SAML 规范规定 `relayState` 值“长度不得超过 80 个字节”，但目前的行业惯例往往偏离这种行为。因此，拒绝超过 80 个字节的 `relayState` 值将破坏许多标准 SAML 提供商集成。

1. `relayState` 令牌是对 Amazon Cognito 维护的状态信息的不透明引用。Amazon Cognito 不保证 `relayState` 参数的内容。不要解析其内容，以免您的应用程序依赖解析结果。有关更多信息，请参阅 [SAML 2.0 规范](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html)。

**识别 ACS 端点**  
您的 SAML 身份提供者要求您设置断言使用者端点。您的 IdP 使用 SAML 断言将您的用户重定向到此端点。在用户群体域中为您的 SAML 身份提供者中的 SAML 2.0 POST 绑定配置以下端点。  

```
https://Your user pool domain/saml2/idpresponse
With an Amazon Cognito domain:
https://mydomain.auth.us-east-1.amazoncognito.com/saml2/idpresponse
With a custom domain:
https://auth.example.com/saml2/idpresponse
```
有关用户池域的更多信息，请参阅 [配置用户池域](cognito-user-pools-assign-domain.md)。

**没有重播的断言**  
您无法向您的 Amazon Cognito `saml2/idpresponse` 端点重复或*重放* SAML 断言。重放的 SAML 断言的断言 ID 与早期 IdP 响应的 ID 重复。

**用户池 ID 是 SP 实体 ID**  
您必须向 IdP 提供服务提供商（SP）`urn` 中的用户池 ID，也称为*受众 URI* 或 *SP 实体 ID*。用户池的受众 URI 采用以下格式。  

```
urn:amazon:cognito:sp:us-east-1_EXAMPLE
```
您可以在 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)的**用户池概览**下找到用户池 ID。

**映射所有必需属性**  
配置 SAML IdP，为用户池中根据需要设置的任何属性提供值。例如，`email` 是用户池的通用必需属性。在您的用户可以登录之前，SAML IdP 断言必须包含映射到**用户池属性** `email` 的声明。有关属性映射的更多信息，请参阅[将 IdP 属性映射到配置文件和令牌](cognito-user-pools-specifying-attribute-mapping.md)。

**断言格式有特定的要求**  
SAML IdP 必须在 SAML 断言中包括以下声明。  
+ `NameID` 声明。Amazon Cognito 通过 `NameID` 将 SAML 断言与目标用户关联起来。如果 `NameID` 发生变化，Amazon Cognito 会认为这是针对新用户的断言。您在 IdP 配置中设置为 `NameID` 的属性必须具有永久值。要将 SAML 用户分配给用户池中一致的用户配置文件，请根据一个值不变的属性分配您的 `NameID` 声明。

  ```
  <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:persistent">
    carlos
  </saml2:NameID>
  ```

  `urn:oasis:names:tc:SAML:1.1:nameid-format:persistent` 的 IdP `NameID` 声明中的 `Format` 表示您的 IdP 正在传递一个不变的值。Amazon Cognito 不需要这种格式声明，如果您的 IdP 没有指定 `NameID` 声明的格式，则会分配 `urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified` 格式。此行为符合 [SAML 2.0 规范的*复杂类型名称IDType*第 2.2.](https://groups.oasis-open.org/higherlogic/ws/public/download/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf/latest) 2 节。
+ 一项 `AudienceRestriction` 声明，所具有的 `Audience` 值将您的用户池 SP 实体 ID 设置为响应的目标。

  ```
  <saml:AudienceRestriction>
    <saml:Audience> urn:amazon:cognito:sp:us-east-1_EXAMPLE
  </saml:AudienceRestriction>
  ```
+ 对于 SP 发起的单点登录，`Response` 元素具有原始 SAML 请求 ID 的 `InResponseTo` 值。

  ```
  <saml2p:Response Destination="https://mydomain.auth.us-east-1.amazoncognito.com/saml2/idpresponse" ID="id123" InResponseTo="_dd0a3436-bc64-4679-a0c2-cb4454f04184" IssueInstant="Date-time stamp" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  ```
**注意**  
IdP 发起的 SAML 断言*不得*包含 `InResponseTo` 值。
+ 一个 `SubjectConfirmationData` 元素，具有用户池 `saml2/idpresponse` 端点的 `Recipient` 值，而对于 SP 发起的 SAML，具有与原始 SAML 请求 ID 匹配的 `InResponseTo` 值。

  ```
  <saml2:SubjectConfirmationData InResponseTo="_dd0a3436-bc64-4679-a0c2-cb4454f04184" NotOnOrAfter="Date-time stamp" Recipient="https://mydomain.auth.us-east-1.amazoncognito.com/saml2/idpresponse"/>
  ```

**SP 发起的登录请求**  
当 [对端点授权](authorization-endpoint.md) 将用户定向到您的 IdP 登录页面时，Amazon Cognito 会在 `HTTP GET` 请求的 URL 参数中包括 *SAML 请求*。SAML 请求包含有关用户池（包括 ACS 端点）的信息。您可以选择对这些请求应用加密签名。

**签署请求和加密响应**  
每个使用 SAML 提供者的用户池都会生成一个非对称密钥对和*签名证书*，以便让 Amazon Cognito 将数字签名分配给 SAML 请求。您配置为支持加密 SAML 响应的每个外部 SAML IdP 都会导致 Amazon Cognito 为该提供者生成新的密钥对和*加密证书*。要查看和下载带有公钥的证书，请在 Amazon Cognito 控制台的**社交和外部提供商**菜单中选择您的 IdP。  
要与来自用户池的 SAML 请求建立信任，可以向 IdP 提供用户池 SAML 2.0 签名证书的副本。如果您未将 IdP 配置为接受已签名的请求，则您的 IdP 可能会忽略您的用户池签署的 SAML 请求。  

1. Amazon Cognito 将数字签名应用于用户传递给 IdP 的 SAML 请求。您的用户池签署所有单点注销（SLO）请求，您可以将用户池配置为签署任何 SAML 外部 IdP 的单点登录（SSO）请求。当您提供证书副本时，您的 IdP 会验证用户的 SAML 请求的完整性。

1. 您的 SAML IdP 可以使用加密证书来加密 SAML 响应。当您配置采用 SAML 加密的 IdP 时，您的 IdP 只能发送加密的响应。

**对非字母数字字符进行编码**  
Amazon Cognito 不接受您的 IdP 作为属性值传递的 4 字节 UTF-8 字符（例如 😐 或 𠮷）。您可以将字符编码为 Base64，将其作为文本传递，然后在应用程序中对其进行解码。  
在以下示例中，将不接受属性声明：  

```
<saml2:Attribute Name="Name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
  <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">😐</saml2:AttributeValue>
</saml2:Attribute>
```
与上述示例不同，将接受以下属性声明：  

```
<saml2:Attribute Name="Name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
  <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">8J+YkA==</saml2:AttributeValue>
</saml2:Attribute>
```

**元数据端点必须具有有效的传送层安全性**  
如果您在使用 HTTPS 元数据终端节点 URL 创建 SAML IdP `InvalidParameterException` 时看到，例如 “*<metadata endpoint>*从中检索元数据时出错”，请确保元数据端点已正确设置了 SSL，并且存在与之关联的有效的 SSL 证书。有关验证证书的更多信息，请参阅[什么是 SSL/TLS 证书](https://aws.amazon.com/what-is/ssl-certificate/)？ 。

**对于 HTTP 或 HTTPS，元数据端点必须位于标准 TCP 端口上**  
Amazon Cognito 仅接受 HTTP URLs 的标准 TCP 端口 80 和 HTTPS 的 443 上的 SAML 提供商的元数据。作为安全最佳实践，请将 SAML 元数据托管在带有 `https://` 前缀的 TLS 加密 URL 处。以*`http://www.example.com/saml2/metadata.xml`*或 URLs 的格式输入元数据*`https://www.example.com/saml2/metadata.xml`*。Amazon Cognito 控制台 URLs 仅接受带有前`https://`缀的元数据。您也可以使用和配置 IdP 元数据。[CreateIdentityProvider[UpdateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)

**使用 IdP 发起的 SAML 的应用程序客户端只能使用 SAML 登录**  
当您激活对支持 IdP 启动登录应用程序客户端的 SAML 2.0 IdP 的支持时，您只能向该应用程序客户端添加其他 SAML IdPs 2.0。您无法将用户池中的用户目录*以及*所有非 SAML 外部身份提供者添加到以这种方式配置的应用程序客户端。

**注销响应必须使用 POST 绑定**  
`/saml2/logout` 端点接受 `LogoutResponse` 作为 `HTTP POST` 请求。用户池不接受带有 `HTTP GET` 绑定的注销响应。

**元数据签名证书轮换**  
如果您通过 URL 提供元数据，Amazon Cognito 会将 SAML 元数据缓存长达六个小时。执行任何元数据签名证书轮换时，请将元数据源配置为*同时*发布原始证书和新证书至少六个小时。当 Amazon Cognito 从元数据 URL 刷新缓存时，它会将每个证书视为有效，并且您的 SAML IdP 可以开始使用新证书签名 SAML 断言。在此时间后，您可以从发布的元数据中移除原始证书。

## SAML 用户名区分大小写
<a name="saml-nameid-case-sensitivity"></a>

当联合用户尝试登录时，SAML 身份提供者（IdP）在用户的 SAML 断言中将唯一 `NameId` 传递给 Amazon Cognito。Amazon Cognito 通过其 `NameId` 声明识别 SAML 联合身份用户。无论您的用户池的区分大小写如何设置，当从 SAML IdP 返回的联合用户传递其唯一且区分大小写的 `NameId` 声明时，Amazon Cognito 都会识别该用户。如果您将 `email` 等属性映射到 `NameId`，并且您的用户更改其电子邮件地址，他们将无法登录您的应用程序。

从具有不会改变的值的 IdP 属性映射 SAML 断言中的 `NameId`。

例如，Carlos 在您的不区分大小写的用户池中具有来自 Active Directory 联合身份验证服务 (ADFS) SAML 断言的用户配置文件，该断言传递了`Carlos@example.com` 的 `NameId` 值。下次 Carlos 尝试登录时，您的 ADFS IdP 会传递`carlos@example.com` 的 `NameId` 值。由于 `NameId` 的大小写必须完全匹配，登录不成功。

如果您的用户在其 `NameID` 更改后无法登录，请从您的用户池中删除他们的用户配置文件。Amazon Cognito 将在用户下次登录时创建新的用户配置文件。

**Topics**
+ [IdP 配置的快速参考](#cognito-user-pools-saml-idp-reference)
+ [关于 Amazon Cognito 用户 IdPs 池中 SAML 的注意事项](cognito-user-pools-saml-idp-things-to-know.md)
+ [SAML 用户名区分大小写](#saml-nameid-case-sensitivity)
+ [配置第三方 SAML 身份提供者](cognito-user-pools-integrating-3rd-party-saml-providers.md)
+ [在用户池中添加和力 SAML 身份提供者](cognito-user-pools-managing-saml-idp.md)
+ [SAML 会话在 Amazon Cognito 用户池中启动](cognito-user-pools-SAML-session-initiation.md)
+ [通过单点注销来注销 SAML 用户](cognito-user-pools-saml-idp-sign-out.md)
+ [SAML 签名和加密](cognito-user-pools-SAML-signing-encryption.md)
+ [SAML 身份提供者名称和标识符](cognito-user-pools-managing-saml-idp-naming.md)

# 配置第三方 SAML 身份提供者
<a name="cognito-user-pools-integrating-3rd-party-saml-providers"></a>

如果要将 SAML 身份提供者（IdP）添加到用户池，则必须在 IdP 的管理界面中进行一些配置更新。本节介绍如何格式化您必须提供给 IdP 的值。您还可以了解如何检索用于向用户池标识 IdP 及其 SAML 声明的静态或活动 URL 元数据文档。

要配置第三方 SAML 2.0 身份提供者（IdP）解决方案以使用 Amazon Cognito 用户池的联合身份验证，您必须配置 SAML IdP 以重定向到以下断言使用者服务（ACS）URL：`https://mydomain.auth.us-east-1.amazoncognito.com/saml2/idpresponse`。如果您的用户池具有 Amazon Cognito 域，则可以在 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)中您的用户池的**域**菜单中找到用户池域路径。

某些 SAML IdPs 要求您在表`urn:amazon:cognito:sp:us-east-1_EXAMPLE`单中`urn`提供（也称为受众 URI 或 SP 实体 ID）。您可以在 Amazon Cognito 控制台的**用户池概览**下找到用户池 ID。

您还必须配置 SAML IdP，以便为用户池中您指定为*必需属性*的任何属性提供值。通常，`email` 是用户池的必需属性，在这种情况下，SAML IdP 必须在其 SAML 断言中提供某种形式的 `email` 声明，且您必须将该声明映射到该提供者的属性。

以下第三方 SAML 2.0 IdP 解决方案的配置信息是开始使用 Amazon Cognito 用户池设置联合身份验证的一个很好的起点。有关最新信息，请直接查阅提供者的文档。

要签署 SAML 请求，必须将 IdP 配置为信任由您的用户池签名证书签署的请求。要接受加密的 SAML 响应，必须将 IdP 配置为对用户池的*所有* SAML 响应进行加密。您的提供者将提供有关配置这些特征的文档。有关 Microsoft 的示例，请参阅[配置 Microsoft Entra SAML 令牌加密](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/howto-saml-token-encryption)。

**注意**  
Amazon Cognito 只需要身份提供者元数据文档。您的提供者还可能提供 SAML 2.0 与 IAM 或 AWS IAM Identity Center联合身份验证的自定义配置信息。要了解如何设置 Amazon Cognito 集成，请查看检索元数据文档的一般说明并管理用户池中的其余配置。


| 解决方案 | 更多信息 | 
| --- | --- | 
| Microsoft Entra ID | [联合身份验证元数据](https://learn.microsoft.com/en-us/entra/identity-platform/federation-metadata) | 
| Okta | [如何下载用于 SAML 应用程序集成的 IdP 元数据和 SAML 签名证书](https://support.okta.com/help/s/article/Location-to-download-Okta-IDP-XML-metadata-for-a-SAML-app-in-the-new-Admin-User-Interface) | 
| Auth0 | [将 Auth0 配置为 SAML 身份提供者](https://auth0.com/docs/authenticate/protocols/saml/saml-sso-integrations/configure-auth0-saml-identity-provider) | 
| Ping 身份 (PingFederate) | [从中导出 SAML 元数据 PingFederate](https://docs.pingidentity.com/integrations/contentful/configuring_single_sign-on/pf_contentful_integration_exporting_saml_metadata_from_pf.html) | 
| JumpCloud | [SAML 配置备注](https://jumpcloud.com/support/saml-configuration-notes) | 
| SecureAuth | [SAML 应用程序集成](https://docs.secureauth.com/2104/en/saml-application-integration.html) | 

# 在用户池中添加和力 SAML 身份提供者
<a name="cognito-user-pools-managing-saml-idp"></a>

将身份提供者配置为与 Amazon Cognito 配合使用后，您可以将其添加到用户池和应用程序客户端。以下步骤演示了如何在 Amazon Cognito 用户池中创建、修改和删除 SAML 提供者。

------
#### [ AWS 管理控制台 ]

您可以使用 AWS 管理控制台 来创建和删除 SAML 身份提供商 (IdPs)。

在创建 SAML IdP 之前，您必须具有从第三方 IdP 处获得的 SAML 元数据文档。有关如何获取或生成所需的 SAML 元数据文档的说明，请参阅[配置第三方 SAML 身份提供者](cognito-user-pools-integrating-3rd-party-saml-providers.md)。

**在您的用户池中配置 SAML 2.0 IdP**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入 AWS 凭证。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**社交和外部提供商**菜单，然后选择**添加身份提供者**。

1. 选择一个 **SAML** IdP。

1. 输入**提供商名称**。您可以在 `identity_provider` 请求参数中将这个友好名称传递给 [对端点授权](authorization-endpoint.md)。

1. 输入以逗号分隔的 **Identifiers**（标识符）。标识符将告知 Amazon Cognito 应该检查用户登录时输入的电子邮件地址，然后将它们引导到与其域名对应的提供商。

1. 如果您希望 Amazon Cognito 在用户注销时向您的提供商发送已签名的注销请求，请选择 **Add sign-out flow**（添加注销流程）。您必须配置 SAML 2.0 IdP 以向配置托管登录时创建的 `https://mydomain.auth.us-east-1.amazoncognito.com/saml2/logout` 端点发送注销响应。此 `saml2/logout` 端点使用 POST 绑定。
**注意**  
如果选择此选项，且您的 SAML IdP 需要已签署的注销请求，则还必须为您的 SAML IdP 提供来自用户池的签名证书。  
SAML IdP 将处理已签名的注销请求并从 Amazon Cognito 会话中注销您的用户。

1. 选择 **IdP 发起的 SAML 登录**配置。作为一项安全最佳实践，请选择**仅接受 SP 发起的 SAML 断言**。如果您已准备好环境，以便安全地接受未经请求的 SAML 登录会话，请选择**接受 SP 发起和 IdP 发起的 SAML 断言**。有关更多信息，请参阅 [SAML 会话在 Amazon Cognito 用户池中启动](cognito-user-pools-SAML-session-initiation.md)。

1. 选择 **Metadata document source**（元数据文档源）。如果您的 IdP 在公有 URL 上提供 SAML 元数据，则可以选择 **Metadata document URL**（元数据文档 URL），然后输入该公有 URL。否则，请选择 **Upload metadata document**（上载元数据文档），然后选择您之前从提供商下载的元数据文件。
**注意**  
如果您的提供者具有公有端点，建议您输入元数据文档 URL，而不是上传文件。Amazon Cognito 会自动从元数据 URL 刷新元数据。通常，元数据刷新操作每 6 小时执行一次或在元数据过期前执行（以时间较早者为准）。

1. **在 SAML 提供者和用户池之间映射属性**选项将 SAML 提供者属性映射到用户池中的用户配置文件。在属性映射中包含用户池必需属性。

   例如，当您选择 **User pool attribute**（用户池属性）`email` 时，按照您的 IdP 提供的 SAML 断言中显示的内容，输入 SAML 属性名称。如果 IdP 提供了示例 SAML 断言，您可以使用这些示例断言帮助您查找名称。有些 IdPs 使用简单的名称，例如`email`，而另一些则使用如下所示的名称。

   ```
   http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
   ```

1. 选择**创建**。

------
#### [ API/CLI ]

使用以下命令可创建和管理 SAML 身份提供者 (IdP)。

**创建 IdP 并上传元数据文档**
+ AWS CLI: `aws cognito-idp create-identity-provider`

  带元数据文件的示例：`aws cognito-idp create-identity-provider --user-pool-id us-east-1_EXAMPLE --provider-name=SAML_provider_1 --provider-type SAML --provider-details file:///details.json --attribute-mapping email=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`

  其中 `details.json` 包含：

  ```
  "ProviderDetails": { 
        "MetadataFile": "<SAML metadata XML>",
        "IDPSignout" : "true",
        "RequestSigningAlgorithm" : "rsa-sha256",
        "EncryptedResponses" : "true",
        "IDPInit" : "true"
  }
  ```
**注意**  
如果*<SAML metadata XML>*包含该字符的任何实例`"`，则必须添加`\`为转义字符：`\"`。

  带元数据 URL 的示例：`aws cognito-idp create-identity-provider --user-pool-id us-east-1_EXAMPLE --provider-name=SAML_provider_1 --provider-type SAML --provider-details MetadataURL=https://myidp.example.com/sso/saml/metadata --attribute-mapping email=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`
+ AWS API: [CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)

**为 IdP 上传新的元数据文档**
+ AWS CLI: `aws cognito-idp update-identity-provider`

  带元数据文件的示例：`aws cognito-idp update-identity-provider --user-pool-id us-east-1_EXAMPLE --provider-name=SAML_provider_1 --provider-details file:///details.json --attribute-mapping email=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`

  其中 `details.json` 包含：

  ```
  "ProviderDetails": { 
        "MetadataFile": "<SAML metadata XML>",
        "IDPSignout" : "true",
        "RequestSigningAlgorithm" : "rsa-sha256",
        "EncryptedResponses" : "true",
        "IDPInit" : "true"
  }
  ```
**注意**  
如果*<SAML metadata XML>*包含该字符的任何实例`"`，则必须添加`\`为转义字符：`\"`。

  带元数据 URL 的示例：`aws cognito-idp update-identity-provider --user-pool-id us-east-1_EXAMPLE --provider-name=SAML_provider_1 --provider-details MetadataURL=https://myidp.example.com/sso/saml/metadata --attribute-mapping email=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`
+ AWS API: [UpdateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html)

**获取有关特定 IdP 的信息**
+ AWS CLI: `aws cognito-idp describe-identity-provider`

  `aws cognito-idp describe-identity-provider --user-pool-id us-east-1_EXAMPLE --provider-name=SAML_provider_1`
+ AWS API: [DescribeIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeIdentityProvider.html)

**列出所有相关信息 IdPs**
+ AWS CLI: `aws cognito-idp list-identity-providers`

  示例：`aws cognito-idp list-identity-providers --user-pool-id us-east-1_EXAMPLE --max-results 3`
+ AWS API: [ListIdentityProviders](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListIdentityProviders.html)

**删除 IdP**
+ AWS CLI: `aws cognito-idp delete-identity-provider`

  `aws cognito-idp delete-identity-provider --user-pool-id us-east-1_EXAMPLE --provider-name=SAML_provider_1`
+ AWS API: [DeleteIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteIdentityProvider.html)

------

**设置 SAML IdP 以添加用户池作为信赖方**
+ 用户池服务提供商 URN 为：`urn:amazon:cognito:sp:us-east-1_EXAMPLE`。Amazon Cognito 要求受众限制值与 SAML 响应中的这个 URN 相匹配。将您的 IdP 配置为使用以下 POST 绑定端点 IdP-to-SP作为响应消息。

  ```
  https://mydomain.auth.us-east-1.amazoncognito.com/saml2/idpresponse
  ```
+ 您的 SAML IdP 必须在 SAML 断言中为用户池填入 `NameID` 和任何必需属性。`NameID` 用于在用户池中唯一地标识您的 SAML 联合用户。您的 IdP 必须以一致、区分大小写的格式传递每个用户的 SAML 名称 ID。用户名 ID 值发生任何变化都会创建一个新的用户配置文件。

**向您的 SAML 2.0 IDP 提供签名证书**
+ 要从 Amazon Cognito 下载公钥的副本，让您的 IdP 可使用该副本来验证 SAML 注销请求，请选择用户池的**社交和外部提供商**菜单，选择您的 IdP，然后在**查看签名证书**下面，选择**以 .crt 格式下载证书**。

您可以使用 Amazon Cognito 控制台删除在用户池中设置的任何 SAML 提供商。

**删除 SAML 提供者**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。

1. 在导航窗格中，选择 **User Pools**（用户池），然后选择要编辑的用户池。

1. 选择**社交和外部提供商**菜单。

1. 选择要删除的 SAML IdPs 旁边的单选按钮。

1. 当系统提示您 **Delete identity provider**（删除身份提供者）时，请输入 SAML 提供商的名称以确认删除，然后选择 **Delete**（删除）。

# SAML 会话在 Amazon Cognito 用户池中启动
<a name="cognito-user-pools-SAML-session-initiation"></a>

Amazon Cognito 支持服务提供商发起（SP 发起）的单点登录（SSO）和 IdP 发起的 SSO。作为一项最佳安全实践，请在用户池中实施 SP 发起的 SSO。[SAML V2.0 技术概述](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0-cd-02.html#5.1.2.SP-Initiated%20SSO:%20%20Redirect/POST%20Bindings|outline)的第 5.1.2 节描述了 SP 启动的 SSO。Amazon Cognito 是您的应用程序的身份提供者 (IdP)。该应用程序是为经过身份验证的用户检索令牌的服务提供程序 (SP)。但是，当您使用第三方 IdP 对用户进行身份验证时，Amazon Cognito 就是 SP。SAML 2.0 用户使用 SP 发起的流程进行身份验证时，他们始终必须先向 Amazon Cognito 发出请求并重定向到 IdP 进行身份验证。

对于某些企业使用案例，对内部应用程序的访问从企业 IdP 托管的控制面板上的书签开始。当用户选择书签时，IdP 会生成一个 SAML 响应并将其发送到 SP 以向应用程序验证用户身份。

您可以在用户池中配置 SAML IdP，以便支持 IdP 发起的 SSO。在支持 IdP 发起的身份验证时，因为 Amazon Cognito 不会通过 SAML 请求发起身份验证，所以 Amazon Cognito 无法验证它是否请求了收到的 SAML 响应。在 SP 发起的 SSO 中，Amazon Cognito 会设置状态参数，用以根据原始请求验证 SAML 响应。通过 SP 发起的登录，您还可以防止跨站点请求伪造（CSRF）攻击。

**Topics**
+ [实施 SP 发起的 SAML 登录](#cognito-user-pools-saml-idp-authentication)
+ [实施 IdP 发起的 SAML 登录](#cognito-user-pools-SAML-session-initiation-idp-initiation)

## 实施 SP 发起的 SAML 登录
<a name="cognito-user-pools-saml-idp-authentication"></a>

最佳做法是实现 service-provider-initiated（由 SP 发起的）用户池登录。Amazon Cognito 会启动用户的会话并将他们重定向到您的 IdP。使用这种方法，您可以更大限度地控制谁提出登录请求。在某些条件下，您也可以允许 IdP 发起的登录。

以下过程显示了用户如何通过 SAML 提供者完成 SP 发起的用户池登录。

![\[Amazon Cognito SP 发起的 SAML 登录的身份验证流程图。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/scenario-authentication-saml-stepbystep.png)


1. 您的用户在登录页面输入他们的电子邮件地址。要确定您的用户是否重定向到其 IdP，您可以在自定义构建的应用程序中收集他们的电子邮件地址，或者在 Web 视图中调用托管登录。

   您可以将托管登录页面配置为显示电子邮件地址列表 IdPs或提示输入电子邮件地址，然后将其与 SAML IdP 的标识符进行匹配。要提示输入电子邮件地址，请编辑您的托管登录品牌风格，然后在**基础**中找到**身份验证行为**，然后在**提供商显示**下，将**显示风格**设置为**域搜索输入**。

1. 您的应用程序调用您的用户池重定向端点，并请求使用与应用程序对应的客户端 ID 以及与用户对应的 IdP ID 进行会话。

1. Amazon Cognito 使用（可选择在 `AuthnRequest` 元素中[签署](cognito-user-pools-SAML-signing-encryption.md#cognito-user-pools-SAML-signing.title)的）SAML 请求将您的用户重定向到 IdP。

1. IdP 以交互方式或通过浏览器 Cookie 中记住的会话对用户进行身份验证。

1. IdP 使用其 POST 有效载荷中[可选的加密](cognito-user-pools-SAML-signing-encryption.md#cognito-user-pools-SAML-signing-encryption.title) SAML 断言将用户重定向到用户池 SAML 响应端点。
**注意**  
Amazon Cognito 会取消在 5 分钟内未收到响应的会话，并将用户重定向到托管登录。当您的用户遇到此结果时，他们会收到一条 `Something went wrong` 错误消息。

1. 在验证 SAML 断言并从响应中的声明[映射用户属性](cognito-user-pools-specifying-attribute-mapping.md#cognito-user-pools-specifying-attribute-mapping.title)后，Amazon Cognito 在用户池中内部创建或更新用户的配置文件。通常，您的用户池会向用户的浏览器会话返回授权码。

1. 您的用户向您的应用程序出示他们的授权码，您的应用程序会将该代码兑换 JSON 网络令牌 (JWTs)。

1. 应用程序接受并处理用户的 ID 令牌作为身份验证，使用其访问令牌生成对资源的授权请求，并存储他们的刷新令牌。

当用户进行身份验证并接收授权码授予时，用户池会返回 ID 令牌、访问令牌和刷新令牌。ID 令牌是基于 OIDC 的身份管理的身份验证对象。访问令牌是一个范围为 [OAuth 2.0](https://oauth.net/2/) 的授权对象。刷新令牌是在用户当前令牌到期时生成新 ID 令牌和访问令牌的对象。您可以在用户池应用程序客户端中配置用户令牌的持续时间。

您还可以选择刷新令牌的持续时间。用户的刷新令牌到期后，他们必须重新登录。如果他们通过 SAML IdP 进行身份验证，则用户的会话持续时间由其令牌的到期时间，而不是他们与 IdP 的会话到期时间来设置。您的应用程序必须存储每位用户的刷新令牌，并在刷新令牌到期时更新他们的会话。托管登录会在浏览器的 Cookie 中维持用户的会话，这个 Cookie 的有效期为 1 小时。

## 实施 IdP 发起的 SAML 登录
<a name="cognito-user-pools-SAML-session-initiation-idp-initiation"></a>

在为 IdP 发起的 SAML 2.0 登录配置身份提供者时，您可以向用户池域中的 `saml2/idpresponse` 端点提供 SAML 断言，而无需在 [对端点授权](authorization-endpoint.md) 启动会话。具有此配置的用户池接受从用户池外部身份提供者由 IdP 发起的 SAML 断言，前提是所请求的应用程序客户端支持这种断言。

![\[Amazon Cognito IdP 发起的 SAML 登录的身份验证流程图。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/scenario-authentication-saml-idpinit.png)


1. 用户请求使用您的应用程序进行 SAML 登录。

1. 您的应用程序调用浏览器或将用户重定向到其 SAML 提供商的登录页面。

1. IdP 以交互方式或通过浏览器 Cookie 中记住的会话对用户进行身份验证。

1. IdP 使用 POST 正文中的 SAML 断言或响应将用户重定向到您的应用程序。

1. 您的应用程序将 SAML 断言添加到您的用户池 `saml2/idpresponse` 端点请求的 POST 正文中。

1. Amazon Cognito 向您的用户发出授权码。

1. 您的用户向您的应用程序出示他们的授权码，您的应用程序会将该代码兑换 JSON 网络令牌 (JWTs)。

1. 应用程序接受并处理用户的 ID 令牌作为身份验证，使用其访问令牌生成对资源的授权请求，并存储他们的刷新令牌。

以下步骤描述了配置 IdP 发起的 SAML 2.0 提供者并使用它来登录的整个过程。

1. 创建或指定用户池和应用程序客户端。

1. 在您的用户池中创建 SAML 2.0 IdP。

1. 将您的 IdP 配置为支持 IdP 启动。IdP 发起的 SAML 引入了一些安全性考量，而其他 SSO 提供者没有涉及这些安全性考量。因此，您无法将非 SAML IdPs（包括用户池本身）添加到任何使用 SAML 提供商并通过 IDP 启动登录的应用程序客户端。

1. 将 IdP 发起的 SAML 提供者与用户池中的应用程序客户端关联。

1. 将您的用户引导至 SAML IdP 的登录页面并检索 SAML 断言。

1. 使用 SAML 断言将用户引导至用户池 `saml2/idpresponse` 端点。

1. 接收 JSON 网络令牌 (JWTs)。

要在用户池中接受未经请求的 SAML 断言，必须考虑其对应用程序安全性的影响。当您接受 IdP 发起的请求时，可能会出现请求欺骗和 CSRF 尝试情况。虽然用户池无法验证 IdP 发起的登录会话，但 Amazon Cognito 会验证请求参数和 SAML 断言。

此外，SAML 声明不得包含 `InResponseTo` 声明，并且必须在前 6 分钟内发出。

您必须使用 IdP 发起的 SAML 向您的 `/saml2/idpresponse` 提交请求。对于 SP 发起的请求和托管登录授权请求，您必须提供参数，将您请求的应用程序客户端、范围、重定向 URI 和其他详细信息标识为 `HTTP GET` 请求中的查询字符串参数。但是，对于 IdP 发起的 SAML 断言，必须将请求的详细信息的格式设置为 `HTTP POST` 请求正文中的 `RelayState` 参数。请求正文还必须包含您的 SAML 断言，作为 `SAMLResponse` 参数。

以下是 IdP 发起的 SAML 提供商的示例请求和响应。

```
POST /saml2/idpresponse HTTP/1.1
User-Agent: USER_AGENT
Accept: */*
Host: example.auth.us-east-1.amazoncognito.com
Content-Type: application/x-www-form-urlencoded

SAMLResponse=[Base64-encoded SAML assertion]&RelayState=identity_provider%3DMySAMLIdP%26client_id%3D1example23456789%26redirect_uri%3Dhttps%3A%2F%2Fwww.example.com%26response_type%3Dcode%26scope%3Demail%2Bopenid%2Bphone

HTTP/1.1 302 Found
Date: Wed, 06 Dec 2023 00:15:29 GMT
Content-Length: 0
x-amz-cognito-request-id: 8aba6eb5-fb54-4bc6-9368-c3878434f0fb
Location: https://www.example.com?code=[Authorization code]
```

------
#### [ AWS 管理控制台 ]

**为 IdP 发起的 SAML 配置 IdP**

1. 创建[用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)、[应用程序客户端](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-configuring-app-integration.html)和 SAML 身份提供者。

1. 取消所有社交和 OIDC 身份提供者与应用程序客户端的关联（如果已关联）。

1. 导航到用户池的**社交和外部提供商**菜单。

1. 编辑或添加 SAML 提供商。

1. 在 **IdP 发起的 SAML 登录**下，选择**接受 SP 发起和 IdP 发起的 SAML 断言**。

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

------
#### [ API/CLI ]

**为 IdP 发起的 SAML 配置 IdP**

使用[CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)或 [UpdateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html)API 请求中的`IDPInit`参数配置 IDP 启动的 SAML。以下是支持 IdP 发起的 SAML 的 IdP 的示例 `ProviderDetails`。

```
"ProviderDetails": { 
      "MetadataURL" : "https://myidp.example.com/saml/metadata",
      "IDPSignout" : "true",
      "RequestSigningAlgorithm" : "rsa-sha256",
      "EncryptedResponses" : "true",
      "IDPInit" : "true"
}
```

------

# 通过单点注销来注销 SAML 用户
<a name="cognito-user-pools-saml-idp-sign-out"></a>

Amazon Cognito 支持 SAML 2.0 [单点注销](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0-cd-02.html#5.3.Single%20Logout%20Profile|outline) (SLO)。 借助 SLO，当用户从您的用户池中注销时，您的应用程序可以从其 SAML 身份提供商 (IdPs) 中注销他们。这样，当用户想要再次登录应用程序时，他们必须使用其 SAML IdP 进行身份验证。如果不这样做，他们可能会因为在浏览器中有 IdP 或用户池 Cookie，所以无需提供凭证即可进入您的应用程序。

当您将 SAML IdP 配置为支持**注销流程**时，Amazon Cognito 会通过已签名的 SAML 注销请求将您的用户重定向到您的 IdP。Amazon Cognito 根据您的 IdP 元数据中的 `SingleLogoutService` URL 确定重定向位置。Amazon Cognito 使用您的用户池签名证书签署注销请求。

![\[Amazon Cognito SAML 注销的身份验证流程图。用户请求注销，然后 Amazon Cognito 通过 SAML 注销请求将他们重定向到其提供者。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/scenario-authentication-saml-sign-out.png)


当您将具有 SAML 会话的用户定向到您的用户池 `/logout` 端点时，Amazon Cognito 会将您的 SAML 用户通过以下请求重定向到 IdP 元数据中指定的 SLO 端点。

```
https://[SingleLogoutService endpoint]?
SAMLRequest=[encoded SAML request]&
RelayState=[RelayState]&
SigAlg=http://www.w3.org/2001/04/xmldsig-more#rsa-sha256&
Signature=[User pool RSA signature]
```

然后，您的用户使用来自其 IdP 的 `LogoutResponse` 返回到您的 `saml2/logout` 端点。您的 IdP 必须在 `HTTP POST` 请求中发送 `LogoutResponse`。然后，Amazon Cognito 会根据他们最初的注销请求将他们重定向到重定向目的地。

您的 SAML 提供者可能会发送包含多个 `AuthnStatement` 的 `LogoutResponse`。此类响应中第一个 `AuthnStatement` 中的 `sessionIndex` 必须与最初对用户进行身份验证的 SAML 响应中的 `sessionIndex` 匹配。如果 `sessionIndex` 在任何其他 `AuthnStatement` 中，则 Amazon Cognito 将无法识别会话，且您的用户不会注销。

------
#### [ AWS 管理控制台 ]

**配置 SAML 注销**

1. 创建[用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)、[应用程序客户端](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-configuring-app-integration.html)和 SAML IdP。

1. 创建或编辑 SAML 身份提供者时，在**身份提供者信息**下，选中名称为**添加注销流程**的复选框。

1. 从用户池的**社交和外部提供商**菜单中，选择您的 IdP 并找到**签名证书**。

1. 选择**以 .crt 格式下载证书**。

1. 将您的 SAML 提供者配置为支持 SAML 单点注销和请求签名，然后上传用户池签名证书。您的 IdP 必须重定向到用户池域中的 `/saml2/logout`。

------
#### [ API/CLI ]

**配置 SAML 注销**

使用[CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)或 [UpdateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html)API 请求的`IDPSignout`参数配置单次注销。以下是支持 SAML 单点注销的 IdP 的示例 `ProviderDetails`。

```
"ProviderDetails": { 
      "MetadataURL" : "https://myidp.example.com/saml/metadata",
      "IDPSignout" : "true",,
      "RequestSigningAlgorithm" : "rsa-sha256",
      "EncryptedResponses" : "true",
      "IDPInit" : "true"
}
```

------

# SAML 签名和加密
<a name="cognito-user-pools-SAML-signing-encryption"></a>

SAML 2.0 登录围绕着应用程序的用户作为其身份验证流程中的请求和响应的持有者来进行。您可能需要确保用户不会在传输过程中读取或修改这些 SAML 文档。为此，请将 SAML 签名和加密添加到用户池中的 SAML 身份提供商 (IdPs)。借助 SAML 签名，您的用户池可向 SAML 登录和注销请求添加签名。使用您的用户池公钥，IdP 可以验证它接收的是未经修改的 SAML 请求。然后，当您的 IdP 响应并将 SAML 断言传递给用户的浏览器会话时，IdP 可以加密该响应，这样用户就无法查看自己的属性和权限。

使用 SAML 签名和加密，用户池 SAML 操作期间的所有加密操作都必须使用 user-pool-provided Amazon Cognito 生成的密钥生成签名和密文。目前，无法将用户池配置为使用外部密钥签署请求或接受加密断言。

**注意**  
用户池证书有效期为 10 年。Amazon Cognito 每年都会为用户池生成一次新的签名和加密证书。请求签名证书时，Amazon Cognito 会返回最新的证书，并使用最新的签名证书来签署请求。IdP 可以使用任何未过期的用户池加密证书来加密 SAML 断言。之前的证书在整个有效期内继续有效，并且不同证书之间的公钥不会发生变化。作为一项最佳实践，请每年更新提供者配置中的证书。

**Topics**
+ [接受来自 IdP 的加密 SAML 响应](#cognito-user-pools-SAML-encryption)
+ [签署 SAML 请求](#cognito-user-pools-SAML-signing)

## 接受来自 IdP 的加密 SAML 响应
<a name="cognito-user-pools-SAML-encryption"></a>

当用户登录和注销时，Amazon Cognito 和您的 IdP 可以在 SAML 响应中保持机密性。Amazon Cognito 会向您在用户池中配置的每个外部 SAML 提供者分配一个公有-私有 RSA 密钥对和一个证书。为用户池 SAML 提供者启用响应加密时，必须将证书上传到支持加密 SAML 响应的 IdP。在您的 IdP 开始使用提供的密钥加密所有 SAML 断言之前，您的用户池与 SAML IdP 的连接无法正常工作。

下文概述了加密 SAML 登录的流程。

1. 您的用户开始登录并选择他们的 SAML IdP。

1. 您的用户池 [对端点授权](authorization-endpoint.md) 通过 SAML 登录请求将您的用户重定向到他们的 SAML IdP。您的用户池可以选择在此请求中附上签名，从而让 IdP 可以进行完整性验证。当您想要签署 SAML 请求时，必须将您的 IdP 配置为接受您的用户池使用签名证书中的公钥签署的请求。

1. SAML IdP 让您的用户登录并生成 SAML 响应。IdP 使用公钥对响应进行加密，并将用户重定向到用户池 `/saml2/idpresponse` 端点。IdP 必须按照 SAML 2.0 规范的定义对响应进行加密。有关更多信息，请参阅 [OASIS 安全断言标记语言（SAML）V2.0 的断言和协议](https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf)中的 `Element <EncryptedAssertion>`。

1. 用户池使用私钥解密 SAML 响应中的加密文字并让您的用户登录。

**重要**  
当您为用户池中的 SAML IdP 启用响应加密时，您的 IdP 必须使用该提供者特有的公钥对所有响应进行加密。Amazon Cognito 不接受来自您配置为支持加密的 SAML 外部 IdP 的未加密 SAML 响应。

用户池中的任何外部 SAML IdP 都可以支持响应加密，并且每个 IdP 都会收到自己的密钥对。

------
#### [ AWS 管理控制台 ]

**配置 SAML 响应加密**

1. 创建[用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)、[应用程序客户端](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-configuring-app-integration.html)和 SAML IdP。

1. 创建或编辑 SAML 身份提供者时，在**对请求进行签名并加密响应**下，选中名称为**需要此提供商的加密 SAML 断言**的复选框。

1. 从用户池的**社交和外部提供商**菜单中，选择您的 SAML IdP，然后选择**查看加密证书**。

1. 选择**以 .crt 格式下载证书**，然后将下载的文件提供给您的 SAML IdP。将您的 SAML IdP 配置为使用证书中的密钥加密 SAML 响应。

------
#### [ API/CLI ]

**配置 SAML 响应加密**

使用[CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)或 [UpdateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html)API 请求的`EncryptedResponses`参数配置响应加密。以下是支持请求签名的 IdP 的示例 `ProviderDetails`。

```
"ProviderDetails": { 
      "MetadataURL" : "https://myidp.example.com/saml/metadata",
      "IDPSignout" : "true",
      "RequestSigningAlgorithm" : "rsa-sha256",
      "EncryptedResponses" : "true",
      "IDPInit" : "true"
}
```

要从您的用户池中获取加密证书，请发出 [DescribeIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeIdentityProvider.html)API 请求并在响应参数`ActiveEncryptionCertificate`中检索的值`ProviderDetails`。保存此证书，并将其作为加密证书提供给您的 IdP，用于接收来自用户池的登录请求。

------

## 签署 SAML 请求
<a name="cognito-user-pools-SAML-signing"></a>

能够向您的 IdP 证明 SAML 2.0 请求的完整性是 Amazon Cognito SP 发起的 SAML 登录的一项安全优势。每个拥有域的用户池都会收到一个用户池 X.509 签名证书。使用此证书中的公钥，用户池将加密签名应用于在用户选择 SAML IdP 时用户池生成的*注销请求*。您可以选择将应用程序客户端配置为签署 SAML *登录请求*。当您签署 SAML 请求时，您的 IdP 会核实请求的 XML 元数据中的签名是否与您提供的用户池证书中的公钥相匹配。

------
#### [ AWS 管理控制台 ]

**配置 SAML 请求签名**

1. 创建[用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)、[应用程序客户端](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-configuring-app-integration.html)和 SAML IdP。

1. 创建或编辑 SAML 身份提供者时，在**对请求进行签名并加密响应**下，选中名称为**对此提供商的 SAML 请求进行签名**的复选框。

1. 从用户池的**社交和外部提供商**菜单中，选择**查看签名证书**。

1. 选择**以 .crt 格式下载证书**，然后将下载的文件提供给您的 SAML IdP。配置 SAML IdP 以验证传入 SAML 请求的签名。

------
#### [ API/CLI ]

**配置 SAML 请求签名**

使用[CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)或 [UpdateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html)API 请求的`RequestSigningAlgorithm`参数配置请求签名。以下是支持请求签名的 IdP 的示例 `ProviderDetails`。

```
"ProviderDetails": { 
      "MetadataURL" : "https://myidp.example.com/saml/metadata",
      "IDPSignout" : "true",
      "RequestSigningAlgorithm" : "rsa-sha256",
      "EncryptedResponses" : "true",
      "IDPInit" : "true"
}
```

------

# SAML 身份提供者名称和标识符
<a name="cognito-user-pools-managing-saml-idp-naming"></a>

当您命名您的 SAML 身份提供商 (IdPs) 并分配 IdP 标识符时，您可以自动将 SP 发起的登录和注销请求流向该提供商。有关提供商名称的字符串约束的信息，请参阅的`ProviderName`属性[CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html#CognitoUserPools-CreateIdentityProvider-request-ProviderName)。

![\[使用 IdP 标识符和托管登录的 Amazon Cognito SP 发起的 SAML 登录的身份验证流程图。用户向托管登录提供电子邮件地址，Amazon Cognito 会自动将他们重定向到其提供者。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/scenario-authentication-saml-identifier.png)


您还可以为 SAML 提供商选择最多 50 个标识符。标识符是用户池中 IdP 的友好名称，并且在用户池中必须是唯一的。如果您的 SAML 标识符与用户的电子邮件域匹配，托管登录会请求每个用户的电子邮件地址，评估其电子邮件地址中的域，然后将他们重定向到与其域对应的 IdP。由于同一个组织可以拥有多个域，因此单个 IdP 可以有多个标识符。

无论您是使用还是不使用电子邮件域标识符，您都可以在多租户应用程序中使用标识符将用户重定向到正确的 IdP。当您想完全绕过托管登录时，可以自定义向用户提供的链接，这样他们就可以通过 [对端点授权](authorization-endpoint.md) 直接重定向到他们的 IdP。要使用标识符使您的用户登录并重定向到他们的 IdP，请在其初始授权请求的请求参数中包括 `idp_identifier=myidp.example.com` 格式的标识符。

将用户传递到 IdP 的另一种方法是使用以下 URL 格式的 IdP 名称填充参数 `identity_provider`。

```
https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?
response_type=code&
identity_provider=MySAMLIdP&
client_id=1example23456789&
redirect_uri=https://www.example.com
```

用户使用您的 SAML IdP 登录后，您的 IdP 会将他们重定向到您的 `/saml2/idpresponse` 端点，并在 `HTTP POST` 正文中包括一个 SAML 响应。Amazon Cognito 会处理 SAML 断言，如果响应中的声明符合预期，则会重定向到您的应用程序客户端回调 URL。在用户以这种方式完成身份验证后，他们只与您的 IdP 和您的应用程序的网页进行交互。

使用域格式的 IdP 标识符，托管登录会在登录时请求电子邮件地址，然后，当电子邮件域与 IdP 标识符匹配时，将用户重定向到其 IdP 的登录页面。例如，您构建一个需要两家不同公司的员工登录的应用程序。第一家公司 AnyCompany A 拥有`exampleA.com`和`exampleA.co.uk`。第二家公司 AnyCompany B 拥有`exampleB.com`。在本示例中，您设置了两个 IdPs，每家公司一个，如下所示：
+ 对于 IdP A，您定义标识符 `exampleA.com` 和 `exampleA.co.uk`。
+ 对于 IdP B，您定义标识符 `exampleB.com`。

在您的应用程序中，调用应用程序客户端的托管登录，提示每位用户输入其电子邮件地址。Amazon Cognito 根据电子邮件地址得出域，将该域与具有域标识符的 IdP 关联起来，然后通过向包含 `idp_identifier` 请求参数的 [对端点授权](authorization-endpoint.md) 发出请求，将您的用户重定向到正确的 IdP。例如，如果用户输入 `bob@exampleA.co.uk`，则他们与之交互的下一个页面是位于 `https://auth.exampleA.co.uk/sso/saml` 的 IdP 登录页面。

您也可以独立实施相同的逻辑。在您的应用程序中，您可以构建一个自定义表单，用于收集用户输入并根据自己的逻辑将其与正确的 IdP 关联起来。您可为每个应用程序租户生成自定义门户，其中每个租户都通过请求参数中的租户标识符链接到授权端点。

要在托管登录中收集电子邮件地址并解析域，请为您分配给应用程序客户端的每个 SAML IdP 至少分配一个标识符。默认情况下，托管登录屏幕会针对您分配给应用程序客户端 IdPs的每个登录显示一个按钮。但如果您已成功分配标识符，则经典托管 UI 登录页面将如下图所示。

![\[Amazon Cognito 托管登录的登录页面，显示本地用户登录和要求联合用户输入电子邮件地址的提示。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/cup-saml-identifiers.png)


**注意**  
在经典托管用户界面中，当您为应用程序客户端分配标识符时，应用程序客户端的登录页面会自动提示您输入电子邮件地址。 IdPs在托管登录体验中，您必须在品牌编辑器中启用此行为。在**身份验证行为**设置类别中，在**提供商显示**标题下选择**域搜索输入**。

在托管登录中解析域时，要求使用域作为 IdP 标识符。如果您为应用程序客户端的每个 SAML IdPs 分配了任何类型的标识符，则该应用程序的托管登录将不再显示 IDP 选择按钮。当您打算使用电子邮件解析或自定义逻辑生成重定向时，请为 SAML 添加 IdP 标识符。如果您想生成静默重定向，同时希望托管登录页面显示列表，请不要分配标识符 IdPs，也不要在授权`identity_provider`请求中使用请求参数。
+ 如果您仅将一个 SAML IdP 分配给您的应用程序客户端，则托管登录的登录页面会显示一个用于使用该 IdP 登录的按钮。
+ 如果您向为应用程序客户端激活的每个 SAML IdP 分配一个标识符，则在托管登录的登录页面中会出现要求用户输入电子邮件地址的提示。
+ 如果您有多个 IdPs ，但没有为所有用户分配标识符，则托管登录页面会显示一个按钮，用于使用每个分配的 IdP 进行登录。
+ 如果您为自己分配了标识符， IdPs 并且希望托管登录页面显示精选的 IdP 按钮，请向您的应用程序客户端添加一个没有标识符的新 IdP，或者创建一个新的应用程序客户端。您也可以删除现有 IdP，然后在没有标识符的情况下重新添加它。如果您创建新的 IdP，则您的 SAML 用户将创建新的用户配置文件。活跃用户的重复计数可能会在您更改 IdP 配置的当月对账单产生影响。

有关 IdP 设置的更多信息，请参阅[为用户池配置身份提供者](cognito-user-pools-identity-provider.md)。

# 将 OIDC 身份提供者与用户池配合使用
<a name="cognito-user-pools-oidc-idp"></a>

用户可以使用 OpenID Connect (OIDC) 身份提供商 () 提供的现有账户登录您的应用程序。IdPs借助 OIDC 提供者，独立单点登录系统的用户可以提供现有凭证，同时您的应用程序以用户池共享格式接收 OIDC 令牌。要配置 OIDC IdP，请将您的 IdP 设置为将用户池作为 RP 处理，并将应用程序配置为将用户池作为 IdP 处理。Amazon Cognito 是多个 OIDC IdPs 和您的应用程序之间的中间步骤。用户池将属性映射规则应用于提供者直接传递给用户池的 ID 和访问令牌中的声明。然后，Amazon Cognito 会根据映射的用户属性以及您使用 [Lambda 触发器](cognito-user-pools-working-with-lambda-triggers.md#lambda-triggers-for-federated-users)对身份验证流程所做的任何其他调整来发出新令牌。

使用 OIDC IdP 登录的用户无需提供新的凭证或信息即可访问您的用户池应用程序。您的应用程序可以静默地将他们重定向到其 IdP 进行登录，在后台使用用户池作为工具，用于标准化应用程序的令牌格式。要了解有关 IdP 重定向的更多信息，请参阅[对端点授权](authorization-endpoint.md)。

与其他第三方身份提供者一样，您必须向 OIDC 提供者注册您的应用程序，并获取有关要连接到用户池的 IdP 应用程序的信息。用户池 OIDC IdP 需要客户端 ID、客户端密钥、您要请求的范围以及有关提供者服务端点的信息。您的用户池可以从发现端点发现提供者 OIDC 端点，也可以手动输入它们。您还必须检查提供者 ID 令牌，并在 IdP 和用户池中的属性之间创建属性映射。

![\[用户池 OIDC IdP 身份验证流程\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/flow-cup-oidc-endpoints.png)


有关此身份验证流程的更多详细信息，请参阅 [OIDC 用户池 IdP 身份验证流程](cognito-user-pools-oidc-flow.md)。

**注意**  
通过第三方（联合身份验证）进行登录可在 Amazon Cognito 用户池中实现。此特征不依赖于通过 Amazon Cognito 身份池实现的 OIDC 联合身份验证。

您可以通过 AWS 管理控制台、或使用用户池 API 方法将 OIDC IdP 添加到您的用户池中。 AWS CLI[CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)

**Topics**
+ [先决条件](#cognito-user-pools-oidc-idp-prerequisites)
+ [向 OIDC IdP 注册应用程序](#cognito-user-pools-oidc-idp-step-1)
+ [将 OIDC IdP 添加到用户池](#cognito-user-pools-oidc-idp-step-2)
+ [测试 OIDC IdP 配置](#cognito-user-pools-oidc-idp-step-3)
+ [OIDC 用户池 IdP 身份验证流程](cognito-user-pools-oidc-flow.md)

## 先决条件
<a name="cognito-user-pools-oidc-idp-prerequisites"></a>

在开始之前，您需要：
+ 具有应用程序客户端和用户池域的用户池。有关更多信息，请参阅[创建用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。
+ 具有以下配置的 OIDC IdP：
  + 支持 `client_secret_post` 客户端身份验证。Amazon Cognito 不在 IdP 的 OIDC 发现端点上检查 `token_endpoint_auth_methods_supported` 声明。Amazon Cognito 不支持 `client_secret_basic` 客户端身份验证。有关客户端验证的更多信息，请参阅 OpenID Connect 文档中的[客户端身份验证](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication)。
  + 仅对 OIDC 端点使用 HTTPS，例如 `openid_configuration`、`userInfo` 和 `jwks_uri`。
  + 仅为 OIDC 端点使用 TCP 端口 80 和 443。
  + 只能使用 HMAC-SHA、ECDSA 或 RSA 算法对 ID 令牌进行签名。
  + 在密钥的 `jwks_uri` 处发布密钥 ID `kid` 声明，并在其令牌中包含 `kid` 声明。
  + 提供具有有效根 CA 信任链的未过期公钥。

## 向 OIDC IdP 注册应用程序
<a name="cognito-user-pools-oidc-idp-step-1"></a>

在将 OIDC IdP 添加到用户池配置并将其分配给应用程序客户端之前，您需要在 IdP 中设置一个 OIDC 客户端应用程序。您的用户池是用于管理您的 IdP 身份验证的依赖方应用程序。

**向 OIDC IdP 注册**

1. 使用 OIDC IdP 创建开发人员账户。  
**指向 OIDC 的链接 IdPs**    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/cognito-user-pools-oidc-idp.html)

1. 向 OIDC IdP 注册具有 `/oauth2/idpresponse` 端点的用户池域 URL。这将确保 OIDC IdP 之后在对用户进行身份验证时通过 Amazon Cognito 接受此 URL。

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/idpresponse
   ```

1. 选择您希望用户目录与用户池共享的[范围](cognito-user-pools-define-resource-servers.md#cognito-user-pools-define-resource-servers-about-scopes)。**OIDC 需要使用作用域 openid** IdPs 才能提供任何用户信息。需要使用 `email` 范围才能授予对 `email` 和 `email_verified` [声明](https://openid.net/specs/openid-connect-basic-1_0.html#StandardClaims)的访问权限。OIDC 规范中的其他范围是适用于所有用户属性的 `profile` 以及适用于 `phone_number` 和 `phone_number_verified` 的 `phone`。

1. OIDC IdP 为您提供客户端 ID 和客户端密钥。请记下这些值并将其添加到稍后添加到用户池的 OIDC IdP 的配置中。

**示例：使用 Salesforce 作为用户池的 OIDC IdP**

 当您要在与 OIDC 兼容的 IdP（如 Salesforce）和您的用户池之间建立信任时，请使用 OIDC IdP。

1. 在 Salesforce 开发人员网站上[创建账户](https://developer.salesforce.com/signup)。

1. [通过在上一步中设置的开发人员账户登录。](https://developer.salesforce.com)

1. 请在 Salesforce 页面上，执行以下操作之一：
   +  如果您使用的是 Lightning Experience，请选择设置齿轮图标，然后选择 **Setup Home**（设置主页）。
   +  如果您使用的是 Salesforce Classic 并且在用户界面标题中看到 **Setup**（设置），请选择它。
   +  如果您使用的是 Salesforce Classic 但没有在用户界面标题中看到 **Setup**（设置），请从顶部导航栏中选择您的姓名，然后从下拉列表中选择 **Setup**（设置）。

1. 在左侧导航栏上，选择 **Company Settings**（公司设置）。

1. 在导航栏上，选择**域**，输入一个域，然后选择**创建**。

1. 在左侧导航栏上，选择在 **Platform Tools**（平台工具）下的 **Apps**（应用程序）。

1. 选择 **App Manager**（应用程序管理器）。

1. 

   1. 选择 **New connected app**（新连接的应用程序）。

   1. 完成必填句段。

      在 **Start URL**（启动 URL）下，在 `/authorize` 终端节点处输入使用您的 Salesforce IdP 登录的用户池域的 URL。当您的用户访问您连接的应用程序时，Salesforce 会将他们定向到此 URL 以完成登录。然后 Salesforce 将用户重定向到与应用程序客户端关联的回调 URL。

      ```
      https://mydomain.auth.us-east-1.amazoncognito.com/authorize?response_type=code&client_id=<your_client_id>&redirect_uri=https://www.example.com&identity_provider=CorpSalesforce
      ```

   1. 启用**OAuth 设置**并在**回调 URL 中输入您的用户池域的`/oauth2/idpresponse`终端节点 URL**。这是 Salesforce 发布授权码的网址，Amazon Cognito 用该代码兑换令牌。 OAuth 

      ```
      https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/idpresponse
      ```

1. 选择 [scopes](https://openid.net/specs/openid-connect-basic-1_0.html#Scopes)（范围）。您必须包含范围 **openid**。要授予对 **email** 和 **email\$1verified** [声明](https://openid.net/specs/openid-connect-basic-1_0.html#StandardClaims)的访问权限，请添加**电子邮件**范围。通过空格分隔范围。

1. 选择 **Create**（创建）。

   在 Salesforce 中，客户端 ID 称为 **Consumer Key**（使用者密钥），客户端密钥为 **Consumer Secret**（使用者私有密钥）。记下您的客户端 ID 和客户端密钥。您将在下一节中使用它们。

## 将 OIDC IdP 添加到用户池
<a name="cognito-user-pools-oidc-idp-step-2"></a>

设置 IdP 后，您可以将用户池配置为使用 OIDC IdP 处理身份验证请求。

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

**在控制台中添加 OIDC IdP**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入 AWS 凭证。

1. 从导航菜单中选择 **User Pools**（用户池）。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**社交和外部提供商**菜单，然后选择**添加身份提供者**。

1. 选择一个 **OpenID Connect** IdP。

1. 输入唯一的**提供商名称**。

1. 输入 IdP **客户端 ID**。这是您在 OIDC IdP 中构建的应用程序客户端的 ID。您提供的客户端 ID 必须是您使用回调 URL `https://[your user pool domain]/oauth2/idpresponse` 配置的 OIDC 提供商。

1. 输入 IdP **客户端密钥**。它必须是针对上一步中同一应用程序客户端的客户端密钥。

1. <a name="cognito-user-pools-oidc-step-2-substep-9"></a>为该提供商输入 **Authorized scopes**（授权范围）。范围定义了应用程序将向您的提供商请求的用户属性组（例如 `name` 和 `email`）。按照 [OAuth2.0](https://tools.ietf.org/html/rfc6749#section-3.3) 规范，作用域必须用空格分隔。

   您的 IdP 可能会提示用户在登录时同意向您的应用程序提供这些属性。

1. 选择**属性请求方法**。 IdPs可能需要将其`userInfo`终端节点的请求格式设置为`GET`或`POST`。例如，Amazon Cognito `userInfo` 端点需要采用 `HTTP GET` 请求。

1. 选择**设置方法**，将其作为您希望用户池确定 IdP 处关键 OIDC 联合身份验证端点路径的方式。通常，在颁发者基本 URL 上 IdPs 托管`/well-known/openid-configuration`终端节点。如果您的提供者属于这种情况，则**自动填写发布者 URL** 选项会提示您输入该基本 URL，尝试从这里访问 `/well-known/openid-configuration` 路径，然后读取这里列出的端点。您可能具有非典型端点路径，或者希望通过备用代理将请求传递到一个或多个端点。在这种情况下，请选择**手动输入**并指定 `authorization`、`token`、`userInfo` 和 `jwks_uri` 端点的路径。
**注意**  
URL 应该以 `https://` 开头，并且不应以下斜杠 `/` 结尾。只有端口号 443 和 80 可用于此 URL。例如，Salesforce 使用以下 URL：  
`https://login.salesforce.com`   
如果选择自动填充，则发现文档必须对以下值使用 HTTPS：`authorization_endpoint`、`token_endpoint`、`userinfo_endpoint` 和 `jwks_uri`。否则，登录将失败。

1. 在 **OpenID Connect 提供者和用户池之间映射属性**下配置属性映射规则。**用户池属性**是 Amazon Cognito 用户配置文件中的*目标*属性，**OpenID Connect 属性**是您希望 Amazon Cognito 在 ID 令牌声明或 `userInfo` 响应中找到的*源*属性。Amazon Cognito 会自动将 **sub** OIDC 声明映射到目标用户配置文件中的 `username`。

   有关更多信息，请参阅 [将 IdP 属性映射到配置文件和令牌](cognito-user-pools-specifying-attribute-mapping.md)。

1. 选择**添加身份提供者**。

1. 在**应用程序客户端**菜单中，从列表中选择一个应用程序客户端。导航到**登录页面**选项卡，然后在**托管登录页面配置**下选择**编辑**。找到**身份提供者**并添加新 OIDC IdP。

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

------
#### [ API/CLI ]

请参阅示例二中的 OIDC 配置，网址为。[CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html#API_CreateIdentityProvider_Example_2)您可以修改此语法并将其用作`CreateIdentityProvider``UpdateIdentityProvider`、的请求正文或的`--cli-input-json`输入文件[create-identity-provider](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/create-identity-provider.html)。

------

## 测试 OIDC IdP 配置
<a name="cognito-user-pools-oidc-idp-step-3"></a>

在您的应用程序中，您必须在用户的客户端中调用浏览器，这样他们才能使用其 OIDC 提供商登录。完成前几节中的设置过程后，使用提供商测试登录。以下示例 URL 通过前缀域加载用户池的登录页面。

```
https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?response_type=code&client_id=1example23456789&redirect_uri=https://www.example.com
```

此链接是当您转到**应用程序客户端**菜单，选择应用程序客户端，导航到**登录页面**选项卡，然后选择**查看登录页面**时，Amazon Cognito 将您引导至的页面。有关用户池域的更多信息，请参阅 [配置用户池域](cognito-user-pools-assign-domain.md)。有关应用程序客户端（包括客户端 IDs 和回调）的更多信息 URLs，请参阅[特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。

以下示例链接通过 `identity_provider` 查询参数设置从[对端点授权](authorization-endpoint.md)到 `MyOIDCIdP` 提供者的静默重定向。此 URL 会绕过使用托管登录的交互式用户池登录，直接转到 IdP 登录页面。

```
https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?identity_provider=MyOIDCIdP&response_type=code&client_id=1example23456789&redirect_uri=https://www.example.com
```

# OIDC 用户池 IdP 身份验证流程
<a name="cognito-user-pools-oidc-flow"></a>

通过 OpenID Connect（OIDC）登录，您的用户池会自动执行身份提供者（IdP）的授权码登录流程。您的用户使用其 IdP 完成登录后，Amazon Cognito 会在外部提供商的 `oauth2/idpresponse` 端点收集他们的代码。借助生成的访问令牌，您的用户池查询 IdP `userInfo` 端点以检索用户属性。然后，您的用户池将收到的属性与您设置的属性映射规则进行比较，并相应地填入用户的配置文件和 ID 令牌。

您在 OIDC 提供商配置中请求的 OAuth 2.0 范围定义了 IdP 向 Amazon Cognito 提供的用户属性。作为一项最佳安全实践，请仅请求与要映射到用户池的属性相对应的范围。例如，如果您的用户池请求 `openid profile`，您将获得所有可能的属性，但是如果您请求 `openid email phone_number`，则只能获得用户的电子邮件地址和电话号码。您可以将向 [OIDC 请求的](cognito-user-pools-oidc-idp.md#cognito-user-pools-oidc-step-2-substep-9)范围配置 IdPs为与您在[应用程序客户端](user-pool-settings-client-apps.md#user-pool-settings-client-apps-scopes)和用户池身份验证请求中授权和请求的范围不同。

当您的用户使用 OIDC IdP 登录您的应用程序时，您的用户池执行以下身份验证流程。

1. 用户访问您的托管登录页面，并选择使用其 OIDC IdP 登录。

1. 您的应用程序将用户的浏览器定向到用户池的授权端点。

1. 您的用户池将请求重定向到 OIDC IdP 的授权端点。

1. 您的 IdP 显示登录提示。

1. 在您的应用程序中，用户会话显示 OIDC IdP 的登录提示。

1. 用户输入他们的 IdP 凭证，或者为已通过身份验证的会话提供 cookie。

1. 在您的用户进行身份验证后，OIDC IdP 将使用授权代码重定向至 Amazon Cognito。

1. 用户池将授权码交换为 ID 和访问令牌。当您将 IdP 配置为范围 `openid` 时，Amazon Cognito 将接收访问令牌。ID 令牌中的声明和 `userInfo` 响应由 IdP 配置中的其他范围确定，例如 `profile` 和 `email`。

1. 您的 IdP 发放请求的令牌。

1. 您的用户池 URLs 在您的 IdP 配置中确定颁发者到 IdP `jwks_uri` 终端节点的路径，并从 JSON 网络密钥集 (JWKS) 端点请求令牌签名密钥。

1. IdP 从 JWKS 端点返回签名密钥。

1. 用户池根据令牌中的签名和到期数据验证 IdP 令牌。

1. 用户池使用访问令牌授权向 IdP `userInfo` 端点的请求。IdP 根据访问令牌范围使用用户数据进行响应。

1. 用户池将 ID 令牌和 IdP 的 `userInfo` 响应与用户池中的属性映射规则进行比较。这样会将映射的 IdP 属性写入用户池配置文件属性。

1. Amazon Cognito 颁发应用程序持有者令牌，可能包括身份令牌、访问令牌和刷新令牌。

1. 您的应用程序处理用户池令牌并将用户登录。

![\[用户池 OIDC IdP 身份验证流程\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/flow-cup-oidc-endpoints.png)


**注意**  
Amazon Cognito 会取消未在 5 分钟内完成的身份验证请求，并将用户重定向到托管登录。页面随即显示 `Something went wrong` 错误消息。

OIDC 是 OAuth 2.0 之上的身份层，它指定由 IdPs OIDC 客户端应用程序（依赖方）颁发的 JSON 格式 (JWT) 身份令牌。有关将 Amazon Cognito 添加为 OIDC 信赖方的信息，请参阅适用于您 OIDC IdP 的文档。

当用户使用授权码授予进行身份验证时，用户池将返回 ID、访问权限和刷新令牌。ID 令牌是用于身份管理的标准 [OIDC](http://openid.net/specs/openid-connect-core-1_0.html) 令牌，访问令牌是标准 [OAuth 2.0](https://oauth.net/2/) 令牌。有关您的用户池应用程序客户端可以支持的授权类型的更多信息，请参阅[对端点授权](authorization-endpoint.md)。

## 用户群体如何处理来自 OIDC 提供者的声明
<a name="how-a-cognito-user-pool-processes-claims-from-an-oidc-provider"></a>

当用户通过第三方 OIDC 提供者完成登录时，托管登录会从 IdP 检索授权码。用户池会与 IdP 的 `token` 端点交换访问令牌和 ID 令牌的授权码。用户池不会将这些令牌传递给用户或应用程序，而是使用它们来构建用户配置文件，其中包含用户池在声明中以其自己的令牌表示的数据。

 Amazon Cognito 不会独立验证访问令牌。相反，它会从提供者 `userInfo` 端点请求用户属性信息，如果令牌无效，则该请求会被拒绝。

Amazon Cognito 通过以下检查来验证提供者 ID 令牌：

1. 检查提供者是否使用以下集合中的算法对令牌进行了签名：RSA、HMAC、椭圆曲线。

1. 如果提供者使用非对称签名算法对令牌进行了签名，请检查令牌 `kid` 声明中的签名密钥 ID 是否在提供者 `jwks_uri` 端点上列出。Amazon Cognito 会为其处理的每个 IdP ID 令牌刷新 IdP 配置中的 JWKS 端点的签名密钥。

1. 根据提供者元数据，将 ID 令牌签名与预期的签名进行比较。

1. 将 `iss` 声明与为 IdP 配置的 OIDC 颁发者进行比较。

1. 比较 `aud` 声明是否与在 IdP 上配置的客户端 ID 相匹配，或者，如果 `aud` 声明中有多个值，则声明包含所配置的客户端 ID。

1. 检查 `exp` 声明中的时间戳不早于当前时间。

用户池会验证 ID 令牌，然后尝试使用提供者访问令牌向提供者 `userInfo` 端点发出请求。此请求检索访问令牌中的范围授权它读取的任何用户配置文件信息。然后，用户池将搜索您在用户池中根据需要设置的用户属性。您必须在提供者配置中为必需的属性创建属性映射。用户池会检查提供者 ID 令牌和 `userInfo` 响应。用户池将所有与映射规则匹配的声明写入用户池用户配置文件中的用户属性。用户池会忽略与映射规则匹配、但不是必需且在提供者的声明中找不到的属性。

# 将 IdP 属性映射到配置文件和令牌
<a name="cognito-user-pools-specifying-attribute-mapping"></a>

身份提供者（IdP）服务（包括 Amazon Cognito）通常可以记录有关用户的更多信息。您可能想知道他们在哪家公司工作、如何联系他们以及其他可供识别的信息。但是，这些属性的格式在不同的提供者之间存在差异。例如，使用您的用户池设置 IdPs 来自三个不同供应商的三个供应商，并检查每个供应商的 SAML 断言、ID 令牌或`userInfo`负载示例。其中一个 IdP 将用户的电子邮件地址表示为 `email`，另一个表示为 `emailaddress`，第三个表示为 `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`。

 IdPs 与用户池整合带来的一个主要好处是，能够将各种属性名称映射到具有一致、可预测的共享属性名称的单个 OIDC 令牌架构中。这样，您的开发人员就无需维护处理各种复杂单点登录事件的逻辑。这种格式整合就是属性映射。用户池属性映射将 IdP 属性名称分配给相应的用户池属性名称。例如，您可以将用户池配置为将 `emailaddress` 声明的值写入标准用户池属性 `email`。

每个用户池 IdP 都有单独的属性映射架构。要为您的 IdP 指定属性映射，请在 Amazon Cognito 控制台、 AWS SDK 或用户池 REST API 中配置用户池身份提供者。

## 有关映射的需知信息
<a name="cognito-user-pools-specifying-attribute-mapping-requirements"></a>

在开始设置用户属性映射之前，请查看以下重要详细信息。
+ 当联合用户登录到您的应用程序时，您的用户池需要的每个用户池属性都必须存在一个映射。例如，如果您的用户池需要 `email` 属性来进行注册，则将此属性映射到 IdP 中的对等属性。
+ 默认情况下，映射的电子邮件地址未经验证。您无法使用一次性代码验证映射的电子邮件地址。而是要映射 IdP 的属性来获取验证状态。例如，Google 和大多数 OIDC 提供商都包含 `email_verified` 属性。
+ 您可以将身份提供者（IdP）令牌映射到用户池中的自定义属性。社交提供者提供访问令牌，而 OIDC 提供者提供访问令牌和 ID 令牌。要映射令牌，请添加一个最大长度为 2048 个字符的自定义属性，向您的应用程序客户端授予对该属性的写入权限，然后将 `access_token` 或 `id_token` 从 IdP 映射到自定义属性。
+ 对于每个映射的用户池属性，最大值长度 2048 个字符必须足够大，才能容纳 Amazon Cognito 从 IdP 处获取的值。否则，当用户登录到您的应用程序时，Amazon Cognito 会报告错误。当令牌长度超过 2048 个字符时，Amazon Cognito 不支持将 IdP 令牌映射到自定义属性。
+ Amazon Cognito 从联合身份验证 IdP 传递的特定声明中派生出联合用户配置文件中的 `username` 属性，如下表所示。Amazon Cognito 在此属性值前面加上 IdP 的名称，例如 `MyOIDCIdP_[sub]`。当您希望联合用户拥有与外部用户目录中的属性完全匹配的属性时，请将该属性映射到 Amazon Cognito 登录属性，如 `preferred_username`。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/cognito-user-pools-specifying-attribute-mapping.html)
+ 当用户池[不区分大小写](user-pool-case-sensitivity.md)时，Amazon Cognito 会将联合用户自动生成的用户名中的用户名源属性转换为小写字母。以下是区分大小写的用户池的示例用户名：`MySAML_TestUser@example.com`。以下是*不区分大小写*的用户池的相同用户名：`MySAML_testuser@example.com`。

  在不区分大小写的用户池中，处理用户名的 Lambda 触发器必须考虑到对任何混合大小写的声明进行的这种修改，以适应用户名称源属性。要将您的 IdP 链接到区分大小写设置与当前用户池不同的用户池，请创建一个新的用户池。
+ 当用户登录您的应用程序时，Amazon Cognito 必须能够更新映射的用户池属性。用户通过某个 IdP 登录时，Amazon Cognito 将使用来自该 IdP 的最新信息更新映射的属性。Amazon Cognito 仅在映射的属性的值发生变化时才对其进行更新。要确保 Amazon Cognito 可以更新属性，请检查以下要求：
  + 您从 IdP 映射的所有用户池自定义属性都必须为*可变的*。您可以随时更新可变的自定义属性。相比之下，只有在首次创建用户配置文件时，才能为用户的*不可变* 自定义属性设置值。要在 Amazon Cognito 控制台中创建可变的自定义属性，请在**注册**菜单中选择**添加自定义属性**时，为您添加的属性激活**可变**复选框。或者，如果您使用 [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)API 操作创建用户池，则可以将每个属性的`Mutable`参数设置为`true`。如果您的 IdP 为映射的不可变属性发送一个值，Amazon Cognito 会返回错误且登录失败。
  + 在应用程序的应用程序客户端设置中，映射的属性必须*可写*。您可以在 Amazon Cognito 控制台的 **App clients (应用程序客户端)** 页面中设置哪些属性为可写属性。或者，如果您使用 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html) API 操作创建应用程序客户端，则可以将这些属性添加到 `WriteAttributes` 数组。如果您的 IdP 为映射的不可写属性发送一个值，Amazon Cognito 不会设置该属性值，而是继续进行身份验证。
+ 当 IdP 属性包含多个值时，Amazon Cognito 会将所有值扁平化为一个以逗号分隔的字符串，并用方括号字符 `[` 和 `]` 将其括起来。Amazon Cognito 对包含除 `.`、`-`、`*` 和 `_` 之外的非字母数字字符的值进行 URL 格式编码。在您的应用程序中使用这些值之前，您必须解码并解析各个值。
+ 目标属性会保留属性映射规则分配给它的任何值，除非登录或管理操作对其进行了更改。当不再在提供者令牌或 SAML 断言中发送源属性时，Amazon Cognito 不会从用户处移除属性。以下操作会从联合用户的用户池配置文件中移除属性的值：

  1. IdP 为源属性发送空值，并且映射规则将该空值应用于目标属性。

  1. 您可以使用[DeleteUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUserAttributes.html)或[AdminDeleteUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDeleteUserAttributes.html)请求清除映射属性的值。

## 指定适用于用户池的身份提供者属性映射（AWS 管理控制台）
<a name="cognito-user-pools-specifying-attribute-mapping-console"></a>

您可以使用为您的用户 AWS 管理控制台 池的 IdP 指定属性映射。

**注意**  
只有当陈述存在于传入令牌中时，Amazon Cognito 才会将传入陈述映射到用户池属性。如果之前映射的声明不再存在于传入令牌中，则不会被删除或更改。如果您的应用程序需要映射已删除的声明，则可以使用预身份验证 Lambda 触发器在身份验证期间删除自定义属性，并允许从传入令牌重新填充这些属性。

**指定社交 IdP 属性映射**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 在导航窗格中，选择 **用户池**，然后选择要编辑的用户池。

1. 选择**社交和外部提供商**菜单。

1. 选择**添加身份提供者**，或者选择您已配置的 **Facebook**、**Google**、**Amazon** 或 **Apple** IdP。找到 **Attribute mapping**（属性映射），然后选择 **Edit**（编辑）。

   有关添加社交 IdP 的更多信息，请参阅[将社交身份提供者与用户池配合使用](cognito-user-pools-social-idp.md)。

1. 对于需要映射的每个属性，请完成以下步骤：

   1. 从 **User pool attribute**（用户池属性）列中选择属性。这是分配给您的用户池中用户配置文件的属性。自定义属性在标准属性之后列出。

   1. 从属性列中选择一个***<provider>*属性**。这将是从提供商目录传递的属性。在下拉列表中提供来自社交服务提供商的已知属性。

   1. 要在 IdP 和 Amazon Cognito 之间映射其它属性，请选择 **Add another attribute**（添加其它属性）。

1. 选择 **Save changes**（保存更改）。

**指定 SAML 提供商属性映射**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 在导航窗格中，选择 **用户池**，然后选择要编辑的用户池。

1. 选择**社交和外部提供商**菜单。

1. 选择 **Add an identity provider**（添加身份提供者），或者选择您已配置的 SAML IdP。找到 **Attribute mapping**（属性映射），然后选择 **Edit**（编辑）。有关添加 SAML IdP 的更多信息，请参阅[将 SAML 身份提供者与用户池配合使用](cognito-user-pools-saml-idp.md)。

1. 对于需要映射的每个属性，请完成以下步骤：

   1. 从 **User pool attribute**（用户池属性）列中选择属性。这是分配给您的用户池中用户配置文件的属性。自定义属性在标准属性之后列出。

   1. 从 **SAML attribute**（SAML 属性）列中选择属性。这将是从提供商目录传递的属性。

      您的 IdP 可能会提供示例 SAML 断言以供参考。有些 IdPs 使用简单的名称，例如`email`，而另一些则使用类似于 URL 格式的属性名称：

      ```
      http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
      ```

   1. 要在 IdP 和 Amazon Cognito 之间映射其它属性，请选择 **Add another attribute**（添加其它属性）。

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

## 为您的用户池（AWS CLI 和 AWS API）指定身份提供商属性映射
<a name="cognito-user-pools-specifying-attribute-mapping-cli-api"></a>

以下请求正文按顺序将 SAML 提供商 “MyIdP” 属性`emailaddress``birthdate`、、和[UpdateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html)映射`phone`到用户池属性`email``birthdate``phone_number`、和。[CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)这是 SAML 2.0 提供者的完整请求正文，您的请求正文将因 IdP 类型和具体细节而有所不同。属性映射位于 `AttributeMapping` 参数中。

```
{
   "AttributeMapping": { 
      "email" : "emailaddress",
      "birthdate" : "birthdate",
      "phone_number" : "phone"
   },
   "IdpIdentifiers": [ 
      "IdP1",
      "pdxsaml"
   ],
   "ProviderDetails": { 
      "IDPInit": "true", 
      "IDPSignout": "true", 
      "EncryptedResponses" : "true", 
      "MetadataURL": "https://auth.example.com/sso/saml/metadata", 
      "RequestSigningAlgorithm": "rsa-sha256"
   },
   "ProviderName": "MyIdP",
   "ProviderType": "SAML",
   "UserPoolId": "us-west-2_EXAMPLE"
}
```

使用以下命令为您的用户池指定 IdP 属性映射。

**在提供商创建时指定属性映射**
+ AWS CLI: `aws cognito-idp create-identity-provider`

  带元数据文件的示例：`aws cognito-idp create-identity-provider --user-pool-id <user_pool_id> --provider-name=SAML_provider_1 --provider-type SAML --provider-details file:///details.json --attribute-mapping email=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`

  其中 `details.json` 包含：

  ```
  { 
      "MetadataFile": "<SAML metadata XML>"
  }
  ```
**注意**  
如果*<SAML metadata XML>*包含任何引号 (`"`)，则必须对其进行转义 (`\"`)。

  带元数据 URL 的示例：

  ```
  aws cognito-idp create-identity-provider \
  --user-pool-id us-east-1_EXAMPLE \
  --provider-name=SAML_provider_1 \
  --provider-type SAML \
  --provider-details MetadataURL=https://myidp.example.com/saml/metadata \
  --attribute-mapping email=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
  ```
+ API/SDK：[CreateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateIdentityProvider.html)

**指定现有 IdP 的属性映射**
+ AWS CLI: `aws cognito-idp update-identity-provider`

  示例：`aws cognito-idp update-identity-provider --user-pool-id <user_pool_id> --provider-name <provider_name> --attribute-mapping email=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`
+ API/SDK：[UpdateIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateIdentityProvider.html)

**获取有关特定 IdP 的属性映射的信息**
+ AWS CLI: `aws cognito-idp describe-identity-provider`

  示例：`aws cognito-idp describe-identity-provider --user-pool-id <user_pool_id> --provider-name <provider_name>`
+ API/SDK：[DescribeIdentityProvider](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeIdentityProvider.html)

# 将联合用户与现有用户配置文件关联
<a name="cognito-user-pools-identity-federation-consolidate-users"></a>

通常，同一个用户的个人资料包含多个身份提供商 (IdPs)，您已将其连接到您的用户池。Amazon Cognito 可以将用户的每次出现与目录中的同一个用户配置文件关联。这样，一个拥有多个 IdP 用户的人就可以在您的应用中获得一致的体验。 [AdminLinkProviderForUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html)让 Amazon Cognito 将您的联合目录中用户的唯一 ID 识别为用户池中的用户。当您具有零个或多个与用户配置文件相关联的联合身份时，用户池中的一个用户将计为一个每月活跃用户 (MAU) 以进行[计费](https://aws.amazon.com/cognito/pricing/)。

当联合用户首次登录您的用户池时，Amazon Cognito 会查找您已关联到其身份的本地个人资料。如果不存在关联的个人资料，则您的用户池会创建一个新的个人资料。您可以在联合用户首次登录前的任何时候，通过计划中的预先准备任务或 [注册前 Lambda 触发器](user-pool-lambda-pre-sign-up.md) 中的 `AdminLinkProviderForUser` API 请求，创建本地配置文件将其链接到联合用户。在您的用户登录且 Amazon Cognito 检测到关联的本地个人资料后，您的用户池会读取用户的声明，并将其与 IdP 的映射规则进行比较。然后，您的用户池会使用他们登录时映射的声明来更新关联的本地个人资料。通过这种方式，您可以为本地配置文件配置访问权限声明，并将其身份声明保留给您的 up-to-date提供商。在 Amazon Cognito 将您的联合用户与关联的个人资料匹配后，他们将始终登录该个人资料。然后，您可以将用户的更多提供者身份关联到同一个人资料，从而为一位客户提供一致的应用体验。要关联之前登录过的联合用户，必须先删除其现有个人资料。您可以通过其格式识别现有个人资料：`[Provider name]_identifier`。例如 `LoginWithAmazon_amzn1.account.AFAEXAMPLE`。您创建并链接到第三方用户身份的用户具有创建时使用的用户名和包含其关联身份详细信息的 `identities` 属性。

**重要**  
由于`AdminLinkProviderForUser`允许具有外部联合身份的用户以用户池中的现有用户身份登录，因此必须仅将其与应用程序所有者信任的外部 IdPs 和提供者属性一起使用。

例如，如果您是托管服务提供商 (MSP)，具有一个与多个客户共享的应用程序。每个客户都通过 Active Directory Federation Services (ADFS) 登录您的应用程序。您的 IT 管理员 Carlos 在每个客户的域中都有一个账户。您希望 Carlos 在每次登录时都能被识别为应用程序管理员，而不考虑 IdP。

你的 ADFS 在 IdPs 向亚马逊 Cognito 提出的 S `msp_carlos@example.com` AML `email` 声明中出示了 Carlos 的电子邮件地址。您使用用户名 `Carlos` 在用户池中创建一个用户。以下 AWS Command Line Interface (AWS CLI) 命令将来自 IdPs ADFS1、 ADFS2和 Carlos 的身份链接起来。 ADFS3

**注意**  
您可以根据特定属性声明关联用户。这种能力是 OIDC 和 SAML 所独有的。 IdPs对于其他提供者类型，您必须基于固定来源属性来进行关联。有关更多信息，请参阅 [AdminLinkProviderForUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html)。当您将社交 IdP 与用户配置文件关联时，必须将 `ProviderAttributeName` 设置为 `Cognito_Subject`。`ProviderAttributeValue` 必须是用户在 IdP 中的唯一标识符。

```
aws cognito-idp admin-link-provider-for-user \
--user-pool-id us-east-1_EXAMPLE \
--destination-user ProviderAttributeValue=Carlos,ProviderName=Cognito \
--source-user ProviderName=ADFS1,ProviderAttributeName=email,ProviderAttributeValue=msp_carlos@example.com

aws cognito-idp admin-link-provider-for-user \
--user-pool-id us-east-1_EXAMPLE \
--destination-user ProviderAttributeValue=Carlos,ProviderName=Cognito \
--source-user ProviderName=ADFS2,ProviderAttributeName=email,ProviderAttributeValue=msp_carlos@example.com

aws cognito-idp admin-link-provider-for-user \
--user-pool-id us-east-1_EXAMPLE \
--destination-user ProviderAttributeValue=Carlos,ProviderName=Cognito \
--source-user ProviderName=ADFS3,ProviderAttributeName=email,ProviderAttributeValue=msp_carlos@example.com
```

用户池中的用户配置文件 `Carlos` 现在具有以下 `identities` 属性。

```
[{
    "userId": "msp_carlos@example.com",
    "providerName": "ADFS1",
    "providerType": "SAML",
    "issuer": "http://auth.example.com",
    "primary": false,
    "dateCreated": 111111111111111
}, {
    "userId": "msp_carlos@example.com",
    "providerName": "ADFS2",
    "providerType": "SAML",
    "issuer": "http://auth2.example.com",
    "primary": false,
    "dateCreated": 111111111111111
}, {
    "userId": "msp_carlos@example.com",
    "providerName": "ADFS3",
    "providerType": "SAML",
    "issuer": "http://auth3.example.com",
    "primary": false,
    "dateCreated": 111111111111111
}]
```

**有关关联联合用户需了解的事项**
+ 您最多可以将五个联合用户与每个用户配置文件关联。
+ 根据 `AdminLinkProviderForUser` API 请求中的 `SourceUser` 的 `ProviderAttributeName` 参数的定义，您最多可以将用户链接到五个 IdP 属性声明中的每个 IdP。例如，如果您已将至少一个用户链接到源属性 `email`、`phone`、`department`、`given_name` 和 `location`，则只能选择这五个属性中的一个来链接额外的用户。
+ 您可以将联合用户与现有联合用户配置文件或本地用户关联。
+ 您无法在中将提供商链接到用户个人资料 AWS 管理控制台。
+ 您的用户 ID 令牌在 `identities` 声明中含包所有关联的提供者。
+ 您可以在 API 请求中为自动创建的联合用户配置文件设置密码。[AdminSetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserPassword.html)然后，该用户的状态从 `EXTERNAL_PROVIDER` 更改为 `CONFIRMED`。处于此状态的用户能够以联合用户身份登录，并像关联的本地用户一样在 API 中启动身份验证流程。他们还可以在经过令牌验证的 API 请求中修改自己的密码和属性，例如和。[ChangePassword[UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ChangePassword.html)作为最佳安全实践，为了让用户与您的外部 IdP 保持同步，请勿在联合用户配置文件上设置密码。相反，使用 `AdminLinkProviderForUser` 将用户与本地配置文件关联。
+ 当用户通过 IdP 进行登录时，Amazon Cognito 会将用户属性填充到关联的本地用户配置文件中。Amazon Cognito 处理来自 OIDC IdP 的 ID 令牌中的身份声明，还会检查 2.0 和 OIDC 提供商`userInfo`的 OAuth终端节点。Amazon Cognito 将 ID 令牌中的信息优先级置于来自 `userInfo` 的信息之上。

当您得知用户不再使用您已关联到其个人资料的外部用户账户时，您可以取消该用户账户与您的用户池用户的关联。当您关联用户时，您会在请求中提供用户的属性名称、属性值和提供者名称。要删除用户不再需要的配置文件，请使用等效参数发出 [AdminDisableProviderForUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDisableProviderForUser.html)API 请求。

[AdminLinkProviderForUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html)有关其他命令语法和示例，请参见 AWS SDKs。

# 用户池托管登录
<a name="cognito-user-pools-managed-login"></a>

您可以选择一个 Web 域来托管用户池的服务。当您添加域时，Amazon Cognito 用户池将获得以下功能，这些功能统称为*托管登录*。
+ 一种[授权服务器](https://datatracker.ietf.org/doc/html/rfc6749#section-1.1)，充当使用 OAuth 2.0 和 OpenID Connect (OIDC) 的应用程序的身份提供者 (IdP)。授权服务器[路由请求、发出](authorization-endpoint.md)[和管理 JSON Web 令牌 (JWTs)](token-endpoint.md)，并[提供用户属性信息](userinfo-endpoint.md)。
+ 用于登录、注销和密码管理等身份验证操作的 ready-to-use用户界面 (UI)。*托管登录页面*充当身份验证服务的 Web 前端。
+ SAML 2.0、OIDC、Facebook、Lo IdPs gin with Amazon IdPs、使用苹果登录和谷歌的服务提供商 (SP) 或依赖方 (RP)。

与托管登录共享某些功能的另一个选项是经典的*托管 UI*。经典托管 UI 是托管登录服务的第一代版本。托管 UI IdP 和 RP 服务通常与托管登录具有相同的特征，但是登录页面的设计更简单，功能也更少。例如，通行密钥登录在经典托管 UI 中不可用。在精简版[功能计划](cognito-sign-in-feature-plans.md)中，经典托管 UI 是用户池域服务的唯一选择。

托管登录页面是一组 Web 界面，用于在用户池中进行基本注册、登录、多重身份验证和密码重置活动。当你想让用户选择登录选项时，它们还会将用户连接到一个或多个第三方身份提供商 (IdPs)。当您想要对用户进行身份验证和授权时，应用程序可以在用户的浏览器中调用托管登录页面。

您可以通过自定义徽标、背景和样式使托管登录用户体验适合您的品牌。您有两个品牌选项可能适用于托管登录 UI：适用于托管登录的*品牌编辑器*和适用于托管 UI 的*托管 UI（经典）品牌*。

**品牌编辑器**  
Amazon Cognito 控制台中提供了最多的 up-to-date身份验证选项和可视化编辑器，带来了更新的用户体验。

**托管 UI 品牌**  
Amazon Cognito 用户池的先前采用者所熟悉的用户体验。托管 UI 的品牌推广是一个基于文件的系统。要将品牌应用于托管 UI 页面，您需要上传一个徽标图像文件和一个为多个预定 CSS 样式选项设置值的文件。

品牌编辑器并非在用户池的所有功能计划中都可用。有关更多信息，请参阅 [用户池功能计划](cognito-sign-in-feature-plans.md)。

有关构造对托管登录和托管 UI 服务的请求的更多信息，请参阅[用户池端点和托管登录参考](cognito-userpools-server-contract-reference.md)。

**注意**  
Amazon Cognito 托管登录不支持使用[自定义身份验证质询 Lambda 触发器](user-pool-lambda-challenge.md)进行自定义身份验证。

**Topics**
+ [托管登录本地化](#managed-login-localization)
+ [条款文档](#managed-login-terms-documents)
+ [使用设置托管登录 AWS Amplify](#cognito-user-pools-app-integration-amplify)
+ [使用 Amazon Cognito 控制台设置托管登录](#set-up-managed-login)
+ [查看您的登录页面](#view-login-pages)
+ [自定义身份验证页面](#cognito-user-pools-app-integration-customize-hosted-ui)
+ [托管登录和托管 UI 需知](#managed-login-things-to-know)
+ [配置用户池域](cognito-user-pools-assign-domain.md)
+ [将品牌应用于托管登录页面](managed-login-branding.md)

## 托管登录本地化
<a name="managed-login-localization"></a>

在用户交互式页面中，托管登录默认为英语。您可以显示您选择的语言的本地化托管登录页面。可用语言为在 AWS 管理控制台中可用的语言。在分发给用户的链接中，请添加 `lang` 查询参数，如以下示例所示。

```
https://<your domain>/oauth2/authorize?lang=es&response_type=code&client_id=<your app client id>&redirect_uri=<your relying-party url>
```

Amazon Cognito 会在用户发出带有 `lang` 参数的初始请求后，在用户的浏览器中对他们的语言首选项设置一个 cookie。设置 cookie 后，语言选择将持续保留，无需在后续请求中显示或要求您在请求中包含该参数。例如，在用户使用 `lang=de` 参数发出登录请求后，他们的托管登录页面将以德语呈现，直到他们清除其 cookie 或使用新的本地化参数（例如 `lang=en`）提出新请求。

本地化仅适用于托管登录。您必须使用 Essentials 或 Plus [功能计划](cognito-sign-in-feature-plans.md)并且已分配域才能使用[托管登录品牌](managed-login-branding.md)。

用户在托管登录中所做的选择不可用于[自定义电子邮件或短信发件人触发器](user-pool-lambda-custom-sender-triggers.md)。在实施这些触发器时，必须使用其他机制来确定用户的首选语言。在登录流程中，`locale` 属性可能会根据位置指示用户的首选语言。在注册流程中，用户池的区域或应用程序客户端 ID 可能会指示语言首选项。

有以下语言可供选择。


**托管登录语言**  

| 语言 | 代码 | 
| --- | --- | 
| 德国料理 | de | 
| English | en | 
| 西班牙料理 | es | 
| 法式料理 | fr | 
| 印度尼西亚语 | id | 
| 意大利语 | 原 | 
| 日语 | ja | 
| 韩语 | ko | 
| 葡萄牙语（巴西） | pt-BR | 
| 中文（简体） | zh-CN | 
| 中文（繁体） | zh-TW | 

## 条款文档
<a name="managed-login-terms-documents"></a>

您可以将托管登录页面配置为在用户注册时显示指向**使用条款**和**隐私政策**文档的链接。在应用程序客户端中设置这两个条款文档时，用户在注册时会看到以下文本：**注册即表示您同意我们的使用条款和隐私政策**。**使用条款**和**隐私政策**这两个短语出现在您的托管登录页面中，并以超链接形式链接到您的文档。

术语文档支持与托管登录本地化 URLs 相一致的特定语言。当用户使用 `lang` 查询参数选择语言时，Amazon Cognito 将以该语言显示指向条款文档的链接。如果您尚未配置特定语言的 URL，Amazon Cognito 将使用您为应用程序客户端配置的默认 URL。

要为应用程序客户端配置条款文档，请导航到用户池中的**托管登录**菜单。在**条款文档**下，选择**创建条款文档**。

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

**创建条款文档**

1. 导航到用户池，然后选择**托管登录**菜单。找到**条款文档**。

1. 选择**创建条款文档**。

1. 选择要将条款文档分配到的应用程序客户端。

1. 输入**条款名称**。它在控制台中标识您的文档。

1. 在**链接**下，选择**语言**，然后输入以该语言托管条款文档的 **URL**。

1. 要 URLs 为其他语言添加，请选择**添加其他**语言。

1. 选择**创建**。

------
#### [ Amazon Cognito user pools API ]

以下是一个示例 [CreateTerms](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateTerms.html) 请求正文。它会导致应用程序客户端 `1example23456789` 的注册页面在托管登录本地化为法语和葡萄牙语（巴西）版本的隐私政策时呈现该语言的链接。在托管登录在注册页面呈现链接`terms-of-use`之前，需要设置 URLs 单独的请求。

```
{
   "ClientId": "1example23456789",
   "Enforcement": "NONE",
   "Links": { 
      "cognito:default" : "https://example.com/privacy/",
      "cognito:french" : "https://example.com/fr/privacy/",
      "cognito:portuguese-brazil" : "https://example.com/pt/privacy/"
   },
   "TermsName": "privacy-policy",
   "TermsSource": "LINK",
   "UserPoolId": "us-east-1_EXAMPLE"
}
```

------

**注意**  
在 Amazon Cognito 在托管登录页面中显示条款文档之前，您必须为应用程序客户端创建使用条款和隐私政策文档。

## 使用设置托管登录 AWS Amplify
<a name="cognito-user-pools-app-integration-amplify"></a>

如果您使用 AWS Amplify 向网络或移动应用程序添加身份验证，则可以在 Amplify 命令行界面 (CLI) 中设置托管登录页面，在 Amplify 框架中设置库。要向应用程序添加身份验证功能，请将 `Auth` 类别添加到项目中。然后，在您的应用程序中，使用 Amplify 客户端库对用户池用户进行身份验证。

您可以调用托管登录页面进行身份验证，也可以通过重定向到 IdP 的授权端点联合用户。用户成功通过提供商身份验证之后，Amplify 在您的用户池中创建一个新用户，并将用户的令牌传递给您的应用程序。

以下示例说明 AWS Amplify 如何使用在您的应用程序中设置社交服务提供商的托管登录。
+ [React](https://docs.amplify.aws/react/build-a-backend/auth/concepts/external-identity-providers/)
+ [Swift](https://docs.amplify.aws/swift/build-a-backend/auth/concepts/external-identity-providers/)
+ [Flutter](https://docs.amplify.aws/flutter/build-a-backend/auth/concepts/external-identity-providers/)
+ [Android](https://docs.amplify.aws/android/build-a-backend/auth/concepts/external-identity-providers/)

## 使用 Amazon Cognito 控制台设置托管登录
<a name="set-up-managed-login"></a>

托管登录和托管 UI 的第一个要求是用户池域。在用户池控制台中，导航到用户池的**域**选项卡，然后添加 **Cognito 域**或**自定义域**。您也可以在创建新用户池的过程中选择域。有关更多信息，请参阅 [配置用户池域](cognito-user-pools-assign-domain.md)。当某个域在您的用户池中处于活动状态时，所有应用程序客户端都会在该域上提供公共身份验证页面。

创建或修改用户池域时，将为您的域设置**品牌版本**。此品牌版本可以选择**托管登录**或**托管 UI（经典）**。您选择的品牌版本将应用于在您的域中使用登录服务的所有应用程序客户端。

下一步是从用户池的**应用程序客户端**选项卡创建[应用程序客户端](user-pool-settings-client-apps.md)。在创建应用程序客户端的过程中，Amazon Cognito 会要求您提供有关应用程序的信息，然后提示您选择**返回 URL**。返回 URL 也称为依赖方（RP）URL、重定向 URI 和回调 URL。这是据以运行您的应用程序的 URL，例如 `https://www.example.com` 或 `myapp://example`。

在用户池中配置具有品牌风格的域和应用程序客户端后，托管登录页面便可以在互联网上使用。

## 查看您的登录页面
<a name="view-login-pages"></a>

在 Amazon Cognito 控制台中，在**应用程序客户端**菜单下选择应用程序客户端**登录页面**选项卡中的**查看登录页面**按钮。此按钮会将您转到用户池域中的登录页面，其中包含以下基本参数。
+ 应用程序客户端 id
+ 授权代码授予请求
+ 对您为当前应用程序客户端激活的所有范围的请求
+ 当前应用程序客户端列表中的第一个回调 URL

当您想要测试托管登录页面的基本功能时，**查看登录页面**按钮非常有用。您的登录页面将与您分配给[用户池域](cognito-user-pools-assign-domain.md)的**品牌版本**相匹配。您可以使用其他和修改后的参数自定义登录 URL。在大多数情况下，**查看登录页面**链接的自动生成的参数不完全符合您的应用程序需求。在这些情况下，您必须自定义应用程序在用户登录时调用的 URL。有关登录参数键和值的更多信息，请参阅 [用户池端点和托管登录参考](cognito-userpools-server-contract-reference.md)。

登录网页使用以下 URL 格式。此示例使用 `response_type=code` 参数请求授权码授予。

```
https://<your domain>/oauth2/authorize?response_type=code&client_id=<your app client id>&redirect_uri=<your relying-party url>
```

您可以从用户池中的**域**菜单查找您的用户池域字符串。在**应用程序客户端**菜单中，您可以识别应用程序客户端 IDs、其回调 URLs、允许的范围和其他配置。

当您使用自定义参数导航到 `/oauth2/authorize` 端点时，Amazon Cognito 会将您重定向到 `/oauth2/login` 端点，或者在您具有 `identity_provider` 或 `idp_identifier` 参数时，静默地将您重定向到 IdP 登录页面。

**隐式授予的示例请求**  
您可以使用针对隐式代码授予的以下 URL 查看登录网页，其中 `response_type=token`。成功登录后，Amazon Cognito 会将用户池令牌返回到您的 Web 浏览器的地址栏。

```
            https://mydomain.auth.us-east-1.amazoncognito.com/authorize?response_type=token&client_id=1example23456789&redirect_uri=https://mydomain.example.com
```

身份令牌和访问令牌显示为附加到您的重定向 URL 的参数。

以下内容是来自隐式授予请求的示例响应。

```
            https://auth.example.com/#id_token=eyJraaBcDeF1234567890&access_token=eyJraGhIjKlM1112131415&expires_in=3600&token_type=Bearer  
```

## 自定义身份验证页面
<a name="cognito-user-pools-app-integration-customize-hosted-ui"></a>

过去，Amazon Cognito 仅使用经典*托管 UI* 托管登录页面，这是一种向身份验证网页授予通用外观的简单设计。您可以使用徽标图像自定义 Amazon Cognito 用户池，也可以使用指定某些 CSS 样式值的文件调整某些样式。后来，Amazon Cognito 推出了*托管登录*，这是一项更新的托管身份验证服务。*品牌编辑*器更新 look-and-feel了托管登录。品牌编辑器是一个无代码可视化编辑器，提供一套比托管 UI 自定义体验更多的选项。托管登录还引入了自定义背景图像和深色模式主题。

在用户池中，您可以在托管登录和托管 UI 品牌体验之间切换。要了解有关自定义托管登录页面的更多信息，请参阅[将品牌应用于托管登录页面](managed-login-branding.md)。

## 托管登录和托管 UI 需知
<a name="managed-login-things-to-know"></a>

**一小时托管登录和托管 UI 会话 Cookie**  
当用户使用您的登录页面或第三方提供商登录时，Amazon Cognito 会在他们的浏览器中设置一个 Cookie。使用此 Cookie，用户可以在一小时内使用相同的身份验证方法再次登录。当他们使用浏览器 Cookie 登录时，他们会获得新的令牌，这些令牌将持续在应用程序客户端配置中指定的持续时间。用户属性或身份验证因素的更改不会影响他们使用其浏览器 Cookie 再次登录的能力。

使用会话 Cookie 进行身份验证不会将 Cookie 持续时间额外重置一小时。如果用户在最近一次成功进行交互式身份验证超过一个小时后尝试访问您的登录页面，则必须重新登录。

**确认用户账户并验证用户属性**  
对于用户池[本地用户](cognito-terms.md#terms-localuser)，当您将用户池配置为**允许 Cognito 自动发送消息以进行验证和确认**时，托管登录和托管 UI 效果最佳。当您启用此设置时，Amazon Cognito 会向注册的用户发送一条包含确认码的消息。当您改而确认用户为用户池管理员时，在注册后登录页面会显示一条错误消息。在这种状态下，Amazon Cognito 已创建新用户，但无法发送验证消息。您仍然可以确认用户为管理员，但他们可能会在遇到错误后联系您的支持部门。有关管理确认的更多信息，请参阅[允许用户在您的应用程序中注册但以用户池管理员身份进行确认](signing-up-users-in-your-app.md#signing-up-users-in-your-app-and-confirming-them-as-admin)。

**托管登录操作范围**  
托管登录和经典托管 UI 支持注册、登录和密码管理。这包括通过多重身份验证（MFA）和注册 webAuthn 身份验证器完成登录。托管登录不支持用户自助配置文件管理，例如属性更改和设置 MFA 首选项。您必须在自己的应用程序代码中实施配置文件管理。当您以管理员身份[AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)通过 API 操作更新电子邮件地址和电话号码时，托管登录也无法确认属性更改。

**查看您对配置所做的更改**  
如果您对页面做出样式更改但未立即显示这些更改，请等待几分钟，然后刷新页面。

**解码用户池令牌**  
Amazon Cognito 用户池令牌使用算法进行 RS256 签名。您可以使用解码和验证用户池令牌。 AWS Lambda请参阅[解码和验证 Amazon Cognito J](https://github.com/awslabs/aws-support-tools/tree/master/Cognito/decode-verify-jwt) WT 令牌。 GitHub

**TLS 版本**  
托管登录和托管 UI 页面要求在传输过程中进行加密。Amazon Cognito 提供的用户池域要求用户浏览器支持的最低 TLS 版本为 1.2。自定义域支持 TLS 版本 1.2 的浏览器连接。托管 UI（经典）对自定义域**不要求**使用 TLS 1.2，但较新的托管登录对自定义域和前缀域**要求**使用 TLS 版本 1.2。由于 Amazon Cognito 管理域服务的配置，因此您无法修改用户池域的 TLS 要求。

**CORS 策略**  
托管登录或托管 UI 都不支持自定义跨源资源共享（CORS）源策略。CORS 策略将阻止用户在其请求中传递身份验证参数，应在应用程序前端实施 CORS 策略。Amazon Cognito 对发往以下端点的请求返回 `Access-Control-Allow-Origin: *` 响应标头。

1. [令牌端点](token-endpoint.md)

1. [撤销端点](revocation-endpoint.md)

1. [userInfo 端点](userinfo-endpoint.md)

**Cookie**  
托管登录和托管 UI 在用户的浏览器中设置 Cookie。这些 Cookie 符合某些浏览器的要求，即要求网站不能设置第三方 Cookie。它们的范围仅限于您的用户池端点，包括以下内容：
+ 每个请求有一个 `XSRF-TOKEN` Cookie。
+ 一个 `csrf-state` Cookie，用于在重定向用户时保持会话一致性。
+ 用于保持会话一致性的 `csrf-state-legacy` Cookie，当您的浏览器不支持 `SameSite` 属性时由 Amazon Cognito 以回退的形式进行读取。
+ 一个 `cognito` 会话 Cookie，用于将成功的登录尝试保留一小时。
+ 一个用于在托管登录中保持用户对[语言本地化](#managed-login-localization)的选择的 `lang` Cookie。
+ 一个当用户在托管登录页面之间导航时保留所需数据的 `page-data` Cookie。

在 iOS 中，您可以[阻止所有 Cookie](https://support.apple.com/en-us/105082)。此设置与托管登录或托管 UI 不兼容。要与可能启用此设置的用户合作，请使用 AWS SDK 将用户池身份验证构建到原生 iOS 应用程序中。在这种情况下，您可以构建自己的会话存储，该存储不依赖 Cookie。

**托管登录版本更改的影响**  
请考虑添加域和设置托管登录版本的以下影响。
+ 当您添加带有托管登录或托管 UI（经典）品牌的前缀域时，登录页面可能需要长达 60 秒钟才可用。
+ 当您添加带有托管登录或托管 UI（经典）品牌的自定义域时，登录页面可能需要长达五分钟才可用。
+ 当您更改域的品牌版本时，可能需要长达四分钟，登录页面才会在新的品牌版本中可用。
+ 当您在托管登录和托管 UI（经典）品牌之间切换时，Amazon Cognito 不会维护用户会话。他们必须使用新界面重新登录。

**默认风格**  
当您在中创建应用程序客户端时 AWS 管理控制台，Amazon Cognito 会自动为您的应用程序客户端分配品牌风格。当您通过该[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)操作以编程方式创建应用程序客户端时，不会创建任何品牌风格。在您使用[CreateManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateManagedLoginBranding.html)请求创建应用程序客户端之前，托管登录不可用于使用 AWS SDK 创建的应用程序客户端。

**托管登录身份验证提示超时**  
Amazon Cognito 会取消未在五分钟内完成的身份验证请求，并将用户重定向到托管登录。页面随即显示 `Something went wrong` 错误消息。

# 配置用户池域
<a name="cognito-user-pools-assign-domain"></a>

配置域是设置用户池的可选部分。用户池域托管用于用户身份验证、与第三方提供者的联合身份验证以及 OpenID Connect（OIDC）流等功能。它具有*托管登录*，这是用于执行注册、登录和密码恢复等密钥操作的预构建界面。它还托管标准 OpenID Connect (OIDC) 端点，例如授权[、](authorization-endpoint.md)[用户信息和](userinfo-endpoint.md)[令牌](token-endpoint.md)，用于 machine-to-machine (M2M) 授权以及其他 OIDC 和 2.0 身份验证和授权流程。 OAuth 

用户在与您的用户池关联的域中使用托管登录页面进行身份验证。您可以通过两种方式配置此域：您可以使用默认 Amazon Cognito 托管域，也可以配置自己拥有的自定义域。

自定义域选项在灵活性、安全性和控制性方面有更多选择。例如，一个熟悉的、由组织拥有的域可以增强用户信任并使登录过程更加直观。但是，自定义域名方法需要一些额外的开销，例如管理 SSL 证书和 DNS 配置的开销。

终端节点 URLs 和`/.well-known/jwks.json`令牌签名密钥`/.well-known/openid-configuration`的 OIDC 发现端点未托管在您的域中。有关更多信息，请参阅 [身份提供者和依赖方端点](federation-endpoints.md)。

了解如何为您的用户池配置和管理域，这是将身份验证集成到应用程序中的重要一步。使用用户池 API 和 S AWS DK 登录可以替代配置网域。基于 API 的模型直接在 API 响应中提供令牌，但是对于使用用户池扩展功能作为 OIDC IdP 的实现，必须配置域。有关用户池中可用的身份验证模型的更多信息，请参阅[了解 API、OIDC 和托管登录页面身份验证](authentication-flows-public-server-side.md#user-pools-API-operations)。

**Topics**
+ [用户池域需知信息](#cognito-user-pools-assign-domain-things-to-know)
+ [使用 Amazon Cognito 前缀域进行托管登录](cognito-user-pools-assign-domain-prefix.md)
+ [使用您自己的域进行托管登录](cognito-user-pools-add-custom-domain.md)

## 用户池域需知信息
<a name="cognito-user-pools-assign-domain-things-to-know"></a>

用户池域是应用程序中的 OIDC 依赖方和 UI 元素的服务点。当您计划为用户池实施域时，请考虑以下详细信息。

**保留术语**  
您不能在 Amazon Cognito 前缀域的名称中使用文本 `aws`、`amazon` 或 `cognito`。

**发现端点位于另一个域中**  
用户池[发现端点](federation-endpoints.md) `.well-known/openid-configuration` 和 `.well-known/jwks.json` 不在您的用户池自定义域或前缀域中。这些端点的路径如下所示。
+ `https://cognito-idp.Region.amazonaws.com/your user pool ID/.well-known/openid-configuration`
+ `https://cognito-idp.Region.amazonaws.com/your user pool ID/.well-known/jwks.json`

**域变更的生效时间**  
Amazon Cognito 可能需要长达一分钟的时间才能启动或更新前缀域的品牌版本。对自定义域的更改最长可能需要五分钟才能传播。新自定义域最长可能需要一小时才能传播。

**同时使用自定义域和前缀域**  
您可以使用自定义域名和拥有的前缀域名来设置用户池 AWS。由于用户池[发现端点](federation-endpoints.md)托管在另一个域中，因此它们仅为*自定义域*提供服务。例如，您的 `openid-configuration` 将为 `"authorization_endpoint"` 提供单个值：`"https://auth.example.com/oauth2/authorize"`。

当用户池中同时包含自定义域和前缀域时，您可以使用自定义域来启用 OIDC 提供程序的完整特征。具有此配置的用户池中的前缀域没有发现或 token-signing-key端点，因此应相应地使用。

**首选自定义域作为通行密钥的依赖方 ID**  
使用[通行密钥](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passkey)设置用户池身份验证时，必须设置依赖方（RP）ID。如果同时具有自定义域和前缀域，则只能将 RP ID 设置为自定义域。要在 Amazon Cognito 控制台中将前缀域设置为 RP ID，请删除您的自定义域，或将前缀域的完全限定的域名（FQDN）作为**第三方域**进行输入。

**不要在域层次结构的不同级别使用自定义域**  
您可以为不同的用户池配置独立的自定义域，并且这些域可以共享同一个顶级域（TLD），例如 *auth.example.com* 和 *auth2.example.com*。托管登录会话 Cookie 对自定义域和所有子域（如 *\$1.auth.example.com*）均有效。因此，您的应用程序的任何用户都不应访问任何父域*和*子域的托管登录。如果自定义域使用相同的 TLD，则应将其保持在相同的子域级别。

假设您有一个使用自定义域 *auth.example.com* 的用户池。然后创建另一个用户池并分配自定义域 *uk.auth.example.com*。用户使用 *auth.example.com* 登录，并获得 Cookie，他们的浏览器会将其呈现给通配符路径 *\$1.auth.example.com* 中的任何网站。然后他们尝试登录 *uk.auth.example.com*。他们向用户池域传递无效 Cookie，将收到错误信息，而不是收到登录提示。相比之下，拥有 *\$1.auth.example.com* 的 Cookie 的用户可以在 *auth2.example.com* 启动登录会话，而不会遇到任何问题。

**品牌版本**  
创建域时可设置**品牌版本**。您可以选择更新的托管登录体验或经典的托管 UI 体验。这一选择适用于在您的域中托管服务的所有应用程序客户端。

# 使用 Amazon Cognito 前缀域进行托管登录
<a name="cognito-user-pools-assign-domain-prefix"></a>

托管登录的默认体验托管在 AWS 拥有的网域上。这种方法的进入门槛较低（选择一个前缀名称即可生效），但该方法没有自定义域所具有的值得信任的特征。Amazon Cognito 域选项和自定义域选项在费用上没有差异。唯一的差异是您引导用户访问的 Web 地址中的域。对于第三方 IdP 重定向和客户端凭证流，托管域几乎没有明显的影响。自定义域更适合以下情况，即，您的用户使用托管登录进行登录，并且会与不匹配应用程序域的身份验证域进行交互。

托管的 Amazon Cognito 域有您选择的前缀，但托管在根域 `amazoncognito.com`。以下是示例：

```
https://cognitoexample.auth.ap-south-1.amazoncognito.com
```

所有前缀域都遵循以下格式：`prefix`.`auth`.*`AWS 区域 code`*.`amazoncognito`.`com`。[自定义域](cognito-user-pools-add-custom-domain.md)用户池可以在您拥有的任何域中对托管登录或托管 UI 页面进行托管。

**注意**  
为了增强您的 Amazon Cognito 应用程序的安全性，用户池端点的父域将在[公共后缀列表 (PSL)](https://publicsuffix.org/) 中注册。PSL 可帮助用户的网络浏览器对您的用户池端点及其设置的 Cookie 建立一致的理解。  
用户池父域采用以下格式。  

```
auth.Region.amazoncognito.com
auth-fips.Region.amazoncognito.com
```

要使用添加应用程序客户端和用户池域 AWS 管理控制台，请参阅[创建应用程序客户端](user-pool-settings-client-apps.md#cognito-user-pools-app-idp-settings-console-create)。

**Topics**
+ [先决条件](#cognito-user-pools-assign-domain-prefix-prereq)
+ [配置 Amazon Cognito 域前缀](#cognito-user-pools-assign-domain-prefix-step-1)
+ [验证登录页面](#cognito-user-pools-assign-domain-prefix-verify)

## 先决条件
<a name="cognito-user-pools-assign-domain-prefix-prereq"></a>

在开始之前，您需要：
+ 用户池和应用程序客户端。有关更多信息，请参阅 [用户池入门](getting-started-user-pools.md)。

## 配置 Amazon Cognito 域前缀
<a name="cognito-user-pools-assign-domain-prefix-step-1"></a>

您可以使用 AWS 管理控制台 或 AWS CLI 或 API 来配置用户池域。

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

**配置域**

1. 导航到**品牌**下的**域**菜单。

1. 选择**域**旁边的**操作**，然后选择**创建 Cognito 域**。如果您已配置用户池前缀域，请先选择**删除 Cognito 域**，然后再创建新的自定义域。

1. 输入可用的域前缀，以与 **Amazon Cognito 域**结合使用。有关设置**自定义域**的信息，请参阅[使用您自己的域进行托管登录](cognito-user-pools-add-custom-domain.md)。

1. 选择**品牌版本**。您的品牌版本适用于该域的所有用户交互页面。您的用户池可以针对所有应用程序客户端，对托管登录或托管 UI 品牌进行托管。
**注意**  
您可以拥有自定义域和前缀域，但是 Amazon Cognito 仅为*自定义*域处理 `/.well-known/openid-configuration` 端点。

1. 选择**创建**。

------
#### [ CLI/API ]

使用以下命令可以创建域前缀并将其分配到您的用户池。

**配置用户池域**
+ AWS CLI: `aws cognito-idp create-user-pool-domain`

  **示例**：`aws cognito-idp create-user-pool-domain --user-pool-id <user_pool_id> --domain <domain_name> --managed-login-version 2`
+ 用户池 API 操作：[CreateUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolDomain.html)

**获取有关域的信息**
+ AWS CLI: `aws cognito-idp describe-user-pool-domain`

  **示例**：`aws cognito-idp describe-user-pool-domain --domain <domain_name>`
+ 用户池 API 操作：[DescribeUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPoolDomain.html)

**删除域**
+ AWS CLI: `aws cognito-idp delete-user-pool-domain`

  **示例**：`aws cognito-idp delete-user-pool-domain --domain <domain_name>`
+ 用户池 API 操作：[DeleteUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUserPoolDomain.html)

------

## 验证登录页面
<a name="cognito-user-pools-assign-domain-prefix-verify"></a>
+ 验证登录页面是否可从您的 Amazon Cognito 托管域访问。

  ```
  https://<your_domain>/login?response_type=code&client_id=<your_app_client_id>&redirect_uri=<your_callback_url>
  ```

您的域显示在 Amazon Cognito 控制台的 **Domain name (域名)** 页面上。您的应用程序客户端 ID 和回调 URL 将显示在 **App client settings**（应用程序客户端设置）页面上。

# 使用您自己的域进行托管登录
<a name="cognito-user-pools-add-custom-domain"></a>

在设置应用程序客户端后，您可以为[托管登录](cognito-user-pools-managed-login.md)的域服务使用自定义域来配置用户池。使用自定义域，用户就可以使用您自己的网址而不是默认的 `amazoncognito.com` [前缀域](cognito-user-pools-assign-domain-prefix.md)来登录您的应用程序。自定义域让您可以使用熟悉的域名，从而提高用户对您的应用程序的信任度，尤其是当根域与托管应用程序的域匹配时。使用自定义域，可以进一步满足组织的安全要求。

自定义域有一些先决条件，包括用户池、应用程序客户端和您拥有的 Web 域。自定义域名还需要使用位于美国东部（弗吉尼亚北部）的 AWS Certificate Manager (ACM) 管理的自定义域名的 SSL 证书。Amazon Cognito 会创建亚马逊 CloudFront 配送，在运输途中使用您的 ACM 证书进行保护。由于您拥有该域名，因此必须创建 DNS 记录，将流量引导至自定义域名的 CloudFront 分配。

在这些要素准备就绪后，您可以通过 Amazon Cognito 控制台或 API 将自定义域添加到用户池。这包括指定域名和 SSL 证书，然后使用提供的别名目标更新 DNS 配置。在进行这些更改后，您可以验证是否可从您的自定义域访问登录页面。

创建自定义域最省力的方法是在 Amazon Route 53 中使用公有托管区。Amazon Cognito 控制台只需几个步骤即可创建正确的 DNS 记录。在开始之前，请考虑为您拥有的域或子域[创建 Route 53 托管区](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/CreatingHostedZone.html)。

**Topics**
+ [将自定义域添加到用户池](#cognito-user-pools-add-custom-domain-adding)
+ [先决条件](#cognito-user-pools-add-custom-domain-prereq)
+ [步骤 1：输入自定义域名](#cognito-user-pools-add-custom-domain-console-step-1)
+ [步骤 2：添加别名目标和子域](#cognito-user-pools-add-custom-domain-console-step-2)
+ [步骤 3：验证登录页面](#cognito-user-pools-add-custom-domain-console-step-3)
+ [更改自定义域的 SSL 证书](#cognito-user-pools-add-custom-domain-changing-certificate)

## 将自定义域添加到用户池
<a name="cognito-user-pools-add-custom-domain-adding"></a>

要将自定义域添加到用户池，请在 Amazon Cognito 控制台中指定域名，并提供您使用 [AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/)（ACM）管理的证书。在添加域后，Amazon Cognito 提供了一个要添加到 DNS 配置的别名目标。

## 先决条件
<a name="cognito-user-pools-add-custom-domain-prereq"></a>

在开始之前，您需要：
+ 用户池和应用程序客户端。有关更多信息，请参阅 [用户池入门](getting-started-user-pools.md)。
+ 您拥有的 Web 域。其*父域*必须具有有效的 DNS **A 记录**。您可以为该记录分配任何值。父域可以是域的根，也可以是域层次结构中上一级的子域。例如，如果您的自定义域是 *auth.xyz.example.com*，Amazon Cognito 必须能够将 *xyz.example.com* 解析为 IP 地址。为了防止对客户基础设施造成意外影响，Amazon Cognito 不支持使用顶级域名 (TLDs) 作为自定义域名。有关更多信息，请参阅[域名](https://tools.ietf.org/html/rfc1035)。
+ 能够为自定义域创建子域。建议对您的子域名进行**身份验证**。例如：*auth.example.com*。
**注意**  
如果您没有[通配符证书](https://en.wikipedia.org/wiki/Wildcard_certificate)，则可能需要为自定义域的子域获取新证书。
+ 由美国东部（弗吉尼亚北部）ACM 管理的公共 SSL/TLS 证书。证书必须在 us-east-1 中，因为该证书将与全球服务中的发行版 CloudFront相关联。
+ 支持服务器名称指示（SNI）的浏览器客户端。Amazon Cognito CloudFront 分配给自定义域名的分配需要 SNI。您无法更改此设置。有关 CloudFront 分发中的 SNI 的更多信息，请参阅《*亚马逊 CloudFront 开发者*指南》中的 “[使用 SNI 处理 HTTPS 请求](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cnames-https-dedicated-ip-or-sni.html#cnames-https-sni)”。
+ 一个应用程序，允许您的用户池授权服务器向用户会话中添加 Cookie。Amazon Cognito 为托管登录页面设置多个必需的 Cookie。这包括 `cognito`、`cognito-fl` 和 `XSRF-TOKEN`。尽管每个 Cookie 都符合浏览器大小限制，但更改用户池配置可能会导致托管登录 Cookie 变大。像自定义域前面的应用程序负载均衡器（ALB）这样的中间服务可能会强制设定最大请求头大小或总 Cookie 大小。如果您的应用程序还设置了自己的 Cookie，则用户的会话可能会超过这些限制。为避免大小限制冲突，建议您的应用程序不要在托管用户池域服务的子域上设置 Cookie。
+ 允许更新 Amazon CloudFront 分配。为此，您可以为 AWS 账户中的用户附加以下 IAM policy 声明：

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

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
           {
              "Sid": "AllowCloudFrontUpdateDistribution",
              "Effect": "Allow",
              "Action": [
                  "cloudfront:updateDistribution"
              ],
              "Resource": [
                  "*"
              ]
          }
      ]
  }
  ```

------

  有关授权操作的更多信息 CloudFront，请参阅[使用基于身份的策略（IAM 策略）](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/access-control-managing-permissions.html)。 CloudFront

  Amazon Cognito 最初使用您的 IAM 权限来配置 CloudFront分配，但分配由管理。 AWS您无法更改 Amazon Cognito 与您的用户池关联的 CloudFront 分配的配置。例如，您无法更新安全策略中支持的 TLS 版本。

## 步骤 1：输入自定义域名
<a name="cognito-user-pools-add-custom-domain-console-step-1"></a>

您可以使用 Amazon Cognito 控制台或 API 将域添加到用户池。

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

**将域从 Amazon Cognito 控制台添加到用户池：**

1. 导航到**品牌**下的**域**菜单。

1. 选择**域**旁边的**操作**，然后选择**创建自定义域**或**创建 Amazon Cognito 域**。如果您已配置用户池自定义域，请先选择**删除自定义域**，然后再创建新的自定义域。

1. 选择**域**旁边的**操作**，然后选择**创建自定义域**。如果您已配置自定义域，请先选择**删除自定义域**来删除现有域，然后再创建新的自定义域。

1. 对于**自定义域**，请输入您希望与 Amazon Cognito 一起使用的域的 URL。您的域名只能包含小写字母、数字和连字符。请勿对第一个或最后一个字符使用连字符。使用句点来分隔子域名。

1. 对于 **ACM 证书**，请选择要用于您的域的 SSL 证书。无论您的用户池如何，只有美国东部（弗吉尼亚北部）的 ACM 证书才有资格用于 Amazon Cognito 自定义域。 AWS 区域 

   如果您没有可用证书，则可以使用 ACM 在美国东部（弗吉尼亚北部）预置一个证书。有关更多信息，请参阅《AWS Certificate Manager 用户指南》**中的[入门](https://docs.aws.amazon.com/acm/latest/userguide/gs.html)。

1. 选择**品牌版本**。您的品牌版本适用于该域的所有用户交互页面。您的用户池可以针对所有应用程序客户端，对托管登录或托管 UI 品牌进行托管。
**注意**  
您可以拥有自定义域和前缀域，但是 Amazon Cognito 仅为*自定义*域处理 `/.well-known/openid-configuration` 端点。

1. 选择**创建**。

1. Amazon Cognito 将转至**域**菜单。此时将显示标题为**在域名的 DNS 中创建别名记录**的消息。记下控制台中显示的**域**和**别名目标**。在下一步骤中，将使用它们将流量指向您的自定义域。

------
#### [ API ]

以下[CreateUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolDomain.html)请求正文创建了一个自定义域。

```
{
   "Domain": "auth.example.com",
   "UserPoolId": "us-east-1_EXAMPLE",
   "ManagedLoginVersion": 2,
   "CustomDomainConfig": {
    "CertificateArn": "arn:aws:acm:us-east-1:111122223333:certificate/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
   }
}
```

------

## 步骤 2：添加别名目标和子域
<a name="cognito-user-pools-add-custom-domain-console-step-2"></a>

在本步骤中，您将通过域名服务器（DNS）服务提供商设置一个别名，该别名指回到上一个步骤中的别名目标。如果您将 Amazon Route 53 用于 DNS 地址解析，请选择**使用 Route 53 添加别名目标和子域**部分。

### 将别名目标和子域添加到当前 DNS 配置
<a name="cognito-user-pools-add-custom-domain-console-step-2a"></a>
+ 如果您没有将 Route 53 用于 DNS 地址解析，则必须使用您的 DNS 服务提供商配置工具将上一个步骤中的别名目标添加到域 DNS 记录中。您的 DNS 提供商还需要为您的自定义域设置子域。

### 使用 Route 53 添加别名目标和子域
<a name="cognito-user-pools-add-custom-domain-console-step-2b"></a>

1. 登录 [Route 53 控制台](https://console.aws.amazon.com/route53/)。如果出现提示，请输入您的 AWS 凭据。

1. 如果您在 Route 53 中没有公共托管区，请创建一个托管区，将根域作为您的自定义域的父域。有关更多信息，请参阅《Amazon Route 53 开发人员指南》**中的[创建公共托管区](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/CreatingHostedZone.html)。

   1. 选择**创建托管区域**。

   1. 例如*auth.example.com*，从域名列表中输入自定义域名的父**域名**。*myapp.auth.example.com*

   1. 输入托管区域的**描述**。

   1. 选择**公有托管区域**的托管区域**类型**以允许公共客户端解析您的自定义域。不支持选择**私有托管区域**。

   1. 根据需要应用**标签**。

   1. 选择**创建托管区域**。
**注意**  
您还可以为自定义域创建新的托管区，并且使用父托管区中的委托集将查询指向子域托管区。否则，请创建 A 记录。此方法为您的托管区域提供了更大的灵活度和安全性。有关更多信息，请参阅[通过 Amazon Route 53 为托管域创建子域](https://aws.amazon.com/premiumsupport/knowledge-center/create-subdomain-route-53/)。

1. 在**托管区域**页面上，选择您的托管区域的名称。

1. 为自定义域的父域添加 DNS 记录（如果您还没有 DNS 记录）。为父域创建 DNS 记录，其属性如下：
   + **记录名称**：留空。
   + **记录类型**：`A`。
   + **别名**：不启用。
   + **值**：输入您选择的目标。此记录必须解析到*某个地址*，但记录的值对于 Amazon Cognito 来说并不重要。
   + **TTL**：设置为您的首选 TTL 或保留为默认值。
   + **路由策略**：选择**简单路由**。

1. 选择**创建记录**。以下是该域的示例记录*example.com*：

   `example.com. 60 IN A 198.51.100.1`
**注意**  
Amazon Cognito 验证您的自定义域的父域是否有 DNS 记录，以防止意外劫持生产域。如果您没有父域的 DNS 记录，则当您尝试设置自定义域时，Amazon Cognito 将返回错误消息。起始授权（SOA）记录是一条 DNS 记录，但不足以用于父域验证。

1. 使用以下属性为您的自定义域添加另一条 DNS 记录：
   + **记录名称**：用于为 `auth.example.com` 创建记录的自定义域前缀（例如 `auth`）。
   + **记录类型**：`A`。
   + **别名**：启用。
   + **流量路由至**：选择 **CloudFront 分发的别名**。输入您之前记录的**别名目标**，例如 `123example.cloudfront.net`。
   + **路由策略**：选择**简单路由**。

1. 选择**创建记录**。
**注意**  
新记录可能需要大约 60 秒钟才能传播到所有 Route 53 DNS 服务器。您可以使用 Route 53 [GetChange](https://docs.aws.amazon.com/Route53/latest/APIReference/API_GetChange.html)API 方法来验证您的更改是否已传播。

## 步骤 3：验证登录页面
<a name="cognito-user-pools-add-custom-domain-console-step-3"></a>
+ 验证登录页面是否可从您的自定义域访问。

  通过在浏览器中输入此地址，使用您的自定义域和子域进行登录。以下是*example.com*带有子域名的自定义网域的网址示例：*auth*

  ```
  https://myapp.auth.example.com/login?response_type=code&client_id=<your_app_client_id>&redirect_uri=<your_callback_url>
  ```

## 更改自定义域的 SSL 证书
<a name="cognito-user-pools-add-custom-domain-changing-certificate"></a>

如果需要，您可以使用 Amazon Cognito 更改应用于自定义域的证书。

通常，在使用 ACM 进行常规证书续订后，此操作是不必要的。当您续订 ACM 中的现有证书时，证书的 ARN 保持不变，并且您的自定义域将自动使用新证书。

但是，如果您将现有证书替换为新证书，ACM 将为新证书提供一个新 ARN。要将新证书应用于自定义域，您必须将此 ARN 提供给 Amazon Cognito。

在提供新证书后，Amazon Cognito 需要长达 1 小时才能将它分配给自定义域。

**开始前的准备工作**  
您必须先将证书添加到 Amazon Cognito，然后才能更改 ACM 中的证书。有关更多信息，请参阅《AWS Certificate Manager 用户指南》**中的[入门](https://docs.aws.amazon.com/acm/latest/userguide/gs.html)。  
将您的证书添加到 ACM 时，您必须选择美国东部（弗吉尼亚北部）作为 AWS 区域。

您可以使用 Amazon Cognito 控制台或 API 更改证书。

------
#### [ AWS 管理控制台 ]

**更新 Amazon Cognito 控制台的证书：**

1. 登录 AWS 管理控制台 并打开 Amazon Cognito 控制台，网址为。[https://console.aws.amazon.com/cognito/home](https://console.aws.amazon.com/cognito/home)

1. 选择**用户池**。

1. 选择要更新其证书的用户池。

1. 选择**域**菜单。

1. 选择 **操作**、**编辑 ACM 证书**。

1. 选择您希望与自定义域关联的新证书。

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

------
#### [ API ]

**更新证书（Amazon Cognito API）**
+ 使用 [UpdateUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolDomain.html) 操作。

------

# 将品牌应用于托管登录页面
<a name="managed-login-branding"></a>

您可能想在身份验证服务和应用程序之间提供一致的用户体验。您可以通过 AWS SDK 中的自定义表单和后端 API 操作或托管登录来实现此目标。托管登录和经典托管 UI 是应用程序中提供用户池身份验证的组件的 Web 前端。要将托管身份验证服务与应用程序 UX 同步，您有两个自定义选项：品牌编辑器和托管 UI 品牌。您可以在 Amazon Cognito 控制台中使用用户池 API 操作来选择自己的首选体验。

**品牌编辑器**  
[品牌编辑器](managed-login-brandingeditor.md)是[托管登录](cognito-user-pools-managed-login.md)（最新的用户池 UI 体验）的最新自定义选项。品牌编辑器是一个无代码的可视化编辑器，用于管理托管登录页面的资产和样式，同时提供一组 API 操作，支持以编程方式配置大量配置选项。配置了[域](cognito-user-pools-assign-domain.md)和托管登录的用户池会自动呈现品牌设计器版本的登录页面。

**托管 UI（经典）品牌**  
[托管 UI（经典）品牌体验](hosted-ui-classic-branding.md)有两个选项：修改一个具有固定样式选项的层叠样式表（CSS）文件，以及添加自定义徽标图像。您可以在 Amazon Cognito 控制台中或通过[设置 UICustomization API 操作来设置](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUICustomization.html)这些选项。在该服务推出时，Amazon Cognito 只有这个选项。配置了[域](cognito-user-pools-assign-domain.md)和托管 UI 品牌版本的用户池会自动呈现经典版本的登录页面。您的[功能计划](cognito-sign-in-feature-plans.md)也可能仅支持托管 UI。

**注意**  
品牌编辑器和经典品牌体验会修改托管身份验证服务的视觉属性。目前，您无法修改托管登录页面上显示的文本，只能将本地化应用于几种语言中的一种。有关本地化的更多信息，请参阅[托管登录本地化](cognito-user-pools-managed-login.md#managed-login-localization)。

## 选择品牌体验并分配样式
<a name="managed-login-branding-choose"></a>

在 Amazon Cognito 控制台中，新用户池默认为**托管登录**品牌体验。您在托管登录可用之前设置的用户池将显示**托管 UI（经典）**品牌。您可以在托管登录和托管 UI 品牌之间切换。当您更改**品牌版本**时，Amazon Cognito 会立即将更改应用于您的用户池域的用户交互式页面。在托管登录和托管 UI 中，您的用户池可以为每个应用程序客户端设置一种样式。

每个应用程序客户端可以有不同的品牌*样式*，但是一个用户池域只能用于托管登录或托管 UI 中的一种。样式是指应用于应用程序客户端的一组自定义设置。每个用户池可以设置一个[自定义域](cognito-user-pools-add-custom-domain.md)和一个[前缀域](cognito-user-pools-assign-domain-prefix.md)。您可以为自定义域和前缀域分配不同的品牌版本。但是，如果您还有自定义域，则前缀域的功能并不完整：`.well-known` OIDC 发现端点*仅* 提供自定义域的路径。在具有此配置的用户池中，前缀域只能用于不需要端点发现（`openid-configuration`）的操作。由于用户池的这些属性，您在每个用户池中只能有效使用一种品牌样式。

您可以在已将域设置为托管登录品牌版本的用户池中，为应用程序客户端分配样式。样式是一组视觉设置，由图像文件、显示选项和 CSS 值组成。当您为应用程序客户端分配样式后，Amazon Cognito 会立即将您的更新推送到用户交互式登录页面。Amazon Cognito 会使用您选择的品牌版本及其所应用的自定义设置来呈现这些用户交互式页面。

### 更新和删除样式
<a name="managed-login-branding-update"></a>

创建样式时，可将其链接到应用程序客户端。要更改应用程序客户端的样式分配，必须先删除原始样式。目前，您无法在样式之间复制设置，必须通过编程方式来实现这一点。要在样式和应用程序客户端之间复制设置，请[DescribeManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeManagedLoginBranding.html)通过 API 操作获取样式的设置，然后使用[CreateManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateManagedLoginBranding.html)或应用这些设置[UpdateManagedLoginBranding](https://docs.aws.amazon.com/)。您无法更改已分配给应用程序客户端的样式，只能删除原始样式并设置新样式。有关通过 API 和 SDK 操作管理样式的更多信息，请参阅[托管登录品牌的 API 和 SDK 操作](managed-login-brandingeditor.md#branding-designer-api)。

**注意**  
对于通过编程方式创建或更新品牌样式的请求，请求大小不得超过 2 MB。如果您的请求超过此限制，请将其拆分为多个 `UpdateManagedLoginBranding` 请求，每组参数的大小均不超过最大请求限制。这些部分更新请求不会将未指定的参数重置为默认值，因此您可以安全地发送它们，而不会影响现有的设置。

您可以在 Amazon Cognito 控制台的**托管登录**菜单中删除样式。在**样式**下，选择要删除的样式，然后选择**删除样式**。

简而言之，为域分配品牌的流程包括以下步骤。

1. [创建域并设置品牌版本](cognito-user-pools-assign-domain.md)。

1. 创建品牌样式，并将其分配给应用程序客户端。

**将样式分配给应用程序客户端**

1. 在用户池的**域**菜单中创建域，并将**品牌版本**设置为**托管登录**。

1. 导航至**托管登录**菜单。在**样式**下，选择**创建样式**。

1. 选择要为其分配样式的应用程序客户端，或新建一个[应用程序客户端](user-pool-settings-client-apps.md)。

1. 要开始配置品牌设置，请选择**启动品牌编辑器**。

**Topics**
+ [选择品牌体验并分配样式](#managed-login-branding-choose)
+ [品牌编辑器与自定义托管登录](managed-login-brandingeditor.md)
+ [自定义托管 UI（经典）品牌](hosted-ui-classic-branding.md)

# 品牌编辑器与自定义托管登录
<a name="managed-login-brandingeditor"></a>

品牌编辑器是托管登录网页的可视化设计和编辑工具。该工具已内置到 Amazon Cognito 控制台中。在品牌编辑器中，您首先会看到登录页面的预览，并可选择进入快速设置选项，或包含高级选项的详细视图。您可以修改和预览样式参数或添加自定义背景图像和徽标。您还可以配置浅色模式和深色模式。

![\[Amazon Cognito 用户池品牌编辑器可视化编辑器的预览图。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/hosted-ui-customization-editor-preview.png)


首先，创建一种可以应用于用户池或应用程序客户端的样式。

**开始使用品牌编辑器**

1. 在**域**选项卡中[创建域](cognito-user-pools-assign-domain.md)，或者更新现有域。在**品牌版本**下，将您的域设置为使用**托管登录**。

1. 如有任何现有应用程序客户端样式，则将其删除。

   1. 在**应用程序客户端**菜单中，选择您的应用程序客户端。

   1. 在**托管登录样式**下，选择分配给您的应用程序客户端的样式。

   1. 选择**删除样式**。确认您的选择。

1. 导航到用户池中的**托管登录**菜单。如果您没有此功能，请按照提示选择一个包含托管登录的[功能计划](cognito-sign-in-feature-plans.md)。如果您只想查看品牌编辑器而不进行任何更改，也可以选择**预览此功能**。

1. 在**样式**下，选择**创建样式**。

1. 选择要为其分配样式的应用程序客户端，然后选择**创建**。您还可以新建应用程序客户端。

1. Amazon Cognito 控制台将启动品牌编辑器。

1. 选择要开始编辑的选项卡，或者选择**启动编辑器**并进入[快速设置](#branding-designer-quick-setup)。可以看到以下选项卡：  
**预览**  
查看您当前的选择在托管登录页面中的实际效果。  
**基础**  
设置整体主题，配置指向外部身份提供者的链接，并设置表单字段的样式。  
**组件**  
配置页眉、页脚及各个 UI 元素的样式。

1. 要选择初始设置，请进入快速设置。选择**更改设置类别**，然后选择**快速设置**。选择**继续**后，品牌编辑器将启动，其中包含一组可配置的基本选项。

## 文本和本地化
<a name="branding-designer-loc"></a>

您无法在品牌编辑器中修改或本地化文本。请改为在分发给用户的 URL 中添加 `lang` 查询参数。此参数会使您的托管登录页面本地化为多种可用语言之一。有关更多信息，请参阅 [托管登录本地化](cognito-user-pools-managed-login.md#managed-login-localization)。

## 快速设置
<a name="branding-designer-quick-setup"></a>

**启动品牌编辑器**按钮会加载一个可视化编辑器，用于配置您的托管登录页面，您可在其中选择多种主要自定义选项。在您进行选择时，Amazon Cognito 会在预览窗口中呈现托管登录页面的更改。要返回详细设置菜单，请选择**更改设置类别**按钮。

**整体外观和风格应该如何？**  
为托管登录页面配置基本主题设置。    
**显示模式**  
为托管登录选择浅色模式、深色模式或自适应体验。自适应设置会在 Amazon Cognito 呈现托管登录页面时，遵循用户的浏览器偏好。当您选择浏览器自适应模式时，可以为浅色模式和深色模式选择不同的颜色和徽标图像。  
**Spacing**  
设置页面中元素之间的默认间距。  
**边框圆角**  
设置元素外边框的圆角程度。

**页面背景应呈现什么效果？**    
**背景类型**  
**显示图像**复选框用于指定您是希望使用背景图像，还是设置纯色背景。  

1. 要使用图像，请选择**显示图像**，然后为浅色模式和深色模式分别选择背景图像。您还可以为图像未覆盖的背景区域分别设置深色模式和浅色模式的**页面背景颜色**。

1. 要使用纯色背景，请取消选择**显示图像**，然后选择浅色模式和深色模式的**页面背景颜色**。

**表单应呈现什么效果？**  
为托管登录的表单元素配置设置。表单项的示例包括登录和验证码提示。    
**水平对齐**  
设置表单字段的水平对齐方式。  
**表单徽标**  
设置徽标图像的位置。  
**徽标图像**  
选择要包含在浅色和深色模式的表单元素中的徽标图像文件。要上传图像，请选择**徽标图像**下拉列表，选择**添加新资产**，然后添加徽标文件。  
**主要品牌颜色**  
为浅色模式和深色模式设置主题颜色。此颜色将作为背景色应用于所有归类为主要元素的元素。

**页眉应呈现什么效果？**  
选择是否要在托管登录页面中添加页眉。页眉可以包含徽标图像。    
**页眉徽标**  
设置徽标图像在页眉中的位置。  
**徽标图像**  
选择徽标位置，以及要添加在页眉中的徽标图像文件。要上传图像，请选择**徽标图像**下拉列表，选择**添加新资产**，然后添加徽标文件。  
**页眉背景颜色**  
为页眉的背景设置浅色模式和深色模式颜色。

## 详细设置
<a name="branding-designer-advanced"></a>

在详细设置视图中，您可以修改**基础**和**组件**中的各个组件。**预览**选项卡会根据当前上下文和您的自定义设置，显示托管登录页面的预览效果。

![\[托管登录组件详细配置的 AWS 管理控制台 屏幕截图。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/hosted-ui-customization-console-preview.png)


要进入组件的可视化编辑器，请在组件对应的磁贴中选择编辑图标。在主题 Studio 编辑器中，您可以使用**更改设置类别**按钮在组件之间切换。

### 基础
<a name="branding-designer-advanced-foundation"></a>

**应用程序样式**  
配置托管登录的基本设置。此类别包含整体主题、文本间距以及页眉和页脚的设置。

**显示模式**  
为托管登录页面选择浅色模式、深色模式或自适应体验。当您选择浏览器自适应模式时，可以为浅色模式和深色模式选择不同的颜色和徽标图像。

**Spacing**  
设置页面中元素之间的默认间距。

**身份验证行为**  
为将您的用户连接到外部身份提供商的按钮配置样式（IdPs）。本节包含**域搜索输入**选项，启用后，托管登录会提示用户输入电子邮件地址，并将其与对应的 [SAML 身份提供者标识符](cognito-user-pools-managing-saml-idp-naming.md)进行匹配。

**表单行为**  
配置输入表单的样式：输入的位置、颜色和元素的对齐方式。

### 组件
<a name="branding-designer-advanced-components"></a>

**按钮**  
Amazon Cognito 在托管登录页面上呈现的按钮样式。

**分隔线**  
托管登录元素之间分隔线和边界的样式，例如输入表单与外部提供商登录选择器之间的分隔。

**下拉菜单**  
下拉菜单的样式。

**网页图标**  
Amazon Cognito 为选项卡和书签图标提供的图像的样式。

**焦点环**  
当前选中输入框的高亮样式。

**表单容器**  
包围表单的元素的样式。

**全局页脚**  
Amazon Cognito 在托管登录页面底部显示的页脚样式。

**全局页眉**  
Amazon Cognito 在托管登录页面顶部显示的页眉样式。

**指示**  
错误和成功消息的样式。

**选项控件**  
复选框、多选框和其他输入提示的样式。

**页面背景**  
托管登录页面整体背景的样式。

**输入**  
表单字段输入提示的样式。

**Link**  
托管登录页面中超链接的样式。

**页面文本**  
页内文本的样式。

**字段文本**  
表单输入框周围文本的样式。

## 托管登录品牌的 API 和 SDK 操作
<a name="branding-designer-api"></a>

您还可以使用 API 操作[CreateManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateManagedLoginBranding.html)和将品牌应用于托管登录风格[UpdateManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateManagedLoginBranding.html)。这些操作非常适合为另一个应用程序客户端或用户池创建完全相同或稍作修改版的品牌样式。使用 API 操作查询现有样式的托管登录品牌 [DescribeManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeManagedLoginBranding.html)，然后根据需要修改输出并将其应用于其他资源。

`UpdateManagedLoginBranding` 操作不会更改您的样式应用到的应用程序客户端。它仅会更新分配给应用程序客户端的现有样式。要完全替换应用程序客户端的样式，请删除现有样式，[DeleteManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteManagedLoginBranding.html)然后使用指定新样式`CreateManagedLoginBranding`。在 Amazon Cognito 控制台中，情况也是如此：必须先删除现有样式，然后创建新样式。

在 API 或 SDK 请求中设置托管登录品牌时，需要将您的设置嵌入到一个 JSON 文件中，并将该文件转换为 `Document` 数据类型。下面提供了关于可添加的图像以及如何生成编程式请求以配置品牌样式的指导。

### 图像资产
<a name="branding-designer-api-assets"></a>

[CreateManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateManagedLoginBranding.html)并[UpdateManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateManagedLoginBranding.html)包括一个`Assets`参数。该参数是一个采用 base64 编码二进制格式的图像文件数组。

**注意**  
对于通过编程方式创建或更新品牌样式的请求，请求大小不得超过 2 MB。您请求中的资产可能会使请求超过此限制。如果是这种情况，请将其拆分为多个 `UpdateManagedLoginBranding` 请求，每组参数的大小均不超过最大请求限制。这些部分更新请求不会将未指定的参数重置为默认值，因此您可以安全地发送它们，而不会影响现有的设置。

有些资产对您可提交的文件类型有限制。


****  

| 资产 | 接受的文件扩展名 | 
| --- | --- | 
| FAVICON\$1ICO | ico | 
| FAVICON\$1SVG | svg | 
| EMAIL\$1GRAPHIC | png、svg、jpeg | 
| SMS\$1GRAPHIC | png、svg、jpeg | 
| AUTH\$1APP\$1GRAPHIC | png、svg、jpeg | 
| PASSWORD\$1GRAPHIC | png、svg、jpeg | 
| PASSKEY\$1GRAPHIC | png、svg、jpeg | 
| PAGE\$1HEADER\$1LOGO | png、svg、jpeg | 
| PAGE\$1HEADER\$1BACKGROUND | png、svg、jpeg | 
| PAGE\$1FOOTER\$1LOGO | png、svg、jpeg | 
| PAGE\$1FOOTER\$1BACKGROUND | png、svg、jpeg | 
| PAGE\$1BACKGROUND | png、svg、jpeg | 
| FORM\$1BACKGROUND | png、svg、jpeg | 
| FORM\$1LOGO | png、svg、jpeg | 
| IDP\$1BUTTON\$1ICON | ico、svg | 

SVG 类型的文件支持以下属性和元素。

------
#### [ Attributes ]

```
accent-height, accumulate, additivive, alignment-baseline, ascent, attributename, attributetype, azimuth, basefrequency, baseline-shift, begin, bias, by, class, clip, clip-path, clip-rule, color, color-interpolation, color-interpolation-filters, color-profile, color-rendering, cx, cy, d, dx, dy, diffuseconstant, direction, display, divisor, dur, edgemode, elevation, end, fill, fill-opacity, fill-rule, filter, filterunits, flood-color, flood-opacity, font-family, font-size, font-size-adjust, font-stretch, font-style, font-variant, font-weight, fx, fy, g1, g2, glyph-name, glyphref, gradientunits, gradienttransform, height, href, id, image-rendering, in, in2, k, k1, k2, k3, k4, kerning, keypoints, keysplines, keytimes, lang, lengthadjust, letter-spacing, kernelmatrix, kernelunitlength, lighting-color, local, marker-end, marker-mid, marker-start, markerheight, markerunits, markerwidth, maskcontentunits, maskunits, max, mask, media, method, mode, min, name, numoctaves, offset, operator, opacity, order, orient, orientation, origin, overflow, paint-order, path, pathlength, patterncontentunits, patterntransform, patternunits, points, preservealpha, preserveaspectratio, r, rx, ry, radius, refx, refy, repeatcount, repeatdur, restart, result, rotate, scale, seed, shape-rendering, specularconstant, specularexponent, spreadmethod, stddeviation, stitchtiles, stop-color, stop-opacity, stroke-dasharray, stroke-dashoffset, stroke-linecap, stroke-linejoin, stroke-miterlimit, stroke-opacity, stroke, stroke-width, style, surfacescale, tabindex, targetx, targety, transform, text-anchor, text-decoration, text-rendering, textlength, type, u1, u2, unicode, values, viewbox, visibility, vert-adv-y, vert-origin-x, vert-origin-y, width, word-spacing, wrap, writing-mode, xchannelselector, ychannelselector, x, x1, x2, xmlns, y, y1, y2, z, zoomandpan
```

------
#### [ Elements ]

```
svg, a, altglyph, altglyphdef, altglyphitem, animatecolor, animatemotion, animatetransform, audio, canvas, circle, clippath, defs, desc, ellipse, filter, font, g, glyph, glyphref, hkern, image, line, lineargradient, marker, mask, metadata, mpath, path, pattern, polygon, polyline, radialgradient, rect, stop, style, switch, symbol, text, textpath, title, tref, tspan, video, view, vkern, feBlend, feColorMatrix, feComponentTransfer, feComposite, feConvolveMatrix, feDiffuseLighting, feDisplacementMap, feDistantLight, feFlood, feFuncA, feFuncB, feFuncG, feFuncR, feGaussianBlur, feMerge, feMergeNode, feMorphology, feOffset, fePointLight, feSpecularLighting, feSpotLight, feTile, feTurbulence
```

------

### 托管登录品牌操作的工具
<a name="branding-designer-api-tools"></a>

对于托管登录品牌设置对象，Amazon Cognito 管理有一个 [JSON Schema 格式](https://json-schema.org/docs)的文件。以下是以编程方式更新品牌样式的步骤。

**在用户池 API 中更新品牌**

1. 在 Amazon Cognito 控制台中，从用户池的**托管登录**菜单中创建默认的托管登录品牌样式。将其分配给应用程序客户端。

1. 记录您为其创建样式的应用程序客户端的 ID，例如 `1example23456789`。

1. 使用设置为的 [DescribeManagedLoginBrandingByClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeManagedLoginBrandingByClient.html)API 请求检索品牌风格的`ReturnMergedResources`设置`true`。以下是一个示例 请求正文。

   ```
   {
      "ClientId": "1example23456789",
      "ReturnMergedResources": true,
      "UserPoolId": "us-east-1_EXAMPLE"
   }
   ```

1. 使用您的自定义设置修改 `DescribeManagedLoginBrandingByClient` 的输出。

   1. 响应正文包裹在一个 `ManagedLoginBranding` 元素中，该元素不属于创建和更新操作的语法部分。需要移除这个 JSON 对象的顶层结构。

   1. 要替换图像，请将 `Bytes` 值替换为每个图像文件的 Base64 编码二进制数据。

   1. 要更新设置，请修改 `Settings` 对象的输出，并将其包含在下一次请求中。Amazon Cognito 会忽略 `Settings` 对象中任何未包含在 API 响应所返回的架构中的值。

1. 在[CreateManagedLoginBranding](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateManagedLoginBranding.html)或[UpdateManagedLoginBranding](https://docs.aws.amazon.com/)请求中使用更新的响应正文。如果请求大小超过 2 MB，请将其拆分为多个请求。这些操作采用 `PATCH` 模式，除非您另行指定，否则原始设置将保持不变。

# 自定义托管 UI（经典）品牌
<a name="hosted-ui-classic-branding"></a>

您可以使用 AWS 管理控制台、 AWS CLI 或 API 为托管 UI 指定经典自定义设置。您可以上传要显示在应用程序中的自定义徽标图像。您还可以将层叠样式表（CSS）选项应用于 UI 的外观。

您可以自定义 UI 默认设置，并通过特定设置覆盖各个[应用程序客户端](cognito-terms.md#term-appclient)的设置。Amazon Cognito 会将默认配置应用于所有没有客户端级设置的应用程序客户端。

在 Amazon Cognito 控制台和 API 请求中，用于设置 UI 自定义的请求大小不得超过 135 KB。在极少数情况下，请求标头、您的 CSS 文件和徽标的大小总和可能超过 135 KB。Amazon Cognito 对图像文件进行 Base64 编码。这会将 100KB 大小的图像增加到 130KB，保留 5KB 用于请求标头和 CSS。如果请求太大， AWS 管理控制台 或您的 `SetUICustomization` API 请求将返回`request parameters too large`错误。请将您的徽标图像调整为不超过 100 KB，将 CSS 文件调整为不超过 3 KB。您无法单独设置 CSS 和徽标定制设置。

**注意**  
要自定义 UI，必须为用户池设置域。

## 在经典品牌中指定自定义徽标
<a name="cognito-user-pools-app-ui-customization-logo"></a>

Amazon Cognito 将您的自定义徽标放在 [登录端点](login-endpoint.md) 的输入字段上方居中。

为自定义托管 UI 徽标选择可缩放至 350 x 178 像素的 PNG、JPG 或 JPEG 文件。徽标文件的大小不得超过 100KB，或者在 Amazon Cognito 编码为 Base64 之后不超过 130KB。要在 API `ImageFile` [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUICustomization.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUICustomization.html)中设置，请将您的文件转换为 Base64 编码的文本字符串，或者在中提供文件路径并让 Amazon Cognito 为您对其进行编码。 AWS CLI

## 在经典品牌中指定 CSS 自定义项
<a name="cognito-user-pools-app-ui-customization-css"></a>

您可以为托管应用程序页面自定义 CSS，但存在以下限制：
+ 您可以使用以下任意 CSS 类名：
  + `background-customizable`
  + `banner-customizable`
  + `errorMessage-customizable`
  + `idpButton-customizable`
  + `idpButton-customizable:hover`
  + `idpDescription-customizable`
  + `inputField-customizable`
  + `inputField-customizable:focus`
  + `label-customizable`
  + `legalText-customizable`
  + `logo-customizable`
  + `passwordCheck-valid-customizable`
  + `passwordCheck-notValid-customizable`
  + `redirect-customizable`
  + `socialButton-customizable`
  + `submitButton-customizable`
  + `submitButton-customizable:hover`
  + `textDescription-customizable`
+ 属性值可以包含 HTML，但以下值除外：`@import`、`@supports`、`@page` 或者 `@media` 语句以及 Javascript。

您可以自定义以下 CSS 属性。

**标签**  
+ **font-weight** 是 100 的倍数 (从 100 到 900)。
+ **color** 是文本颜色。必须是[合法的 CSS 颜色值](https://www.w3schools.com/cssref/css_colors_legal.php)。

**输入字段**  
+ **width** 是以占包含块大小的百分比形式表示的宽度。
+ **height** 是输入字段的高度，以像素 (px) 为单位。
+ **color** 是文本颜色。它可以是任何标准 CSS 颜色值。
+ **background-color** 是输入字段的背景色。它可以是任何标准 CSS 颜色值。
+ **border** 是标准 CSS 边框值，用于指定您的应用程序窗口边框的宽度、透明度和颜色。宽度可以是从 1px 到 100px 的任何值。透明度可以是完全透明或不透明。颜色可以是任何标准颜色值。

**文本描述**  
+ **padding-top** 是文本描述上方的填充量。
+ **padding-bottom** 是文本描述下方的填充量。
+ **display** 可以是 `block` 或 `inline`。
+ **font-size** 是文本描述的字体大小。
+ **color** 是文本颜色。必须是[合法的 CSS 颜色值](https://www.w3schools.com/cssref/css_colors_legal.php)。

**提交按钮**  
+ **font-size** 是按钮文本的字体大小。
+ **font-weight** 是按钮文本的字体粗细：`bold`、`italic` 或 `normal`。
+ **页边距**是一个由四个值组成的字符串，用于指示按钮的上边距、右边距、下边距和左边距大小。
+ **font-size** 是文本描述的字体大小。
+ **width** 是按钮文本的宽度，以占包含块大小的百分比形式表示。
+ **height** 是按钮的高度，以像素 (px) 为单位。
+ **color** 是按钮文本颜色。它可以是任何标准 CSS 颜色值。
+ **background-color** 是按钮的背景色。它可以是任何标准颜色值。

**横幅**  
+ **填充**是一个由四个值组成的字符串，用于指示横幅的上边距、右边距、下边距和左边距大小。
+ **background-color** 是横幅的背景色。它可以是任何标准 CSS 颜色值。

**提交按钮悬停**  
+ **color** 是您将鼠标指针悬停在按钮上方时按钮的前景色。它可以是任何标准 CSS 颜色值。
+ **background-color** 是您将鼠标指针悬停在按钮上方时按钮的背景色。它可以是任何标准 CSS 颜色值。

**身份提供商按钮悬停**  
+ **color** 是您将鼠标指针悬停在按钮上方时按钮的前景色。它可以是任何标准 CSS 颜色值。
+ **background-color** 是您将鼠标指针悬停在按钮上方时按钮的背景色。它可以是任何标准 CSS 颜色值。

**密码校验无效**  
+ **color** 是 `"Password check not valid"` 消息的文本颜色。它可以是任何标准 CSS 颜色值。

**背景**  
+ **background-color** 是应用程序窗口的背景色。它可以是任何标准 CSS 颜色值。

**错误消息**  
+ **页边距**是一个由四个值组成的字符串，用于指示上边距、右边距、下边距和左边距大小。
+ **padding** 是边距大小。
+ **font-size** 是字体大小。
+ **width** 是错误消息的宽度，以占包含块大小的百分比形式表示。
+ **background** 是错误消息的背景色。它可以是任何标准 CSS 颜色值。
+ **边框**是一个由三个值组成的字符串，用于指定边框的宽度、透明度和颜色。
+ **color** 是错误消息文本颜色。它可以是任何标准 CSS 颜色值。
+ **box-sizing** 用于向浏览器指示应包含的大小属性 (宽度和高度)。

**身份提供商按钮**  
+ **height** 是按钮的高度，以像素 (px) 为单位。
+ **width** 是按钮文本的宽度，以占包含块大小的百分比形式表示。
+ **text-align** 是文本对齐设置。它可以是 `left`、`right` 或 `center`。
+ **margin-bottom** 是下边距设置。
+ **color** 是按钮文本颜色。它可以是任何标准 CSS 颜色值。
+ **background-color** 是按钮的背景色。它可以是任何标准 CSS 颜色值。
+ **border-color** 是按钮边框的颜色。它可以是任何标准 CSS 颜色值。

**身份提供商描述**  
+ **padding-top** 是描述上方的填充量。
+ **padding-bottom** 是描述下方的填充量。
+ **display** 可以是 `block` 或 `inline`。
+ **font-size** 是描述的字体大小。
+ **color** 是 IdP 区域标题的文本颜色，例如**使用您的企业账号登录**。必须是[合法的 CSS 颜色值](https://www.w3schools.com/cssref/css_colors_legal.php)。

**法律文本**  
+ **color** 是文本颜色。它可以是任何标准 CSS 颜色值。
+ **font-size** 是字体大小。
自定义 **Legal text**（法律文本）时，您自定义的是 **We won't post to any of your accounts without asking first**（如果未先询问，我们不会发布到您的任何账户）的消息，该消息显示在登录页面的社交身份提供商下方。

**Logo**  
+ **max-width** 是以占包含块大小的百分比形式表示的最大宽度。
+ **max-height** 是以占包含块大小的百分比形式表示的最大高度。
+ **background-color** 是包含透明区域的日志背景颜色。必须是[合法的 CSS 颜色值](https://www.w3schools.com/cssref/css_colors_legal.php)。

**输入字段聚焦**  
+ **border-color** 是输入字段的颜色。它可以是任何标准 CSS 颜色值。
+ **outline** 是输入字段的边框宽度 (以像素为单位)。

**社交按钮**  
+ **height** 是按钮的高度，以像素 (px) 为单位。
+ **text-align** 是文本对齐设置。它可以是 `left`、`right` 或 `center`。
+ **width** 是按钮文本的宽度，以占包含块大小的百分比形式表示。
+ **margin-bottom** 是下边距设置。

**密码校验有效**  
+ **color** 是 `"Password check valid"` 消息的文本颜色。它可以是任何标准 CSS 颜色值。

## 使用经典品牌自定义托管用户界面 AWS 管理控制台
<a name="cognito-user-pools-app-ui-customization-console"></a>

您可以使用为您的应用程序指定界面自定义设置。 AWS 管理控制台 

**注意**  
通过利用您的用户池的特定信息构建以下 URL 并将它键入到浏览器中，您可以查看具有自定义项的托管 UI：` https://<your_domain>/login?response_type=code&client_id=<your_app_client_id>&redirect_uri=<your_callback_url>` 在控制台中进行的更改出现之前，您可能必须等待长达 1 分钟才能刷新浏览器。  
您的域显示在 **App integration**（应用程序集成）选项卡中，该选项卡位于 **Domain**（域）下方。您的应用程序客户端 ID 和回调 URL 在 **App clients**（应用程序客户端）下显示。

**指定应用程序 UI 自定义设置**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。

1. 在导航窗格中，选择 **User Pools**（用户池），然后选择要编辑的用户池。

1. 在**域**选项卡中[创建域](cognito-user-pools-assign-domain.md)，或者更新现有域。在**品牌版本**下，将您的域设置为使用**托管 UI（经典）**。

1. 选择**托管登录**菜单。

1. 要为所有应用程序客户端自定义 UI 设置，请找到**托管 UI 设置**下的**样式**，然后选择**编辑**。

1. 要为某个应用程序客户端自定义 UI 设置，请转到**应用程序客户端**菜单，选择要修改的应用程序客户端，然后找到**托管 UI（经典）样式**并选择**覆盖**。选择**编辑**。

1. 要上载自己的徽标图像文件，请选择 **Choose file**（选择文件）或 **Replace current file**（替换当前文件）。

1. 要自定义托管 UI CSS，请下载 **CSS template.css**，然后使用您想要自定义的值修改模板。只有模板中包含的密钥才能与托管 UI 一起使用。添加的 CSS 密钥不会反映在您的 UI 中。自定义 CSS 文件后，请选择 **Choose file**（选择文件）或 **Replace current file**（替换当前文件）来上载您的自定义 CSS 文件。

## 使用用户池 API 中的经典品牌自定义托管用户界面，并使用 AWS CLI
<a name="cognito-user-pools-app-ui-customization-cli-api"></a>

使用以下命令可为您的用户池指定应用程序 UI 自定义项。

**使用以下 API 操作，获取用户池的内置应用程序 UI 的 UI 定制设置。**
+ AWS CLI: `aws cognito-idp get-ui-customization`
+ AWS API: [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUICustomization.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUICustomization.html)

**使用以下 API 操作，设置用户池的内置应用程序 UI 的 UI 定制设置。**
+ AWS CLI 来自图像文件：`aws cognito-idp set-ui-customization --user-pool-id <your-user-pool-id> --client-id <your-app-client-id> --image-file fileb://"<path-to-logo-image-file>" --css ".label-customizable{ color: <color>;}"`
+ AWS CLI 图像编码为 Base64 二进制文本：`aws cognito-idp set-ui-customization --user-pool-id <your-user-pool-id> --client-id <your-app-client-id> --image-file <base64-encoded-image-file> --css ".label-customizable{ color: <color>;}"`
+ AWS API: [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUICustomization.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUICustomization.html)

# 使用 Lambda 触发器自定义用户池工作流
<a name="cognito-user-pools-working-with-lambda-triggers"></a>

Amazon Cognito 使用 AWS Lambda 函数来修改用户池的身份验证行为。您可以将您的用户池配置为在用户首次注册之前、完成身份验证之后以及两者之间的几个阶段自动调用 Lambda 函数。您的函数可以修改身份验证流程的默认行为，发出 API 请求以修改您的用户池或其他 AWS 资源，以及与外部系统通信。您的 Lambda 函数中的代码是您自己的。Amazon Cognito 会将事件数据发送到您的函数，等待函数处理数据，而且在大多数情况下，预计会出现一个响应事件，该事件反映您要对会话进行的任何更改。

在请求和响应事件系统中，您可以引入自己的身份验证挑战、在您的用户池与其他身份存储之间迁移用户、自定义消息以及修改 JSON Web 令牌（JWTs）。

Lambda 触发器可以自定义用户在您的用户池中启动操作后 Amazon Cognito 向用户提供的响应。例如，您可以阻止原本会成功的用户登录。他们还可以对您的 AWS 环境、外部环境 APIs、数据库或身份存储执行运行时操作。例如，迁移用户触发器可以将外部操作与 Amazon Cognito 中的更改相结合：您可以在外部目录中查找用户信息，然后根据该外部信息设置新用户的属性。

当您为用户池分配 Lambda 触发器时，Amazon Cognito 会中断其原定设置流程，以从您的函数请求信息。Amazon Cognito 生成 JSON *事件*并将其传递给您的函数。该事件包含有关您的用户旨在创建用户账户、登录、重置密码或更新属性的请求的信息。然后，您的函数有机会采取行动，或者将事件原封不动地发回。未经修改返回的事件会通知您的用户池继续执行对该事件的默认操作。例如，您的注册前触发器可以自动确认用户是否使用 `PreSignUp_SignUp` 触发器源，但对于外部用户和管理员创建的用户，返回的事件保持不变。

下表总结了使用 Lambda 触发器自定义用户池操作的一些方法：


****  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)

**Topics**
+ [有关 Lambda 触发器的需知信息](#important-lambda-considerations)
+ [添加用户池 Lambda 触发器](#triggers-working-with-lambda)
+ [用户池 Lambda 触发器事件](#cognito-user-pools-lambda-trigger-event-parameter-shared)
+ [用户池 Lambda 触发器通用参数](#cognito-user-pools-lambda-trigger-syntax-shared)
+ [客户端元数据](#working-with-lambda-trigger-client-metadata)
+ [将 API 操作连接到 Lambda 触发器](#lambda-triggers-by-event)
+ [将 Lambda 触发器连接到用户池功能操作](#working-with-lambda-trigger-sources)
+ [注册前 Lambda 触发器](user-pool-lambda-pre-sign-up.md)
+ [确认后 Lambda 触发器](user-pool-lambda-post-confirmation.md)
+ [身份验证前 Lambda 触发器](user-pool-lambda-pre-authentication.md)
+ [身份验证后 Lambda 触发器](user-pool-lambda-post-authentication.md)
+ [入站联邦 Lambda 触发器](user-pool-lambda-inbound-federation.md)
+ [自定义身份验证质询 Lambda 触发器](user-pool-lambda-challenge.md)
+ [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md)
+ [迁移用户 Lambda 触发器](user-pool-lambda-migrate-user.md)
+ [自定义消息 Lambda 触发器](user-pool-lambda-custom-message.md)
+ [自定义发件人 Lambda 触发器](user-pool-lambda-custom-sender-triggers.md)

## 有关 Lambda 触发器的需知信息
<a name="important-lambda-considerations"></a>

在为 Lambda 函数准备用户池时，请考虑以下各项：
+ Amazon Cognito 发送到 Lambda 触发器的事件可能会随着新功能推出而发生变化。响应和请求元素在 JSON 层次结构中的位置可能改变，或者可能会添加元素名称。在 Lambda 函数中，您预期会收到本指南中介绍的输入元素键值对，但是更严格的输入验证可能会导致您的函数失败。
+ 您可以从 Amazon Cognito 发送到某些触发器的多个事件版本中选择一个。某些版本可能需要您接受对 Amazon Cognito 定价的更改。有关定价的更多信息，请参阅 [Amazon Cognito 定价](https://aws.amazon.com/cognito/pricing/)。要在[令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md)中自定义访问令牌，您必须使用*精简版*之外的功能计划对用户池进行配置，并更新 Lambda 触发器配置以使用事件版本 2。
+ Amazon Cognito 会同步调用 Lambda 函数，但 [自定义发件人 Lambda 触发器](user-pool-lambda-custom-sender-triggers.md) 除外。Amazon Cognito 调用您的 Lambda 函数时，函数必须在 5 秒内响应。如果不是，并且可以重试呼叫，Amazon Cognito 可能会重试该呼叫。如果所有重试尝试都失败，则该函数将超时。您无法更改此 5 秒钟超时值。有关更多信息，请参阅《 AWS Lambda 开发人员指南》中的 [Lambda 编程模型](https://docs.aws.amazon.com/lambda/latest/dg/foundation-progmodel.html)。

  Amazon Cognito 不会重试返回[调用错误](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_Errors)且 HTTP 状态代码为 500-599 的函数调用。这些代码表示配置问题导致 Lambda 无法启动该函数。有关更多信息，请参阅[中的错误处理和自动重试。 AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/invocation-retries.html)
+ 您无法在 Lambda 触发器配置中声明函数版本。默认情况下，Amazon Cognito 用户池会调用您的函数的最新版本。但是，您可以将函数版本与别名相关联，并在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求中`LambdaArn`将触发器设置为别名 ARN。此选项在 AWS 管理控制台中不可用。要了解有关别名的更多信息，请参阅《AWS Lambda 开发人员指南》**中的 [Lambda 函数别名](https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html)。
+ 如果您删除某个 Lambda 触发器，必须更新用户池中的相应触发器。例如，如果您删除身份验证后触发器，则必须在相应用户池中将 **Post authentication**（身份验证后）触发器设置为 **none**（无）。
+ 如果您的 Lambda 函数没有向 Amazon Cognito 返回请求和响应参数，或者返回错误，则身份验证事件将无法成功。您可以在函数中返回错误，以阻止用户注册、身份验证、令牌生成或其身份验证流程中任何其他调用 Lambda 触发器的阶段。

  托管登录将返回 Lambda 触发器生成的错误作为登录提示上方的错误文本。Amazon Cognito 用户池 API 以 `[trigger] failed with error [error text from response]` 格式返回触发器错误。最佳做法是，仅在 Lambda 函数中生成您希望用户看到的错误。使用输出方法`print()`，例如将任何敏感信息或调试信息 CloudWatch 记录到 Logs 中。有关示例，请参阅[注册前示例：如果用户名少于五个字符，则拒绝注册](user-pool-lambda-pre-sign-up.md#aws-lambda-triggers-pre-registration-example-3)。
+ 您可以在另一个函数中添加 Lambda 函数 AWS 账户 作为用户池的触发器。您必须使用[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)和 [UpdateUserPool](https://docs.aws.amazon.com/)API 操作添加跨账户触发器，或者在和中 CloudFormation 添加等效操作。 AWS CLI您无法在中添加跨账户功能。 AWS 管理控制台
+ 当您在 Amazon Cognito 控制台中添加 Lambda 触发器时，Amazon Cognito 会向您的函数添加一个基于资源的策略，允许您的用户池调用该函数。当您在 Amazon Cognito 控制台之外创建 Lambda 触发器（包括跨账户函数）时，您必须向 Lambda 函数的基于资源的策略添加权限。您添加的权限必须允许 Amazon Cognito 代表您的用户池调用函数。您可以[从 Lambda 控制台添加权限或使用 Lambd](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html) a API 操作。[AddPermission](https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html)

**Lambda 基于资源的策略示例**  
以下 Lambda 基于资源的策略示例授予 Amazon Cognito 有限调用 Lambda 函数的能力。Amazon Cognito 只能在代表 `aws:SourceArn` 中的用户池和 `aws:SourceAccount` 条件中的账户时才能调用函数。

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

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Id": "default",
      "Statement": [
          {
              "Sid": "LambdaCognitoIdpTrust",
              "Effect": "Allow",
              "Principal": {
                  "Service": "cognito-idp.amazonaws.com"
              },
              "Action": "lambda:InvokeFunction",
              "Resource": "arn:aws:lambda:us-east-1:111122223333:function:MyFunction",
              "Condition": {
                  "StringEquals": {
                      "AWS:SourceAccount": "111122223333"
                  },
                  "ArnLike": {
                      "AWS:SourceArn": "arn:aws:cognito-idp:us-east-1:111122223333:userpool/us-east-1_EXAMPLE"
                  }
              }
          }
      ]
  }
  ```

------

## 添加用户池 Lambda 触发器
<a name="triggers-working-with-lambda"></a>

**使用控制台添加用户池 Lambda 触发器**

1. 使用 [Lambda 控制台](https://console.aws.amazon.com/lambda/home)创建 Lambda 函数。有关 Lambda 函数的更多信息，请参阅《AWS Lambda 开发人员指南》[https://docs.aws.amazon.com/lambda/latest/dg/](https://docs.aws.amazon.com/lambda/latest/dg/)。

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)，然后选择 **User Pools**（用户池）。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**扩展**菜单并找到 **Lambda 触发器**。

1. 选择 **Add a Lambda trigger**（添加 Lambda 触发器）。

1. 基于您希望自定义的身份验证阶段，选择 Lambda 触发器 **Category**（类别）。

1. 选择 “**分配 Lambda 函数**”，然后选择与您的用户池 AWS 区域 相同的函数。
**注意**  
如果您的 AWS Identity and Access Management (IAM) 证书有权更新 Lambda 函数，则 Amazon Cognito 会添加基于 Lambda 资源的策略。通过此政策，Amazon Cognito 可以调用您选择的函数。如果登录凭证没有足够的 IAM 权限，则必须单独更新基于资源的策略。有关更多信息，请参阅 [有关 Lambda 触发器的需知信息](#important-lambda-considerations)。

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

1. 您可以在 Lambda 控制台 CloudWatch 中使用来记录您的 Lambda 函数。有关更多信息，请参阅[访问 Lambda 的 CloudWatch 日志](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-functions-logs.html)。

## 用户池 Lambda 触发器事件
<a name="cognito-user-pools-lambda-trigger-event-parameter-shared"></a>

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，Lambda 函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。如果您的函数返回未经修改的输入事件，Amazon Cognito 将继续执行默认行为。下面显示了所有 Lambda 触发器输入事件的通用参数。有关特定于触发器的事件语法，请查阅本指南中各触发器对应章节中的事件架构。

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

```
{
    "version": "string",
    "triggerSource": "string",
    "region": AWSRegion,
    "userPoolId": "string",
    "userName": "string",
    "callerContext": 
        {
            "awsSdkVersion": "string",
            "clientId": "string"
        },
    "request":
        {
            "userAttributes": {
                "string": "string",
                ....
            }
        },
    "response": {}
}
```

------

## 用户池 Lambda 触发器通用参数
<a name="cognito-user-pools-lambda-trigger-syntax-shared"></a>

**version**  
您的 Lambda 函数的版本号。

**triggerSource**  
触发 Lambda 函数的事件的名称。有关每个 triggerSource 的说明，请参阅[将 Lambda 触发器连接到用户池功能操作](#working-with-lambda-trigger-sources)。

**region**  
 AWS 区域 作为一个`AWSRegion`实例。

**userPoolId**  
用户池的 ID。

**userName**  
当前用户的用户名。

**callerContext**  
有关请求和代码环境的元数据。它包含字段**awsSdkVersion**和**客户端 ID**。    
**awsSdkVersion**  
生成请求的 AWS SDK 版本。  
****clientId****  
用户池应用程序客户端的 ID。

**request**  
您的用户的 API 请求的详细信息。它包括以下字段以及触发器特定的任何请求参数。例如，Amazon Cognito 发送到预身份验证触发器的事件也将包含一个 `userNotFound` 参数。当您的用户尝试使用未注册的用户名登录时，您可以处理此参数的值以执行自定义操作。    
**userAttributes**  
用户属性名称和值的一个或多个键值对，例如 `"email": "john@example.com"`。

**响应**  
此参数在原始请求中不包含任何信息。Lambda 函数必须将整个事件返回给 Amazon Cognito，并将任何返回参数添加到 `response`。要查看您的函数可以包含哪些返回参数，请参阅要使用的触发器的文档。

## 客户端元数据
<a name="working-with-lambda-trigger-client-metadata"></a>

您可以在 API 操作和[令牌端点](token-endpoint.md)请求中向 Lambda 触发器函数提交自定义参数。通过客户端元数据，您的应用程序可以收集有关请求来源环境的额外信息。当您将客户端元数据传递给您的 Lambda 函数时，它们可以处理这些附加数据，并将其用于日志记录或自定义身份验证流。客户端元数据是您选择和设计的字符串对，采用 JSON 键值格式。

**客户端元数据使用案例示例**
+ 在注册时将地理位置数据传递给[注册前触发器](user-pool-lambda-pre-sign-up.md)，并阻止来自非预期位置的登录请求。
+ 将租户 ID 数据传递给[自定义质询触发器](user-pool-lambda-challenge.md)，并向来自不同业务单位的客户发出不同的质询。
+ 将用户的令牌传递给[令牌生成前触发器](user-pool-lambda-pre-token-generation.md)，并生成日志，记录 M2M 请求所代表的主体。有关示例请求，请参阅[基本授权的客户端凭证POST 正文授权的客户端凭证](token-endpoint.md#exchanging-client-credentials-for-an-access-token-in-request-body)。

以下是向注册前触发器传递客户端元数据的一个示例。

------
#### [ SignUp request ]

以下是一个包含客户端元数据的示例[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html#CognitoUserPools-SignUp-request-ValidationData)请求，Amazon Cognito 会将其传递给注册前触发器。

```
POST HTTP/1.1
Host: cognito-idp.us-east-1.amazonaws.com
X-Amz-Date: 20230613T200059Z
Accept-Encoding: gzip, deflate, br
X-Amz-Target: AWSCognitoIdentityProviderService.SignUp
User-Agent: <UserAgentString>
Authorization: AWS4-HMAC-SHA256 Credential=<Credential>, SignedHeaders=<Headers>, Signature=<Signature>
Content-Length: <PayloadSizeBytes>

{
    "ClientId": "1example23456789",
    "Username": "mary_major",
    "Password": "<Password>",
    "SecretHash": "<Secret hash>",
    "ClientMetadata": { 
        "IpAddress" : "192.0.2.252",
        "GeoLocation" : "Netherlands (Kingdom of the) [NL]"
    }
    "UserAttributes": [
        {
            "Name": "name",
            "Value": "Mary"
        },
        {
            "Name": "email",
            "Value": "mary_major@example.com"
        },
        {
            "Name": "phone_number",
            "Value": "+12065551212"
        }
    ],
}
```

------
#### [ Lambda trigger input event ]

该请求会生成以下请求正文，并发送给您的注册前函数。

```
{
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "1example23456789"
    },
    "region": "us-west-2",
    "request": {
        "clientMetadata": {
            "GeoLocation": "Netherlands (Kingdom of the) [NL]",
            "IpAddress": "192.0.2.252"
        },
        "userAttributes": {
            "email": "mary_major@example.com",
            "name": "Mary",
            "phone_number": "+12065551212"
        },
        "validationData": null
    },
    "response": {
        "autoConfirmUser": false,
        "autoVerifyEmail": false,
        "autoVerifyPhone": false
    },
    "triggerSource": "PreSignUp_SignUp",
    "userName": "mary_major2",
    "userPoolId": "us-west-2_EXAMPLE",
    "version": "1"
}
```

------

**machine-to-machine(M2M) 客户端凭证的客户端元数据**  
您可以在 M2M 请求中传递[客户端元数据](#working-with-lambda-trigger-client-metadata)。客户端元数据是来自用户或应用程序环境的附加信息，可影响[令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md)的结果。在使用用户委托人的身份验证操作中，您可以将客户端元数据传递给 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)API 请求正文中的令牌生成前触发器。[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)由于应用程序通过直接向 [令牌端点](token-endpoint.md) 发出请求来执行为 M2M 生成访问令牌的流程，因此它们的模型不同。在客户端凭证令牌请求的 POST 正文中，传递一个 `aws_client_metadata` 参数，其值为客户端元数据对象经 URL 编码（`x-www-form-urlencoded`）后的字符串。有关示例请求，请参阅[基本授权的客户端凭证POST 正文授权的客户端凭证](token-endpoint.md#exchanging-client-credentials-for-an-access-token-in-request-body)。以下是传递键值对 `{"environment": "dev", "language": "en-US"}` 的参数的示例。

```
aws_client_metadata=%7B%22environment%22%3A%20%22dev%22,%20%22language%22%3A%20%22en-US%22%7D
```

**临时用户属性：`validationData`**  
一些身份验证操作也有一个 `validationData` 参数。与客户端元数据一样，这是一个将 Amazon Cognito 不会自动收集的外部信息传递给 Lambda 触发器的机会。验证数据字段旨在为您的 Lambda 函数提供注册和登录操作中的其他用户上下文。 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html#CognitoUserPools-SignUp-request-ValidationData)并[AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html#CognitoUserPools-AdminCreateUser-request-ValidationData)传递`validationData`到[注册前的触发器](user-pool-lambda-pre-sign-up.md)。 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-ClientMetadata)并像`ClientMetadata`在输入事件`validationData`中一样将 API 请求正文[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html#CognitoUserPools-AdminInitiateAuth-request-ClientMetadata)传递给[预身份验证](user-pool-lambda-pre-authentication.md)并[迁移用户](user-pool-lambda-migrate-user.md)触发器。

要将 API 操作映射到它们可以将客户端元数据传递到的函数，请参阅后面有关触发器源的章节。

## 将 API 操作连接到 Lambda 触发器
<a name="lambda-triggers-by-event"></a>

以下部分介绍 Amazon Cognito 从您的用户池中的活动调用的 Lambda 触发器。

当您的应用程序通过 Amazon Cognito 用户池 API、托管登录或用户池端点登录用户时，Amazon Cognito 会根据会话上下文调用您的 Lambda 函数。有关 Amazon Cognito 用户池 API 和用户池端点的更多信息，请参阅[了解 API、OIDC 和托管登录页面身份验证](authentication-flows-public-server-side.md#user-pools-API-operations)。以下各节中的表格描述了导致 Amazon Cognito 调用函数的事件，以及 Amazon Cognito 在请求中包含的 `triggerSource` 字符串。

**Topics**
+ [Amazon Cognito API 中的 Lambda 触发器](#lambda-triggers-native-users-native-api)
+ [托管登录中的 Amazon Cognito 本地用户的 Lambda 触发器](#lambda-triggers-native-users-hosted-UI)
+ [针对联合身份用户的 Lambda 触发器](#lambda-triggers-for-federated-users)

### Amazon Cognito API 中的 Lambda 触发器
<a name="lambda-triggers-native-users-native-api"></a>

下表描述了 Lambda 触发器的源字符串，当您的应用程序创建、登录或更新本地用户时，Amazon Cognito 可以调用这些触发器。


**Amazon Cognito API 中的本地用户触发器来源**  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)

### 托管登录中的 Amazon Cognito 本地用户的 Lambda 触发器
<a name="lambda-triggers-native-users-hosted-UI"></a>

下表描述了 Lambda 触发器的源字符串，当本地用户使用托管登录来登录到您的用户池时，Amazon Cognito 可以调用这些触发器。


**托管登录中的本地用户触发器源**  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)

### 针对联合身份用户的 Lambda 触发器
<a name="lambda-triggers-for-federated-users"></a>

您可以使用以下 Lambda 触发器，为使用联合身份提供商登录的用户自定义用户池工作流。

**注意**  
联合用户可以使用托管登录进行登录，也可以生成对[对端点授权](authorization-endpoint.md)的请求，以静默方式将它们重新导向到其身份提供者登录页面。您无法使用 Amazon Cognito 用户池 API 登录联合用户。


**联合身份用户触发器源**  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)

联合身份登录不会在您的用户池中调用任何 [自定义身份验证质询 Lambda 触发器](user-pool-lambda-challenge.md)、[迁移用户 Lambda 触发器](user-pool-lambda-migrate-user.md)、[自定义消息 Lambda 触发器](user-pool-lambda-custom-message.md) 或者[自定义发件人 Lambda 触发器](user-pool-lambda-custom-sender-triggers.md)。

## 将 Lambda 触发器连接到用户池功能操作
<a name="working-with-lambda-trigger-sources"></a>

每个 Lambda 触发器都在您的用户池中发挥功能作用。例如，触发器可以修改您的注册流程，或添加自定义身份验证质询。Amazon Cognito 发送到 Lambda 函数的事件可以反映构成该函数角色的多个操作之一。例如，当您的用户注册时以及当您创建用户时，Amazon Cognito 会调用预注册触发器。同一功能角色的每个不同案例都有其自身的 `triggerSource` 值。您的 Lambda 函数可以根据调用该函数的操作以不同的方式处理传入事件。

当事件对应于触发器源时，Amazon Cognito 还会调用所有分配的函数。例如，当用户登录到您分配了迁移用户和预身份验证触发器的用户池时，他们会同时激活这两个触发器。


**注册、确认和登录 (身份验证) 触发器**  

| 触发器 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 注册前 | PreSignUp\$1SignUp | 注册前。 | 
| 注册前 | PreSignUp\$1AdminCreateUser | 在管理员创建新用户时做好注册准备。 | 
| 注册前 | PreSignUp\$1ExternalProvider | 适用于外部身份提供商的注册前。 | 
| 发布确认 | PostConfirmation\$1ConfirmSignUp | 注册后确认。 | 
| 确认后 | PostConfirmation\$1ConfirmForgotPassword | 忘记密码后确认。 | 
| 身份验证前 | PreAuthentication\$1Authentication | 身份验证前。 | 
| 身份验证后 | PostAuthentication\$1Authentication | 身份验证后。 | 


**自定义身份验证质询触发器**  

| 触发器 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 定义身份验证质询 | DefineAuthChallenge\$1Authentication | 定义身份验证质询。 | 
| 创建身份验证质询 | CreateAuthChallenge\$1Authentication | 创建身份验证质询。 | 
| 验证身份验证质询 | VerifyAuthChallengeResponse\$1Authentication | 验证身份验证质询响应。 | 


**联邦触发器**  

| 触发器 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 入站联邦 | InboundFederation\$1ExternalProvider | 入站联合。 | 


**令牌生成前触发器**  

| 触发器 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 令牌生成前 | TokenGeneration\$1HostedAuth |  Amazon Cognito 从您的托管登录页面对用户进行身份验证。 | 
| 令牌生成前 | TokenGeneration\$1Authentication | 用户身份验证或令牌刷新已完成。 | 
| 令牌生成前 | TokenGeneration\$1NewPasswordChallenge | 管理员创建用户。当用户必须更改临时密码时，Amazon Cognito 调用此项。 | 
| 令牌生成前 | TokenGeneration\$1AuthenticateDevice | 结束用户设备身份验证。 | 
| 令牌生成前 | TokenGeneration\$1RefreshTokens | 用户尝试刷新身份和访问令牌时调用。 | 


**迁移用户触发器**  

| 触发器 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 用户迁移 | UserMigration\$1Authentication | 用户登录时进行迁移。 | 
| 用户迁移 | UserMigration\$1ForgotPassword | 忘记密码流程中的用户迁移。 | 


**自定义消息触发器**  

| 触发器 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 自定义消息 | CustomMessage\$1SignUp | 用户在您的用户池中注册时的自定义消息。 | 
| 自定义消息 | CustomMessage\$1AdminCreateUser | 当您创建用户作为管理员并且 Amazon Cognito 向他们发送临时密码时的自定义消息。 | 
| 自定义消息 | CustomMessage\$1ResendCode | 现有用户请求新的确认码时的自定义消息。 | 
| 自定义消息 | CustomMessage\$1ForgotPassword | 用户请求重置密码时的自定义消息。 | 
| 自定义消息 | CustomMessage\$1UpdateUserAttribute | 用户更改其电子邮件地址或电话号码并且 Amazon Cognito 发送验证码时的自定义消息。 | 
| 自定义消息 | CustomMessage\$1VerifyUserAttribute | 用户添加电子邮件地址或电话号码并且 Amazon Cognito 发送验证码时的自定义消息。 | 
| 自定义消息 | CustomMessage\$1Authentication | 配置了 SMS MFA 的用户登录时的自定义消息。 | 


**自定义发件人触发器**  

| 触发器 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 自定义发件人 |  `CustomEmailSender_SignUp` `CustomSmsSender_SignUp`  | 用户在您的用户池中注册。 | 
| 自定义发件人 |  `CustomEmailSender_AdminCreateUser` `CustomSmsSender_AdminCreateUser`  | 您以管理员身份创建用户并且 Amazon Cognito 向他们发送临时密码。 | 
| 自定义发件人 |  `CustomEmailSender_ForgotPassword` `CustomSmsSender_ForgotPassword`  | 用户请求重置密码。 | 
| 自定义发件人 |  `CustomEmailSender_UpdateUserAttribute` `CustomSmsSender_UpdateUserAttribute`  | 用户更改其电子邮件地址或电话号码并且 Amazon Cognito 发送验证码。 | 
| 自定义发件人 |  `CustomEmailSender_VerifyUserAttribute` `CustomSmsSender_VerifyUserAttribute`  | 用户添加电子邮件地址或电话号码并且 Amazon Cognito 发送验证码。 | 
| 自定义发件人 |  `CustomEmailSender_Authentication` `CustomSmsSender_Authentication`  | 配置了短信、电子邮件 MFA 或 OTP 的用户登录。 | 
| 自定义发件人 | CustomEmailSender\$1AccountTakeOverNotification | 您的威胁防护设置对用户的登录尝试采取自动操作并且针对风险级别的操作包括通知。 | 

# 注册前 Lambda 触发器
<a name="user-pool-lambda-pre-sign-up"></a>

您可能想要在具有自助注册选项的用户池中自定义注册流程。注册前触发器的一些常见用途包括对新用户进行自定义分析和记录、应用安全和治理标准，或者将第三方 IdP 的用户链接到[整合的用户配置文件](cognito-user-pools-identity-federation-consolidate-users.md)。您可能还有不需要进行[验证和确认](signing-up-users-in-your-app.md)的可信用户。

在 Amazon Cognito 完成创建新的[本地](cognito-terms.md#terms-localuser)用户或[联合](cognito-terms.md#terms-federateduser)用户之前不久，它会激活注册前 Lambda 函数。发送给此函数的请求对象中的 `userAttributes` 包含本地用户注册时提供的属性，或已成功从联合用户的身份提供者属性映射过来的属性。在使用可信[身份提供商](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-federated)进行自助注册[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)或首次登录时，以及使用创建用户时，您的用户池会调用此触发器。[AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html)在注册过程中，您可以使用此函数，利用自定义逻辑来分析登录事件，并修改或拒绝新用户。

**Topics**
+ [注册前 Lambda 触发器参数](#cognito-user-pools-lambda-trigger-syntax-pre-signup)
+ [注册前示例：从注册的域自动确认用户](#aws-lambda-triggers-pre-registration-example)
+ [注册前示例：自动确认和自动验证所有用户](#aws-lambda-triggers-pre-registration-example-2)
+ [注册前示例：如果用户名少于五个字符，则拒绝注册](#aws-lambda-triggers-pre-registration-example-3)

## 注册前 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-pre-signup"></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",
            . . .
        },
        "validationData": {
            "string": "string",
            . . .
         },
        "clientMetadata": {
            "string": "string",
            . . .
         }
    },

    "response": {
        "autoConfirmUser": "boolean",
        "autoVerifyPhone": "boolean",
        "autoVerifyEmail": "boolean"
    }
}
```

------

### 注册前请求参数
<a name="cognito-user-pools-lambda-trigger-syntax-pre-signup-request"></a>

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

**validationData**  
一个或多个包含用户属性数据的键值对，您的应用程序在创建新用户的请求中将这些数据传递给 Amazon Cognito。在您[AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html)或 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)API 请求的 ValidationData 参数中将此信息发送到您的 Lambda 函数。  
Amazon Cognito 不会将你的 ValidationData 数据设置为你创建的用户的属性。 ValidationData 是您为注册前 Lambda 触发器而提供的临时用户信息。

**clientMetadata**  
一个或多个键值对，您可以将其作为自定义输入内容提供给为注册前触发器指定的 Lambda 函数。您可以使用以下 API 操作中的 ClientMetadata参数将此数据传递给您的 Lambda 函数：[AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html)、[AdminRespondToAuthChallenge[ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)、和。[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)

### 注册前响应参数
<a name="cognito-user-pools-lambda-trigger-syntax-pre-signup-response"></a>

在响应中，如果您想要自动确认用户，则您可以将 `autoConfirmUser` 设置为 `true`。您可以将 `autoVerifyEmail` 设置为 `true`，以自动验证用户的电子邮件。您可以将 `autoVerifyPhone` 设置为 `true`，以自动验证用户的电话号码。

**注意**  
`AdminCreateUser` API 触发注册前 Lambda 函数时，Amazon Cognito 会忽略响应参数 `autoVerifyPhone`、`autoVerifyEmail` 和 `autoConfirmUser`。

**autoConfirmUser**  
设置为 `true` 以自动确认用户，否则设置为 `false`。

**autoVerifyEmail**  
设置为 `true` 可以设置为所注册用户已通过验证的电子邮件地址，否则为 `false`。如果 `autoVerifyEmail` 设置为 `true`，则 `email` 属性必须具有有效的非空值。否则将出现错误，用户将无法完成注册。  
如果选择 `email` 属性作为别名，则在设置了 `autoVerifyEmail` 时将为用户的电子邮件地址创建别名。如果已存在具有该电子邮件地址的别名，则别名将移动到新用户，以前用户的电子邮件地址将标记为未验证。有关更多信息，请参阅 [自定义登录属性](user-pool-settings-attributes.md#user-pool-settings-aliases)。

**autoVerifyPhone**  
设置为 `true` 可以设置为所注册用户已通过验证的电话号码，否则为 `false`。如果 `autoVerifyPhone` 设置为 `true`，则 `phone_number` 属性必须具有有效的非空值。否则将出现错误，用户将无法完成注册。  
如果选择 `phone_number` 属性作为别名，则在设置了 `autoVerifyPhone` 时将为用户的电话号码创建别名。如果已存在具有该电话号码的别名，则别名将移动到新用户，以前用户的电话号码将标记为未验证。有关更多信息，请参阅 [自定义登录属性](user-pool-settings-attributes.md#user-pool-settings-aliases)。

## 注册前示例：从注册的域自动确认用户
<a name="aws-lambda-triggers-pre-registration-example"></a>

这是 Lambda 触发器代码的示例。在 Amazon Cognito 处理注册请求之前不久，注册前触发器会被调用。它使用自定义属性 **custom:domain** 自动确认来自特定电子邮件域的新用户。任何不在自定义域中的新用户都将添加到用户池，但不会自动确认。

------
#### [ Node.js ]

```
export const handler = async (event, context, callback) => {
  // Set the user pool autoConfirmUser flag after validating the email domain
  event.response.autoConfirmUser = false;

  // Split the email address so we can compare domains
  var address = event.request.userAttributes.email.split("@");

  // This example uses a custom attribute "custom:domain"
  if (event.request.userAttributes.hasOwnProperty("custom:domain")) {
    if (event.request.userAttributes["custom:domain"] === address[1]) {
      event.response.autoConfirmUser = true;
    }
  }

  // Return to Amazon Cognito
  callback(null, event);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    # It sets the user pool autoConfirmUser flag after validating the email domain
    event['response']['autoConfirmUser'] = False

    # Split the email address so we can compare domains
    address = event['request']['userAttributes']['email'].split('@')

    # This example uses a custom attribute 'custom:domain'
    if 'custom:domain' in event['request']['userAttributes']:
        if event['request']['userAttributes']['custom:domain'] == address[1]:
            event['response']['autoConfirmUser'] = True

    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
    "request": {
        "userAttributes": {
            "email": "testuser@example.com",
            "custom:domain": "example.com"
        }
    },
    "response": {}
}
```

------

## 注册前示例：自动确认和自动验证所有用户
<a name="aws-lambda-triggers-pre-registration-example-2"></a>

此示例确认所有用户并将用户的 `email` 和 `phone_number` 属性设置为“已验证”（如果该属性存在）。此外，如果启用了别名，当设置了自动验证时，将为 `phone_number` 和 `email` 创建别名。

**注意**  
如果已存在具有相同电话号码的别名，则别名将移动到新用户，以前用户的 `phone_number` 将标记为未验证。电子邮件地址也是如此。为了防止这种情况发生，您可以使用用户池 [ListUsers API](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html) 来查看是否有现有用户已在使用新用户的电话号码或电子邮件地址作为别名。

------
#### [ Node.js ]

```
exports.handler = (event, context, callback) => {
  // Confirm the user
  event.response.autoConfirmUser = true;

  // Set the email as verified if it is in the request
  if (event.request.userAttributes.hasOwnProperty("email")) {
    event.response.autoVerifyEmail = true;
  }

  // Set the phone number as verified if it is in the request
  if (event.request.userAttributes.hasOwnProperty("phone_number")) {
    event.response.autoVerifyPhone = true;
  }

  // Return to Amazon Cognito
  callback(null, event);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    # Confirm the user
    event['response']['autoConfirmUser'] = True

    # Set the email as verified if it is in the request
    if 'email' in event['request']['userAttributes']:
        event['response']['autoVerifyEmail'] = True

    # Set the phone number as verified if it is in the request
    if 'phone_number' in event['request']['userAttributes']:
        event['response']['autoVerifyPhone'] = True

    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
  "request": {
    "userAttributes": {
      "email": "user@example.com",
      "phone_number": "+12065550100"
    }
  },
  "response": {}
}
```

------

## 注册前示例：如果用户名少于五个字符，则拒绝注册
<a name="aws-lambda-triggers-pre-registration-example-3"></a>

此示例检查注册请求中用户名的长度。如果用户输入的名称长度少于五个字符，则该示例将返回错误。

------
#### [ Node.js ]

```
export const handler = (event, context, callback) => {
    // Impose a condition that the minimum length of the username is 5 is imposed on all user pools.
    if (event.userName.length < 5) {
        var error = new Error("Cannot register users with username less than the minimum length of 5");
        // Return error to Amazon Cognito
        callback(error, event);
    }
    // Return to Amazon Cognito
    callback(null, event);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    if len(event['userName']) < 5:
        raise Exception("Cannot register users with username less than the minimum length of 5")
    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
  "userName": "rroe",
  "response": {}
}
```

------

# 确认后 Lambda 触发器
<a name="user-pool-lambda-post-confirmation"></a>

Amazon Cognito 会在注册用户确认其用户账户后调用此触发器。在您的确认后 Lambda 函数中，您可以发送自定义消息或添加自定义 API 请求。例如，您可以查询外部系统并为用户填充其他属性。Amazon Cognito 仅对在您的用户池中注册的用户调用此触发器，而不会针对您使用管理员凭证创建的用户账户调用此触发器。

请求包含已确认用户的当前属性。您的用户池在[ConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html)、[AdminConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminConfirmSignUp.html)和上调用您的帖子确认功能。[ConfirmForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html)当用户在[托管登录](cognito-user-pools-managed-login.md)中确认注册或密码重置时，此触发器也会运行。

**Topics**
+ [确认后 Lambda 触发器参数](#cognito-user-pools-lambda-trigger-syntax-post-confirmation)
+ [确认后示例](#aws-lambda-triggers-post-confirmation-example)

## 确认后 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-post-confirmation"></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",
                . . .
            },
            "clientMetadata": {
            	"string": "string",
            	. . .
            }
        },
    "response": {}
}
```

------

### 确认后请求参数
<a name="cognito-user-pools-lambda-trigger-syntax-post-confirmation-request"></a>

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

**clientMetadata**  
一个或多个键值对，您可以将其作为自定义输入内容提供给为确认后触发器指定的 Lambda 函数。您可以使用以下 API 操作中的 ClientMetadata 参数将此数据传递给您的 Lambda 函数：[AdminConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminConfirmSignUp.html)、[ConfirmForgotPassword[ConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html)、和。[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)

### 确认后响应参数
<a name="cognito-user-pools-lambda-trigger-syntax-post-confirmation-response"></a>

预计响应中没有其他返回信息。

## 确认后示例
<a name="aws-lambda-triggers-post-confirmation-example"></a>

此示例 Lambda 函数将使用 Amazon SES 向用户发送确认电子邮件。有关更多信息，请参阅 [Amazon Simple Email Service 开发人员指南](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/)。

------
#### [ Node.js ]

```
// Import required AWS SDK clients and commands for Node.js. Note that this requires
// the `@aws-sdk/client-ses` module to be either bundled with this code or included
// as a Lambda layer.
import { SES, SendEmailCommand } from "@aws-sdk/client-ses";
const ses = new SES();

const handler = async (event) => {
  if (event.request.userAttributes.email) {
    await sendTheEmail(
      event.request.userAttributes.email,
      `Congratulations ${event.userName}, you have been confirmed.`,
    );
  }
  return event;
};

const sendTheEmail = async (to, body) => {
  const eParams = {
    Destination: {
      ToAddresses: [to],
    },
    Message: {
      Body: {
        Text: {
          Data: body,
        },
      },
      Subject: {
        Data: "Cognito Identity Provider registration completed",
      },
    },
    // Replace source_email with your SES validated email address
    Source: "<source_email>",
  };
  try {
    await ses.send(new SendEmailCommand(eParams));
  } catch (err) {
    console.log(err);
  }
};

export { handler };
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
    "request": {
        "userAttributes": {
            "email": "user@example.com",
            "email_verified": true
        }
    },
    "response": {}
}
```

------

# 身份验证前 Lambda 触发器
<a name="user-pool-lambda-pre-authentication"></a>

当用户尝试登录时，Amazon Cognito 会调用此触发器，以便您可以创建用于执行准备操作的自定义验证。例如，您可以拒绝身份验证请求或将会话数据记录到外部系统。

**注意**  
此 Lambda 触发器在用户不存在时不会激活，除非将用户池应用程序客户端的 `PreventUserExistenceErrors` 设置设为 `ENABLED`。续订现有身份验证会话也不会激活此触发器。

**Topics**
+ [流程概述](#user-pool-lambda-pre-authentication-1)
+ [身份验证前 Lambda 触发器参数](#cognito-user-pools-lambda-trigger-syntax-pre-auth)
+ [身份验证前示例](#aws-lambda-triggers-pre-authentication-example)

## 流程概述
<a name="user-pool-lambda-pre-authentication-1"></a>

![\[身份验证前 Lambda 触发器 – 客户端流程\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/lambda-pre-authentication-1.png)


该请求包含来自 `ClientMetadata` 值的客户端验证数据，该值由应用程序传递到用户池 `InitiateAuth` 和 `AdminInitiateAuth` API 操作。

有关更多信息，请参阅 [身份验证会话示例](authentication.md#amazon-cognito-user-pools-authentication-flow)。

## 身份验证前 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-pre-auth"></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",
            . . .
        },
        "validationData": {
            "string": "string",
            . . .
        },
        "userNotFound": boolean
    },
    "response": {}
}
```

------

### 身份验证前请求参数
<a name="cognito-user-pools-lambda-trigger-syntax-pre-auth-request"></a>

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

**userNotFound**  
当您将用户池客户端的 `PreventUserExistenceErrors` 设置为 `ENABLED` 时，Amazon Cognito 将填充此布尔值。

**validationData**  
一个或多个键/值对，包含用户的登录请求中的验证数据。要将此数据传递给您的 Lambda 函数，请使用[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)和 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)API 操作中的 ClientMetadata 参数。

### 身份验证前响应参数
<a name="cognito-user-pools-lambda-trigger-syntax-pre-auth-response"></a>

Amazon Cognito 不处理您的函数在响应中返回的任何附加信息。您的函数可以返回错误以拒绝登录尝试，或者使用 API 操作来查询和修改资源。

## 身份验证前示例
<a name="aws-lambda-triggers-pre-authentication-example"></a>

此示例函数阻止用户使用特定的应用程序客户端登录到您的用户池。由于预身份验证 Lambda 函数不会在您的用户有现有会话时调用，因此，此函数仅阻止使用您想要屏蔽的应用程序客户端 ID 的*新*会话。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (
    event.callerContext.clientId === "user-pool-app-client-id-to-be-blocked"
  ) {
    throw new Error("Cannot authenticate users from this user pool app client");
  }

  return event;
};

export { handler };
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    if event['callerContext']['clientId'] == "<user pool app client id to be blocked>":
        raise Exception("Cannot authenticate users from this user pool app client")

    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
    "callerContext": {
        "clientId": "<user pool app client id to be blocked>"
    },
    "response": {}
}
```

------

# 身份验证后 Lambda 触发器
<a name="user-pool-lambda-post-authentication"></a>

身份验证后触发器不会更改用户的身份验证流程。Amazon Cognito 会在身份验证完成后，在用户收到令牌之前调用此 Lambda。当您想要添加身份验证事件的自定义后处理时（例如，将在下次登录时反映的日志记录或用户配置文件调整），请添加身份验证后触发器。

不将请求正文返回给 Amazon Cognito 的身份验证后 Lambda 仍会导致身份验证无法完成。有关更多信息，请参阅 [有关 Lambda 触发器的需知信息](cognito-user-pools-working-with-lambda-triggers.md#important-lambda-considerations)。

**Topics**
+ [身份验证流概述](#user-pool-lambda-post-authentication-1)
+ [身份验证后 Lambda 触发器参数](#cognito-user-pools-lambda-trigger-syntax-post-auth)
+ [身份验证后示例](#aws-lambda-triggers-post-authentication-example)

## 身份验证流概述
<a name="user-pool-lambda-post-authentication-1"></a>

![\[身份验证后 Lambda 触发器 – 客户端流程\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/lambda-post-authentication-1.png)


有关更多信息，请参阅 [身份验证会话示例](authentication.md#amazon-cognito-user-pools-authentication-flow)。

## 身份验证后 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-post-auth"></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",
             . . .
         },
         "newDeviceUsed": boolean,
         "clientMetadata": {
             "string": "string",
             . . .
            }
        },
    "response": {}
}
```

------

### 身份验证后请求参数
<a name="cognito-user-pools-lambda-trigger-syntax-post-auth-request"></a>

**newDeviceUsed**  
此标记指示用户是否已在新设备上登录。Amazon Cognito 仅在用户池的记住的设备值设置为 `Always` 或 `User Opt-In` 时设置此标记。

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

**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参数。Amazon Cognito 在传递给身份验证后函数的请求中不包含来自 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)API 操作的数据。

### 身份验证后响应参数
<a name="cognito-user-pools-lambda-trigger-syntax-post-auth-response"></a>

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

## 身份验证后示例
<a name="aws-lambda-triggers-post-authentication-example"></a>

此身份验证后示例 Lambda 函数将成功登录后的数据发送到日志。 CloudWatch 

------
#### [ Node.js ]

```
const handler = async (event) => {
  // Send post authentication data to Amazon CloudWatch logs
  console.log("Authentication successful");
  console.log("Trigger function =", event.triggerSource);
  console.log("User pool = ", event.userPoolId);
  console.log("App client ID = ", event.callerContext.clientId);
  console.log("User ID = ", event.userName);

  return event;
};

export { handler };
```

------
#### [ Python ]

```
import os
def lambda_handler(event, context):

    # Send post authentication data to Cloudwatch logs
    print ("Authentication successful")
    print ("Trigger function =", event['triggerSource'])
    print ("User pool = ", event['userPoolId'])
    print ("App client ID = ", event['callerContext']['clientId'])
    print ("User ID = ", event['userName'])

    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
  "triggerSource": "testTrigger",
  "userPoolId": "testPool",
  "userName": "testName",
  "callerContext": {
      "clientId": "12345"
  },
  "response": {}
}
```

------

# 入站联邦 Lambda 触发器
<a name="user-pool-lambda-inbound-federation"></a>

在使用外部身份提供商进行身份验证的过程中，入站联合身份触发器会转换联合用户属性。当用户通过配置的身份提供商进行身份验证时，此触发器允许您通过拦截和转换身份验证过程中的数据来修改来自外部 SAML 和 OIDC 提供商的响应，从而对 Amazon Cognito 用户池处理联合用户及其属性的方式进行编程控制。

在创建新用户或更新现有联合用户配置文件之前，使用此触发器添加、覆盖或隐藏属性。此触发器接收原始身份提供者属性作为输入，并返回 Amazon Cognito 应用于用户个人资料的修改属性。

**Topics**
+ [流程概述](#cognito-user-pools-lambda-trigger-inbound-federation-flow)
+ [入站联邦 Lambda 触发器参数](#cognito-user-pools-lambda-trigger-syntax-inbound-federation)
+ [入站联盟示例：群组成员资格管理](#aws-lambda-triggers-inbound-federation-example-groups)
+ [入站联合示例：截断大型属性](#aws-lambda-triggers-inbound-federation-example-truncate)
+ [入站联合示例：记录联合事件](#aws-lambda-triggers-inbound-federation-example-logging)

## 流程概述
<a name="cognito-user-pools-lambda-trigger-inbound-federation-flow"></a>

当用户通过外部身份提供商进行身份验证时，Amazon Cognito 会在创建或更新用户个人资料之前调用入站联合触发器。触发器从身份提供者那里接收原始属性，并可以在 Amazon Cognito 存储它们之前对其进行转换。对于新的联合用户和通过联合身份再次登录的现有用户，都会出现此流程。

![\[入站联邦 Lambda 触发流程\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/lambda-inbound-federation.png)


## 入站联邦 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-inbound-federation"></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 ]

```
{
    "version": "string",
    "triggerSource": "InboundFederation_ExternalProvider",
    "region": AWSRegion,
    "userPoolId": "string",
    "userName": "string",
    "callerContext": {
        "awsSdkVersion": "string",
        "clientId": "string"
    },
    "request": {
        "providerName": "string",
        "providerType": "string",
        "attributes": {
            "tokenResponse": {
                "access_token": "string",
                "token_type": "string",
                "expires_in": "string"
            },
            "idToken": {
                "sub": "string",
                "email": "string",
                "email_verified": "string"
            },
            "userInfo": {
                "email": "string",
                "given_name": "string",
                "family_name": "string"
            },
            "samlResponse": {
                "string": "string"
            }
        }
    },
    "response": {
        "userAttributesToMap": {
            "string": "string"
        }
    }
}
```

------

### 入站联盟请求参数
<a name="cognito-user-pools-lambda-trigger-syntax-inbound-federation-request"></a>

**提供者名称**  
外部身份提供商的名称。

**提供者类型**  
外部身份提供商的类型。有效值：`OIDC`、`SAML`、`Facebook`、`Google`、`SignInWithApple`、`LoginWithAmazon`。

**属性**  
处理前从身份提供者那里收到的原始属性。结构因提供商类型而异。

**属性。TokenResponse**  
OAuth 来自`/token`端点的令牌响应数据。仅适用于 OIDC 和社交服务提供商。包含`access_token``id_token`、`refresh_token`、`token_type`、`expires_in`、和`scope`。

**属性.idToken**  
经过解码和验证的 ID 令牌 JWT 声明。仅适用于 OIDC 和社交服务提供商。包含经过验证的用户身份信息，包括`sub`（唯一用户标识符）`email``name`、、`iss`（发行者）、`aud`（受众）、`exp`（到期）和`iat`（发布时间）。

**属性.userInfo**  
来自 UserInfo 端点的扩展用户配置文件信息。仅适用于 OIDC 和社交服务提供商。包含详细的配置文件属性`given_name`，例如、`family_name`、`picture``address`、和其他提供商特定的字段。如果 IdP 不支持 UserInfo 终端节点或端点调用失败，则可能为空。

**属性.samlResponse**  
SAML 断言属性。仅适用于 SAML 提供商。包含来自 SAML 响应的属性。

### 入站联盟响应参数
<a name="cognito-user-pools-lambda-trigger-syntax-inbound-federation-response"></a>

**userAttributesTo地图**  
要应用于用户配置文件的用户属性。

**重要**  
您必须在响应中包含要保留的所有用户属性，包括您未修改的属性。任何未包含在`userAttributesToMap`响应中的属性都将被删除且不会存储在用户配置文件中。这既适用于已修改的属性，也适用于未修改的属性。

**空响应行为**  
如果您`{}`为返回一个空对象`userAttributesToMap`，则身份提供者的所有原始属性都将保持不变。这相当于禁用操作，就像 Lambda 函数从未执行过一样。这与省略属性不同，后者会丢弃这些属性。

**提供商特定的属性**  
的结构`request.attributes`因而异`providerType`. OIDC 和社交提供者包括`tokenResponse``idToken`、和对象。`userInfo`SAML 提供程序仅包含`samlResponse`对象。

## 入站联盟示例：群组成员资格管理
<a name="aws-lambda-triggers-inbound-federation-example-groups"></a>

此示例说明如何将联合身份提供商组映射到 Amazon Cognito 用户池群组。此函数从联合响应中提取群组成员资格，并自动将用户添加到相应的 Amazon Cognito 群组，无需在身份验证后触发器。

------
#### [ Node.js ]

```
exports.handler = async (event) => {
    const { providerType, attributes } = event.request;
    
    // Extract user attributes based on provider type
    let userAttributesFromIdp = {};
    if (providerType === 'SAML') {
        userAttributesFromIdp = attributes.samlResponse || {};
    } else {
        // For OIDC and Social providers, merge userInfo and idToken
        userAttributesFromIdp = {
            ...(attributes.userInfo || {}),
            ...(attributes.idToken || {})
        };
    }
    
    // Extract groups from federated response
    const federatedGroups = userAttributesFromIdp.groups?.split(',') || [];
    
    // Map federated groups to Cognito groups
    const groupMapping = {
        'Domain Admins': 'Administrators',
        'Engineering': 'Developers',
        'Sales': 'SalesTeam'
    };
    
    // Filter to only in-scope groups
    const mappedGroups = federatedGroups
        .map(group => groupMapping[group.trim()])
        .filter(group => group); // Remove undefined values
    
    // Pass through attributes with mapped groups as custom attribute
    const attributesToMap = {
        ...userAttributesFromIdp,
        'custom:user_groups': mappedGroups.join(',')
    };
    
    // Remove original groups attribute
    delete attributesToMap.groups;
    
    event.response.userAttributesToMap = attributesToMap;
    return event;
};
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
    "userPoolId": "us-east-1_XXXXXXXXX",
    "request": {
        "providerName": "CorporateAD",
        "providerType": "SAML",
        "attributes": {
            "samlResponse": {
                "email": "jane.smith@company.com",
                "given_name": "Jane",
                "family_name": "Smith",
                "groups": "Engineering,Domain Admins",
                "department": "Engineering"
            }
        }
    },
    "response": {
        "userAttributesToMap": {}
    }
}
```

------

## 入站联合示例：截断大型属性
<a name="aws-lambda-triggers-inbound-federation-example-truncate"></a>

此示例说明如何截断超过 Amazon Cognito 存储限制的属性值。此函数检查身份提供商提供的每个属性。如果属性值超过 2048 个字符，则会截断该值并添加省略号以表示截断。所有其他属性均保持不变。

------
#### [ Node.js ]

```
exports.handler = async (event) => {
    const MAX_ATTRIBUTE_LENGTH = 2048;
    
    // Get the identity provider attributes based on provider type
    const { providerType, attributes } = event.request;
    let idpAttributes = {};
    
    if (providerType === 'SAML') {
        idpAttributes = attributes.samlResponse || {};
    } else {
        // For OIDC and Social providers, merge userInfo and idToken
        idpAttributes = {
            ...(attributes.userInfo || {}),
            ...(attributes.idToken || {})
        };
    }
    
    const userAttributes = {};
    
    // Process each attribute
    for (const [key, value] of Object.entries(idpAttributes)) {
        if (typeof value === 'string' && value.length > MAX_ATTRIBUTE_LENGTH) {
            // Truncate the value and add ellipsis
            userAttributes[key] = value.substring(0, MAX_ATTRIBUTE_LENGTH - 3) + '...';
            console.log(`Truncated attribute ${key} from ${value.length} to ${userAttributes[key].length} characters`);
        } else {
            // Keep the original value
            userAttributes[key] = value;
        }
    }
    
    // Return the modified attributes
    event.response.userAttributesToMap = userAttributes;
    return event;
};
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
    "version": "string",
    "triggerSource": "InboundFederation_ExternalProvider",
    "region": "us-east-1",
    "userPoolId": "us-east-1_XXXXXXXXX",
    "userName": "ExampleProvider_12345",
    "callerContext": {
        "awsSdkVersion": "string",
        "clientId": "string"
    },
    "request": {
        "providerName": "ExampleProvider",
        "providerType": "OIDC",
        "attributes": {
            "tokenResponse": {
                "access_token": "abcDE...",
                "token_type": "Bearer",
                "expires_in": "3600"
            },
            "idToken": {
                "sub": "12345",
                "email": "user@example.com"
            },
            "userInfo": {
                "email": "user@example.com",
                "given_name": "Example",
                "family_name": "User",
                "bio": "This is a very long biography that contains more than 2048 characters..."
            }
        }
    },
    "response": {
        "userAttributesToMap": {}
    }
}
```

------

## 入站联合示例：记录联合事件
<a name="aws-lambda-triggers-inbound-federation-example-logging"></a>

此示例说明如何记录联合身份验证事件以进行监控和调试。此示例函数捕获有关联合用户及其属性的详细信息，从而提供对身份验证过程的可见性。

------
#### [ Node.js ]

```
exports.handler = async (event) => {
    const { providerName, providerType, attributes } = event.request;
    
    // Extract user attributes based on provider type
    let userAttributesFromIdp = {};
    if (providerType === 'SAML') {
        userAttributesFromIdp = attributes.samlResponse || {};
    } else {
        // For OIDC and Social providers, merge userInfo and idToken
        userAttributesFromIdp = {
            ...(attributes.userInfo || {}),
            ...(attributes.idToken || {})
        };
    }
    
    // Log federated authentication details
    console.log(JSON.stringify({
        timestamp: new Date().toISOString(),
        providerName,
        providerType,
        userEmail: userAttributesFromIdp.email,
        attributeCount: Object.keys(userAttributesFromIdp).length,
        attributes: userAttributesFromIdp
    }));
    
    // Pass through all attributes unchanged
    event.response.userAttributesToMap = userAttributesFromIdp;
    return event;
};
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
    "version": "string",
    "triggerSource": "InboundFederation_ExternalProvider",
    "region": "us-east-1",
    "userPoolId": "us-east-1_XXXXXXXXX",
    "userName": "CorporateAD_john.doe",
    "callerContext": {
        "awsSdkVersion": "string",
        "clientId": "string"
    },
    "request": {
        "providerName": "CorporateAD",
        "providerType": "SAML",
        "attributes": {
            "samlResponse": {
                "email": "john.doe@company.com",
                "given_name": "John",
                "family_name": "Doe",
                "department": "Engineering",
                "employee_id": "EMP12345"
            }
        }
    },
    "response": {
        "userAttributesToMap": {}
    }
}
```

------

预期的 CloudWatch 日志输出：

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

```
{
    "timestamp": "2025-01-14T21:17:40.153Z",
    "providerName": "CorporateAD",
    "providerType": "SAML",
    "userEmail": "john.doe@company.com",
    "attributeCount": 5,
    "attributes": {
        "email": "john.doe@company.com",
        "given_name": "John",
        "family_name": "Doe",
        "department": "Engineering",
        "employee_id": "EMP12345"
    }
}
```

------

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

在为 Amazon Cognito 用户池构建身份验证流程时，您可能会发现需要在内置流程的基础上对身份验证模型进行扩展。自定义质询触发器的一个常见使用场景是在用户名、密码和多重身份验证（MFA）之外实施额外的安全检查。自定义质询是您可以使用 Lambda 支持的编程语言生成的任何问题和回答。例如，在允许用户进行身份验证之前，您可能希望要求用户先破解验证码或回答安全问题。另一个潜在的需求是与专门的身份验证因素或设备集成。或者，您可能已经开发了使用硬件安全密钥或生物识别设备对用户进行身份验证的软件。自定义质询的身份验证成功的定义是，您的 Lambda 函数接受为正确的答案：例如，固定字符串或来自外部 API 的满意响应。

您可以使用自定义质询开始身份验证并完全控制身份验证过程，也可以在应用程序收到自定义质询之前执行用户名和密码身份验证。

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

**[定义](user-pool-lambda-define-auth-challenge.md)**  
启动质询序列。确定您是要启动新的质询、将身份验证标记为已完成，还是要停止身份验证尝试。

**[创建](user-pool-lambda-create-auth-challenge.md)**  
向您的应用程序发出用户必须回答的问题。此函数可能会呈现安全问题或指向验证码的链接，您的应用程序应将其显示给用户。

**[验证](user-pool-lambda-verify-auth-challenge-response.md)**  
知道预期答案并将其与您的应用程序在质询响应中提供的答案进行比较。该函数可能会调用您的验证码服务的 API 来检索用户尝试的解决方案的预期结果。

这三个 Lambda 函数链接在一起，呈现出一种完全由您控制且由您自己设计的身份验证机制。由于自定义身份验证需要在您的客户端和 Lambda 函数中使用应用程序逻辑，因此您无法在托管登录中处理自定义身份验证。此身份验证系统需要开发人员付出额外的努力。您的应用程序必须使用用户池 API 执行身份验证流程，并使用定制登录界面处理由此产生的质询，该界面可在自定义身份验证质询的中心呈现问题。

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


有关实施自定义身份验证的更多信息，请参阅[自定义身份验证流程和质询](amazon-cognito-user-pools-authentication-flow-methods.md#Custom-authentication-flow-and-challenges)。

API 操作之间的身份验证[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)或[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)、和[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)或[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)。在此流程中，用户通过回答连续的质询进行身份验证，直到身份验证失败或用户获得令牌。质询回应可能是一个新的挑战。在这种情况下，您的应用程序会根据需要多次响应新的质询。当定义身份验证质询函数分析到目前为止的结果时，确定所有质询都已回答并返回 `IssueTokens` 时，身份验证就会成功。

**Topics**
+ [自定义质询流程中的 SRP 身份验证](#user-pool-lambda-challenge-srp-authentication)
+ [定义身份验证质询 Lambda 触发器](user-pool-lambda-define-auth-challenge.md)
+ [创建身份验证质询 Lambda 触发器](user-pool-lambda-create-auth-challenge.md)
+ [验证身份验证质询响应 Lambda 触发器](user-pool-lambda-verify-auth-challenge-response.md)

## 自定义质询流程中的 SRP 身份验证
<a name="user-pool-lambda-challenge-srp-authentication"></a>

您可以让 Amazon Cognito 在发出自定义质询之前验证用户密码。当您在自定义质询流程中执行 SRP 身份验证时，[请求频率限额](quotas.md#category_operations.title)身份验证类别中关联的任何 Lambda 触发器都将运行。过程概述如下：

1. 您的应用程序使用 `AuthParameters` 映射来调用 `InitiateAuth` 或 `AdminInitiateAuth`，以此来启动登录。参数必须包括 `CHALLENGE_NAME: SRP_A,` 以及 `SRP_A` 和 `USERNAME` 的值。

1. Amazon Cognito 使用包含 `challengeName: SRP_A` 和 `challengeResult: true` 的初始会话，调用您定义的身份验证质询 Lambda 触发器。

1. 在收到这些输入后，您的 Lambda 函数发出 `challengeName: PASSWORD_VERIFIER`、`issueTokens: false`、`failAuthentication: false` 响应。

1. 如果密码验证成功，Amazon Cognito 会使用包含 `challengeName: PASSWORD_VERIFIER` 和 `challengeResult: true` 的新会话再次调用您的 Lambda 函数。

1. 为了启动您的自定义质询，Lambda 函数发出 `challengeName: CUSTOM_CHALLENGE`、`issueTokens: false` 和 `failAuthentication: false` 响应。如果您不想启动包含密码验证的自定义身份验证流程，可以使用 `AuthParameters` 映射（包括 `CHALLENGE_NAME: CUSTOM_CHALLENGE`）启动登录。

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

以下在使用 SRP 流进行自定义身份验证之前的起始 `InitiateAuth` 请求的示例。

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

### 在自定义身份验证 SRP 流程中重置密码
<a name="user-pool-lambda-challenge-force-password-change"></a>

当用户处于 `FORCE_CHANGE_PASSWORD` 状态时，您的自定义身份验证流程必须集成密码更改步骤，同时保持身份验证质询的完整性。Amazon Cognito 会在 `NEW_PASSWORD_REQUIRED` 质询期间调用您的[定义身份验证质询](user-pool-lambda-define-auth-challenge.md) Lambda 触发器。在这种情况下，使用自定义质询流程和 SRP 身份验证登录的用户如果处于密码重置状态，则可以设置新密码。

当用户处于 `RESET_REQUIRED` 或 `FORCE_CHANGE_PASSWORD` 状态时，他们必须使用 `NEW_PASSWORD` 来[回应](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html#API_RespondToAuthChallenge_RequestParameters) `NEW_PASSWORD_REQUIRED` 质询。在使用 SRP 的自定义身份验证中，Amazon Cognito 会在用户完成 SRP `PASSWORD_VERIFIER` 质询后返回一个 `NEW_PASSWORD_REQUIRED` 质询。您的“定义身份验证质询”触发器会收到 `session` 数组中的两个质询结果，并可在用户成功更改密码后继续执行额外的自定义质询。

您的“定义身份验证质询”Lambda 触发器必须通过 SRP 身份验证、密码重置和随后的自定义质询来管理质询序列。该触发器会在 `session` 参数中收到一个已完成质询的数组，其中包括 `PASSWORD_VERIFIER` 和 `NEW_PASSWORD_REQUIRED` 的结果。如需了解实现示例，请参阅[定义身份验证质询示例](user-pool-lambda-define-auth-challenge.md#aws-lambda-triggers-define-auth-challenge-example)。

#### 身份验证流程步骤
<a name="user-pool-lambda-challenge-password-flow-steps"></a>

对于需要在自定义质询之前验证密码的用户，该过程遵循以下步骤：

1. 您的应用程序使用 `AuthParameters` 映射来调用 `InitiateAuth` 或 `AdminInitiateAuth`，以此来启动登录。参数必须包括 `CHALLENGE_NAME: SRP_A`，以及 `SRP_A` 和 `USERNAME` 的值。

1. Amazon Cognito 使用包含 `challengeName: SRP_A` 和 `challengeResult: true` 的初始会话，调用您定义的身份验证质询 Lambda 触发器。

1. 在收到这些输入后，您的 Lambda 函数发出 `challengeName: PASSWORD_VERIFIER`、`issueTokens: false`、`failAuthentication: false` 响应。

1. 如果密码验证成功，则会发生以下两种情况之一：  
**对于处于正常状态的用户：**  
Amazon Cognito 会使用包含 `challengeName: PASSWORD_VERIFIER` 和 `challengeResult: true` 的新会话再次调用您的 Lambda 函数。  
为了启动您的自定义质询，Lambda 函数发出 `challengeName: CUSTOM_CHALLENGE`、`issueTokens: false` 和 `failAuthentication: false` 响应。  
**对于处于 `RESET_REQUIRED` 或 `FORCE_CHANGE_PASSWORD` 状态的用户：**  
Amazon Cognito 会使用包含 `challengeName: PASSWORD_VERIFIER` 和 `challengeResult: true` 的会话调用您的 Lambda 函数。  
您的 Lambda 函数应该使用 `challengeName: NEW_PASSWORD_REQUIRED`、`issueTokens: false` 和 `failAuthentication: false` 作出响应。  
成功更改密码后，Amazon Cognito 会使用包含 `PASSWORD_VERIFIER` 和 `NEW_PASSWORD_REQUIRED` 的会话调用您的 Lambda 函数。  
为了启动您的自定义质询，Lambda 函数发出 `challengeName: CUSTOM_CHALLENGE`、`issueTokens: false` 和 `failAuthentication: false` 响应。

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

如果您不想启动包含密码验证的自定义身份验证流程，可以使用 `AuthParameters` 映射（包括 `CHALLENGE_NAME: CUSTOM_CHALLENGE`）启动登录。

#### 会话管理
<a name="user-pool-lambda-challenge-session-management"></a>

身份验证流程通过一系列会话 IDs 和质询结果来保持会话的连续性。每个质询响应都会生成一个新的会话 ID，以防止会话重用错误，这对于多重身份验证流程尤其重要。

质询结果按时间顺序存储在您的 Lambda 触发器接收的会话数组中。对于处于 `FORCE_CHANGE_PASSWORD` 状态的用户，该会话数组包含：

1. `session[0]` - 最初的 `SRP_A` 质询

1. `session[1]` - `PASSWORD_VERIFIER` 的结果

1. `session[2]` - `NEW_PASSWORD_REQUIRED` 的结果

1. 后续要素 - 其他自定义质询的结果

#### 身份验证流程示例
<a name="user-pool-lambda-challenge-example-flow"></a>

以下示例展示了一个完整的自定义身份验证流程，在该流程中，一个处于 `FORCE_CHANGE_PASSWORD` 状态的用户必须完成密码更改和自定义 CAPTCHA 质询。

1. **InitiateAuth request**

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

1. **InitiateAuth 响应**

   ```
   {
       "ChallengeName": "PASSWORD_VERIFIER",
       "ChallengeParameters": {
           "USER_ID_FOR_SRP": "testuser"
       },
       "Session": "[session_id_1]"
   }
   ```

1. **RespondToAuthChallenge 请求用 `PASSWORD_VERIFIER`**

   ```
   {
       "ChallengeName": "PASSWORD_VERIFIER",
       "ClientId": "1example23456789",
       "ChallengeResponses": {
           "PASSWORD_CLAIM_SIGNATURE": "[claim_signature]",
           "PASSWORD_CLAIM_SECRET_BLOCK": "[secret_block]",
           "TIMESTAMP": "[timestamp]",
           "USERNAME": "testuser"
       },
       "Session": "[session_id_1]"
   }
   ```

1. **RespondToAuthChallenge 用`NEW_PASSWORD_REQUIRED`挑战回应**

   ```
   {
       "ChallengeName": "NEW_PASSWORD_REQUIRED",
       "ChallengeParameters": {},
       "Session": "[session_id_2]"
   }
   ```

1. **RespondToAuthChallenge 请求用 `NEW_PASSWORD_REQUIRED`**

   ```
   {
       "ChallengeName": "NEW_PASSWORD_REQUIRED",
       "ClientId": "1example23456789",
       "ChallengeResponses": {
           "NEW_PASSWORD": "[password]",
           "USERNAME": "testuser"
       },
       "Session": "[session_id_2]"
   }
   ```

1. **RespondToAuthChallenge 使用 CAPTCHA 自定义挑战进行回应**

   ```
   {
       "ChallengeName": "CUSTOM_CHALLENGE",
       "ChallengeParameters": {
           "captchaUrl": "url/123.jpg"
       },
       "Session": "[session_id_3]"
   }
   ```

1. **RespondToAuthChallenge 请求并附上 CAPTCHA 自定义质询的答案**

   ```
   {
       "ChallengeName": "CUSTOM_CHALLENGE",
       "ClientId": "1example23456789",
       "ChallengeResponses": {
           "ANSWER": "123",
           "USERNAME": "testuser"
       },
       "Session": "[session_id_3]"
   }
   ```

**6。最终成功响应**

```
{
    "AuthenticationResult": {
        "AccessToken": "eyJra456defEXAMPLE",
        "ExpiresIn": 3600,
        "IdToken": "eyJra789ghiEXAMPLE",
        "RefreshToken": "eyJjd123abcEXAMPLE",
        "TokenType": "Bearer"
    },
    "ChallengeParameters": {}
}
```

# 定义身份验证质询 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 };
```

------

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

创建身份验证质询触发器是一个 Lambda 函数，其中包含由定义身份验证质询触发器声明的每个质询的详细信息。它处理由定义身份验证质询触发器声明的质询名称，并返回 `publicChallengeParameters`，您的应用程序必须将其呈现给用户。然后，此函数为您的用户池提供质询 `privateChallengeParameters` 的答案，您的用户池会将该质询传递给验证身份验证质询触发器。在您的定义身份验证质询触发器管理质询序列的地方，您的创建身份验证质询触发器管理质询内容。

![\[质询 Lambda 触发器\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/lambda-challenges2.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 触发器来创建要向用户显示的质询。此 Lambda 触发器的请求包括 `challengeName` 和 `session`。`challengeName` 是一个字符串，是向用户显示的下一质询的名称。此属性的值在定义身份验证质询 Lambda 触发器中设置。

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

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

## 创建身份验证质询 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-create-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",
            . . .
        },
        "challengeName": "string",
        "session": [
            ChallengeResult,
            . . .
        ],
        "clientMetadata": {
            "string": "string",
            . . .
        },
        "userNotFound": boolean
    },
    "response": {
        "publicChallengeParameters": {
            "string": "string",
            . . .
        },
        "privateChallengeParameters": {
            "string": "string",
            . . .
        },
        "challengeMetadata": "string"
    }
}
```

------

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

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

**userNotFound**  
当为您的用户池客户端将 `PreventUserExistenceErrors` 设置为 `ENABLED` 时，将填充此布尔值。

**challengeName**  
新质询的名称。

**会话**  
会话元素是一组 `ChallengeResult` 元素，其中，每个元素包含以下元素：    
**challengeName**  
质询类型。以下值之一：`"CUSTOM_CHALLENGE"`、`"PASSWORD_VERIFIER"`、`"SMS_MFA"`、`"DEVICE_SRP_AUTH"`、`"DEVICE_PASSWORD_VERIFIER"`、`"NEW_PASSWORD_REQUIRED"` 或 `"ADMIN_NO_SRP_AUTH"`。  
**challengeResult**  
如果用户成功完成质询，则设置为 `true`，否则设置为 `false`。  
**challengeMetadata**  
您的自定义质询的名称。仅当 `challengeName` 为 `"CUSTOM_CHALLENGE"` 时使用。

**clientMetadata**  
一个或多个键值对，您可以将其作为自定义输入内容提供给为创建身份验证质询触发器指定的 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 参数将此数据传递给您的 Lambda 函数。调用 create 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-create-auth-challenge-response"></a>

**publicChallengeParameters**  
客户端应用程序要在向用户显示的质询中使用的一个或多个键/值对。此参数应包含所有必要信息，以向用户准确显示质询。

**privateChallengeParameters**  
此参数仅由验证身份验证质询响应 Lambda 触发器使用。此参数应包含所需的所有信息，以验证用户对质询的响应。也就是说，`publicChallengeParameters` 参数包含向用户显示的问题，`privateChallengeParameters` 包含问题的有效答案。

**challengeMetadata**  
您的自定义质询的名称（如果是自定义质询）。

## 创建身份验证质询示例
<a name="aws-lambda-triggers-create-auth-challenge-example"></a>

此功能包含两个自定义质询，对应于我们[定义身份验证质询示例](user-pool-lambda-define-auth-challenge.md#aws-lambda-triggers-define-auth-challenge-example)中的质询序列。前两个质询为 SRP 身份验证。在第三个质询中，此功能会在质询响应中向您的应用程序返回一个 CAPTCHA URL。您的应用程序根据该 URL 呈现 CAPTCHA，并返回用户的输入。CAPTCHA 图像的 URL 作为 `captchaUrl` 添加到公有质询参数中，并且预期答案添加到私有质询参数中。

在第四个质询中，此功能会返回一个安全问题。您的应用程序会呈现该问题并提示用户输入答案。当用户完成这两个自定义质询后，“定义身份验证质询”触发器将确认用户池可以颁发令牌。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (event.request.challengeName !== "CUSTOM_CHALLENGE") {
    return event;
  }

  if (event.request.session.length === 2) {
    event.response.publicChallengeParameters = {};
    event.response.privateChallengeParameters = {};
    event.response.publicChallengeParameters.captchaUrl = "url/123.jpg";
    event.response.privateChallengeParameters.answer = "5";
  }

  if (event.request.session.length === 3) {
    event.response.publicChallengeParameters = {};
    event.response.privateChallengeParameters = {};
    event.response.publicChallengeParameters.securityQuestion =
      "Who is your favorite team mascot?";
    event.response.privateChallengeParameters.answer = "Peccy";
  }

  return event;
};

export { handler };
```

------

# 验证身份验证质询响应 Lambda 触发器
<a name="user-pool-lambda-verify-auth-challenge-response"></a>

验证身份验证质询触发器是一个 Lambda 函数，用于将用户提供的响应与已知回答进行比较。此功能告诉您的用户池，用户是否正确回答了质询。当验证身份验证质询触发器对 `answerCorrect` 的响应为 `true` 时，身份验证序列可以继续。

![\[质询 Lambda 触发器\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/lambda-challenges3.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)的一部分。

此触发器的请求包括 `privateChallengeParameters` 和 `challengeAnswer` 参数。创建身份验证质询 Lambda 触发器返回 `privateChallengeParameters` 值，并包含用户的预期响应。`challengeAnswer` 参数包含用户对质询的响应。

响应包含 `answerCorrect` 属性。如果用户成功完成质询，Amazon Cognito 会将属性值设置为 `true`。如果用户未成功完成质询，Amazon Cognito 会将属性值设置为 `false`。

质询循环将一直重复，直至用户应答所有质询。

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

## 验证身份验证质询 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-verify-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",
            . . .
        },
        "privateChallengeParameters": {
            "string": "string",
            . . .
        },
        "challengeAnswer": "string",
        "clientMetadata": {
            "string": "string",
            . . .
        },
        "userNotFound": boolean
    },
    "response": {
        "answerCorrect": boolean
    }
}
```

------

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

**userAttributes**  
此参数包含表示用户属性的一个或多个名称/值对。

**userNotFound**  
当 Amazon Cognito 将您用户池客户端的 `PreventUserExistenceErrors` 设置为 `ENABLED` 时，Amazon Cognito 将填充此布尔值。

**privateChallengeParameters**  
此参数来自创建身份验证质询触发器。为了确定用户是否通过了质询，Amazon Cognito 将参数与用户的 **challengeAnswer** 进行比较。  
此参数包含所需的所有信息，以验证用户对质询的响应。该信息包括 Amazon Cognito 向用户提出的问题 (`publicChallengeParameters`)，以及问题的有效回答 (`privateChallengeParameters`)。只有验证身份验证质询响应 Lambda 触发器使用此参数。

**challengeAnswer**  
此参数值是来自用户对质询响应的应答。

**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 参数。Amazon Cognito 在传递给验证身份验证质询函数的请求中不包含来自 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)API 操作的数据。

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

**answerCorrect**  
如果用户成功完成质询，Amazon Cognito 将此参数设置为 `true`。如果用户未成功完成质询，Amazon Cognito 将此参数设置为 `false`。

## 验证身份验证质询响应示例
<a name="aws-lambda-triggers-verify-auth-challenge-response-example"></a>

此“验证身份验证质询”功能用于检查用户对质询的响应是否与预期响应一致。用户的回答由您的应用程序输入来定义，正确答案则由[创建身份验证质询触发器响应](user-pool-lambda-create-auth-challenge.md#aws-lambda-triggers-create-auth-challenge-example)中的 `privateChallengeParameters.answer` 来定义。正确答案和用户回答都是此功能的输入事件的一部分。

在本例中，如果用户的响应与预期响应一致，Amazon Cognito 会将 `answerCorrect` 参数设置为 `true`。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (
    event.request.privateChallengeParameters.answer ===
    event.request.challengeAnswer
  ) {
    event.response.answerCorrect = true;
  } else {
    event.response.answerCorrect = false;
  }

  return event;
};

export { handler };
```

------

# 令牌生成前 Lambda 触发器
<a name="user-pool-lambda-pre-token-generation"></a>

由于 Amazon Cognito 会在令牌生成之前调用此触发器，您可以自定义用户池令牌中的声明。使用版本 1 或 `V1_0` 令牌生成前触发器事件的**基本功能**，可以自定义身份（ID）令牌。在具有 Essentials 或 Plus 功能计划的用户池中，您可以使用访问令牌自定义生成版本二或`V2_0`触发事件，以及通过 machine-to-machine (M2M) 客户端凭证授予的访问令牌自定义来生成版本三或`V3_0`触发事件。

Amazon Cognito 将向您的函数发送 `V1_0` 请求，其中包含将写入 ID 令牌的数据。`V2_0` 或 `V3_0` 事件是包含将由 Amazon Cognito 写入身份和访问令牌的数据的单个请求。要自定义这两个令牌，您必须更新函数以使用触发器版本二或三，并在同一个响应中发送两个令牌的数据。

Amazon Cognito 将版本二的事件响应应用于来自用户身份验证的访问令牌，即由人类用户向您的用户池提供凭证的场景。版本三的事件响应则适用于来自用户身份验证和机器身份验证的访问令牌，即自动化系统使用应用程序客户端密钥授权访问令牌请求的场景。除了所生成访问令牌的使用场景不同之外，版本二和版本三的事件完全相同。

在 Amazon Cognito 向您的应用程序发布身份和访问令牌之前，此 Lambda 触发器可以添加、删除和修改这些令牌中的某些声明。要使用此功能，可以从 Amazon Cognito 用户池控制台关联 Lambda 函数或通过 AWS Command Line Interface （AWS CLI）更新用户池 `LambdaConfig`。

## 事件版本
<a name="user-pool-lambda-pre-token-generation-event-versions"></a>

您的用户池可以向您的 Lambda 函数提供不同版本的令牌生成前触发事件。`V1_0` 触发器提供用于修改 ID 令牌的参数。`V2_0` 或 `V3_0` 触发器为以下项提供参数。

1. `V1_0` 触发器的功能。

1. 能够自定义访问令牌。

1. 能够将复杂的数据类型传递给 ID 令牌和访问令牌声明值：
   + 字符串
   + 数字
   + 布尔值
   + 由字符串、数字、布尔值或它们的组合构成的数组
   + JSON

**注意**  
在 ID 令牌中，您可以将复杂对象填充到除了 `phone_number_verified`、`email_verified`、`updated_at` 和 `address` 之外的声明值。

默认情况下，用户池传送 `V1_0` 事件。要将用户池配置为发送 `V2_0` 事件，请在 Amazon Cognito 控制台中配置触发器时，在**基本功能 \$1 面向用户身份的访问令牌自定义设置**中选择**触发事件版本**。要生成 `V3_0` 事件，请选择****基本功能 \$1 面向用户和机器身份的访问令牌自定义设置****。您也可以在[UpdateUserPool ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)或 [CreateUserPool ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)API 请求的`LambdaVersion`[LambdaConfig](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#CognitoUserPools-UpdateUserPool-request-LambdaConfig)参数中设置的值。事件版本一、二和三在**基础版**和**增值版**功能计划中均可用。版本三事件的 M2M 操作采用独立于每月活跃用户（MAU）计费公式的定价结构。有关更多信息，请参阅 [Amazon Cognito 定价](https://aws.amazon.com/cognito/pricing/)。

**注意**  
在 GMT 时间 2024 年 11 月 22 日 18:00 或之前已启用**高级安全功能**选项并持续保留在**精简版**功能层级的用户池，可使用令牌生成前触发器的事件版本一和版本二。此旧版层级中*未启用* 高级安全功能的用户池仅可使用事件版本一。版本三*仅* 在基础版和增值版中可用。

## 声明和作用域参考
<a name="user-pool-lambda-pre-token-generation-excluded-claims"></a>

Amazon Cognito 限制了您可以在访问令牌和身份令牌中添加、修改或隐藏的声明和作用域。下表描述了您的 Lambda 函数可以修改和不能修改的声明，以及影响声明存在或价值的触发器事件参数。


| 声明 | 默认令牌类型 | 是否可以添加？ | 是否可以修改？ | 是否可以隐藏？ | 事件参数 - 添加或修改 | 事件参数 - 隐藏 | 身份类型 | 事件版本 | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| 任何不在用户池令牌架构中的声明 | 无 | 支持 | 是 | 不适用 | claimsToAddOrOverride | claimsToSuppress | 用户、计算机[1](#cognito-pretoken-machine-ids-tier-note) | 全部 [2](#cognito-pretoken-id-access-versions-note) | 
| scope | 访问 | 支持 | 是 | 是 | scopesToAdd | scopesToSuppress | 用户、计算机[1](#cognito-pretoken-machine-ids-tier-note) | v2\$10, v3\$10 | 
| cognito:groups | ID、访问 | 支持 | 是 | 是 | groupsToOverride | claimsToSuppress | 用户 | 全部 [2](#cognito-pretoken-id-access-versions-note) | 
| cognito:preferred\$1role | ID | 支持 | 是 | 是 | preferredRole | claimsToSuppress[3](#cognito-pretoken-suppress-groups-note) | 用户 | 全部 | 
| cognito:roles | ID | 支持 | 是 | 是 | iamRolesToOverride | claimsToSuppress[3](#cognito-pretoken-suppress-groups-note) | 用户 | 全部 | 
| cognito:username | ID | 否 | 否 | 否 | 不适用 | 不适用 | 用户 | 不适用 | 
| 任何其他带有 cognito: 前缀的声明 | 无 | 否 | 否 | 否 | 不适用 | 不适用 | 不适用 | 不适用 | 
| username | 访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户 | v2\$10, v3\$10 | 
| sub | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户 | 不适用 | 
| 标准 OIDC 属性 | ID | 支持 | 是 | 是 | claimsToAddOrOverride | claimsToSuppress | 用户 | 全部 | 
| custom: 属性 | ID | 支持 | 是 | 是 | claimsToAddOrOverride | claimsToSuppress | 用户 | 全部 | 
| dev: 属性 | ID | 否 | 否 | 是 | 不适用 | claimsToSuppress | 用户 | 全部 | 
| identities | ID | 否 | 否 | 否 | 不适用 | 不适用 | 用户 | 不适用 | 
| aud[4](#cognito-pretoken-aud-note) | ID | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| client\$1id | 访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| event\$1id | 访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| device\$1key | 访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户 | 不适用 | 
| version | 访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| acr | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| amr | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| at\$1hash | ID | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| auth\$1time | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| azp | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| exp | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| iat | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| iss | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| jti | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| nbf | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| nonce | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| origin\$1jti | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 
| token\$1use | ID、访问 | 否 | 否 | 否 | 不适用 | 不适用 | 用户、计算机 | 不适用 | 

1 机器身份的访问令牌仅适用于 `v3_0` 的触发器输入事件。事件版本三仅在**基础版**和**增值版**功能层级中可用。**精简版**层级的用户池可以接收 `v1_0` 事件。启用高级安全功能的**精简版**用户池可以接收 `v1_0` 和 `v2_0` 事件。

2 将您的令牌生成前触发器配置为：使用事件版本 `v1_0` 仅处理 ID 令牌，使用 `v2_0` 处理 ID 令牌和访问令牌，使用 `v3_0` 处理 ID 令牌和访问令牌并提供机器身份相关功能。

3 要隐藏 `cognito:preferred_role` 和 `cognito:roles` 声明，请将 `cognito:groups` 添加到 `claimsToSuppress`。

 4 您可以向访问令牌添加 `aud` 声明，但其值必须与当前会话的应用程序客户端 ID 相匹配。您可以从 `event.callerContext.clientId` 获取请求事件中的客户端 ID。

## 自定义身份令牌
<a name="user-pool-lambda-pre-token-generation-idtoken"></a>

使用令牌生成前 Lambda 触发器的所有事件版本，您可以自定义来自用户池的身份（ID）令牌的内容。ID 令牌提供来自可信身份源的用户属性，用于登录 Web 或移动应用程序。有关 ID 令牌的更多信息，请参阅[了解身份（ID）令牌](amazon-cognito-user-pools-using-the-id-token.md)。

将令牌生成前 Lambda 触发器与 ID 令牌结合使用，可实现以下目的。
+ 在运行时更改您的用户从身份池中请求的 IAM 角色。
+ 从外部来源添加用户属性。
+ 添加或替换现有用户属性值。
+ 隐藏用户属性，否则这些属性由于用户获得的授权范围以及您授予应用程序客户端的属性读取权限，会传递给您的应用程序。

## 自定义访问令牌
<a name="user-pool-lambda-pre-token-generation-accesstoken"></a>

使用令牌生成前 Lambda 触发器的事件版本二和三，您可以自定义来自用户池的访问令牌的内容。访问令牌授权用户从受访问保护的资源（例如 Amazon Cognito 令牌授权的 API 操作和第三方）中检索信息。 APIs对于使用客户凭证授予的 machine-to-machine（M2M）授权，Amazon Cognito 仅在您的用户池配置为版本三 () 事件时才会调用令牌生成前触发器。`V3_0`有关访问令牌的更多信息，请参阅[了解访问令牌](amazon-cognito-user-pools-using-the-access-token.md)。

将令牌生成前 Lambda 触发器与访问令牌结合使用，可实现以下目的。
+ 在 `scope` 声明中添加或隐藏作用域。例如，您可以将作用域添加到由 Amazon Cognito 用户池 API 身份验证生成的访问令牌中，该身份验证仅分配作用域 `aws.cognito.signin.user.admin`。
+ 更改用户在用户池组中的成员资格。
+ 添加尚不存在于 Amazon Cognito 访问令牌中的声明。
+ 隐藏原本会传递到应用程序的声明。

要在用户池中支持访问自定义，必须将用户池配置为生成触发器请求的更新版本。请按照如下所示的过程更新用户池。

------
#### [ AWS 管理控制台 ]

**在令牌生成前 Lambda 触发器中支持访问令牌自定义**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)，然后选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**扩展**菜单并找到 **Lambda 触发器**。

1. 添加或编辑**令牌生成前触发器**。

1. 在**分配 Lambda 函数**下选择一个 Lambda 函数。

1. 在**基本功能 \$1 面向用户身份的访问令牌自定义设置**或**基本功能 \$1 面向用户和机器身份的访问令牌自定义设置**中，选择**触发事件版本**。此设置会更新 Amazon Cognito 发送给您的函数的请求参数，使该函数包含用于自定义访问令牌的字段。

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

**在令牌生成前 Lambda 触发器中支持访问令牌自定义**

生成[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求。必须为所有您不想设置为默认值的参数指定一个值。有关更多信息，请参阅 [更新用户池和应用程序客户端配置](cognito-user-pool-updating.md)。

在请求的 `LambdaVersion` 参数中包含以下内容。`V2_0` 的值为 `LambdaVersion` 会使您的用户池为访问令牌添加相关参数并应用更改。`V3_0` 的值为 `LambdaVersion` 会生成与 `V2_0` 相同的事件，但会使您的用户池*同样* 向 M2M 访问令牌应用更改。要调用特定的函数版本，请使用以函数版本作为 `LambdaArn` 值的 Lambda 函数 ARN。

```
"PreTokenGenerationConfig": { 
   "LambdaArn": "arn:aws:lambda:us-west-2:123456789012:function:MyFunction",
   "LambdaVersion": "V3_0"
},
```

------

**machine-to-machine(M2M) 客户端凭证的客户端元数据**  
您可以在 M2M 请求中传递[客户端元数据](cognito-user-pools-working-with-lambda-triggers.md#working-with-lambda-trigger-client-metadata)。客户端元数据是来自用户或应用程序环境的附加信息，可影响[令牌生成前 Lambda 触发器](#user-pool-lambda-pre-token-generation)的结果。在使用用户委托人的身份验证操作中，您可以将客户端元数据传递给 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)API 请求正文中的令牌生成前触发器。[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)由于应用程序通过直接向 [令牌端点](token-endpoint.md) 发出请求来执行为 M2M 生成访问令牌的流程，因此它们的模型不同。在客户端凭证令牌请求的 POST 正文中，传递一个 `aws_client_metadata` 参数，其值为客户端元数据对象经 URL 编码（`x-www-form-urlencoded`）后的字符串。有关示例请求，请参阅[基本授权的客户端凭证POST 正文授权的客户端凭证](token-endpoint.md#exchanging-client-credentials-for-an-access-token-in-request-body)。以下是传递键值对 `{"environment": "dev", "language": "en-US"}` 的参数的示例。

```
aws_client_metadata=%7B%22environment%22%3A%20%22dev%22,%20%22language%22%3A%20%22en-US%22%7D
```

**更多资源**
+ [如何在 Amazon Cognito 用户池中自定义访问令牌](https://aws.amazon.com/blogs/security/how-to-customize-access-tokens-in-amazon-cognito-user-pools/)

**Topics**
+ [事件版本](#user-pool-lambda-pre-token-generation-event-versions)
+ [声明和作用域参考](#user-pool-lambda-pre-token-generation-excluded-claims)
+ [自定义身份令牌](#user-pool-lambda-pre-token-generation-idtoken)
+ [自定义访问令牌](#user-pool-lambda-pre-token-generation-accesstoken)
+ [令牌生成前 Lambda 触发器源](#user-pool-lambda-pre-token-generation-trigger-source)
+ [令牌生成前 Lambda 触发器参数](#cognito-user-pools-lambda-trigger-syntax-pre-token-generation)
+ [令牌生成前触发器事件版本 2 示例：添加和隐藏声明、作用域及组](#aws-lambda-triggers-pre-token-generation-example-version-2-overview)
+ [令牌生成前事件版本 2 示例：添加包含复杂对象的声明](#aws-lambda-triggers-pre-token-generation-example-version-2-complex-objects)
+ [令牌生成前事件版本 1 示例：添加新声明并隐藏现有声明](#aws-lambda-triggers-pre-token-generation-version-1-add-claim)
+ [令牌生成前事件版本 1 示例：修改用户的组成员资格](#aws-lambda-triggers-pre-token-generation-version-1-change-group)

## 令牌生成前 Lambda 触发器源
<a name="user-pool-lambda-pre-token-generation-trigger-source"></a>


| triggerSource 值 | 事件 | 
| --- | --- | 
| TokenGeneration\$1HostedAuth | 通过 Amazon Cognito 托管登录的登录页进行身份验证时调用。 | 
| TokenGeneration\$1Authentication | 用户身份验证流完成之后调用。 | 
| TokenGeneration\$1NewPasswordChallenge | 管理员创建用户之后调用。当用户必须更改临时密码时调用此流。 | 
| TokenGeneration\$1ClientCredentials | 在 M2M 客户端凭证授予后调用。只有当您的事件版本为 V3\$10 时，您的用户池才会发送此事件。 | 
| TokenGeneration\$1AuthenticateDevice | 用户设备身份验证结束时调用。 | 
| TokenGeneration\$1RefreshTokens | 用户尝试刷新身份和令牌时调用。 | 

## 令牌生成前 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-pre-token-generation"></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)的组合。在向用户池添加令牌生成前 Lambda 触发器时，您可以选择触发器版本。此版本决定 Amazon Cognito 是否将请求以及用于自定义访问令牌的附加参数传递给您的 Lambda 函数。

------
#### [ Version one ]

版本一令牌可以在 ID 令牌中设置组成员资格、IAM 角色和新声明。组成员资格覆盖同样适用于访问令牌中的 `cognito:groups` 声明。

```
{
    "request": {
        "userAttributes": {"string": "string"},
        "groupConfiguration": {
                "groupsToOverride": [
                    "string",
                    "string"
                ],
                "iamRolesToOverride": [
                    "string",
                    "string"
                ],
                "preferredRole": "string"
        },
        "clientMetadata": {"string": "string"}
    },
    "response": {
        "claimsOverrideDetails": {
            "claimsToAddOrOverride": {"string": "string"},
            "claimsToSuppress": [
                "string",
                "string"
            ],
            "groupOverrideDetails": {
                "groupsToOverride": [
                    "string",
                    "string"
                ],
                "iamRolesToOverride": [
                    "string",
                    "string"
                ],
                "preferredRole": "string"
            }
        }
    }
}
```

------
#### [ Versions two and three ]

版本二和三请求事件添加了可自定义访问令牌的字段。用户池可将版本三事件的更改应用于机器身份的访问令牌。这些版本还添加了对响应对象中复杂 `claimsToOverride` 数据类型的支持。您的 Lambda 函数可以在 `claimsToOverride` 值中返回以下类型的数据：
+ 字符串
+ 数字
+ 布尔值
+ 由字符串、数字、布尔值或它们的组合构成的数组
+ JSON

```
{
    "request": {
        "userAttributes": {
            "string": "string"
        },
        "scopes": ["string", "string"],
        "groupConfiguration": {
            "groupsToOverride": ["string", "string"],
            "iamRolesToOverride": ["string", "string"],
            "preferredRole": "string"
        },
        "clientMetadata": {
            "string": "string"
        }
    },
    "response": {
        "claimsAndScopeOverrideDetails": {
            "idTokenGeneration": {
                "claimsToAddOrOverride": {
                    "string": [accepted datatype]
                },
                "claimsToSuppress": ["string", "string"]
            },
            "accessTokenGeneration": {
                "claimsToAddOrOverride": {
                    "string": [accepted datatype]
                },
                "claimsToSuppress": ["string", "string"],
                "scopesToAdd": ["string", "string"],
                "scopesToSuppress": ["string", "string"]
            },
            "groupOverrideDetails": {
                "groupsToOverride": ["string", "string"],
                "iamRolesToOverride": ["string", "string"],
                "preferredRole": "string"
            }
        }
    }
}
```

------

### 令牌生成前请求参数
<a name="cognito-user-pools-lambda-trigger-syntax-pre-token-generation-request"></a>


| Name | 说明 | 最低触发器事件版本 | 
| --- |--- |--- |
| userAttributes |  用户池中用户配置文件的属性。  | 1 | 
| groupConfiguration |  包含当前组配置的输入对象。对象包括 `groupsToOverride`、`iamRolesToOverride` 和 `preferredRole`。  | 1 | 
| groupsToOverride |  您的用户所属的[用户池组](cognito-user-pools-user-groups.md#cognito-user-pools-user-groups.title)。  | 1 | 
| iamRolesTo覆盖 |  您可以将用户池组与 AWS Identity and Access Management (IAM) 角色关联。此元素是您的用户所属组中的所有 IAM 角色的列表。  | 1 | 
| preferredRole |  您可以为用户池组设置一个[优先级](cognito-user-pools-user-groups.md#assigning-precedence-values-to-groups.title)。此元素包含 `groupsToOverride` 元素中具有最高优先级组中的 IAM 角色的名称。  | 1 | 
| 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参数。Amazon Cognito 在传递给令牌生成前函数的请求中不包含来自`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)API 操作的数据。  | 1 | 
| 范围 |  访问令牌的作用域。访问令牌中的作用域是您的用户请求且您授权应用程序客户端发布的用户池标准作用域和自定义作用域。  | 2 | 

### 令牌生成前响应参数
<a name="cognito-user-pools-lambda-trigger-syntax-pre-token-generation-response"></a>


| Name | 说明 | 最低触发器事件版本 | 
| --- |--- |--- |
| claimsOverrideDetails | 用于存放 V1\$10 触发器事件中所有元素的容器。 | 1 | 
| claimsAndScopeOverrideDetails |  用于存放 `V2_0` 或 `V3_0` 触发器事件中所有元素的容器。  | 2 | 
| idTokenGeneration |  您要在用户的 ID 令牌中覆盖、添加或隐藏的声明。这是 ID 令牌自定义值的父元素，仅出现在版本 2 事件中，但子元素出现在版本 1 事件中。  | 2 | 
| accessTokenGeneration |  您要在用户的访问令牌中覆盖、添加或隐藏的声明和范围。这是访问令牌自定义值的父元素，仅出现在事件版本 2 及以上版本中。  | 2 | 
| claimsToAddOrOverride |  您要添加或修改的一个或多个声明及其值的映射。对于与组相关的声明，请改用 `groupOverrideDetails`。 在事件版本 2 及以上版本中，此元素同时出现在 `accessTokenGeneration` 和 `idTokenGeneration` 下。  | 1[*](#cognito-pretoken-complex-objects-note) | 
| claimsToSuppress |  您希望 Amazon Cognito 隐藏的声明列表。如果您的函数同时隐藏并替换了声明值，则 Amazon Cognito 会隐藏声明。 在事件版本 2 及以上版本中，此元素同时出现在 `accessTokenGeneration` 和 `idTokenGeneration` 下。  | 1 | 
| groupOverrideDetails |  包含当前组配置的输出对象。对象包括 `groupsToOverride`、`iamRolesToOverride` 和 `preferredRole`。 您的函数将 `groupOverrideDetails` 对象替换为您提供的对象。如果您在响应中提供空的或空对象，则 Amazon Cognito 将隐藏组。要保持现有组配置不变，请将请求的 `groupConfiguration` 对象的值复制到响应中的 `groupOverrideDetails` 对象。然后将其传回服务。 Amazon Cognito ID 令牌和访问令牌都包含 `cognito:groups` 声明。在访问令牌和 ID 令牌中，您的 `groupOverrideDetails` 对象将替换 `cognito:groups` 声明。组覆盖是版本 1 事件可以对访问令牌进行的唯一更改。  | 1 | 
| scopesToAdd |  您希望添加到用户访问令牌中的 `scope` 声明的作用域列表。不能添加包含一个或多个空格字符的作用域值。  | 2 | 
| scopesToSuppress |  您希望从用户访问令牌中的 `scope` 声明中移除的作用域列表。  | 2 | 

 \$1 版本一事件的响应对象可以返回字符串。版本二和三事件的响应对象可以返回[复杂对象](#user-pool-lambda-pre-token-generation-event-versions)。

## 令牌生成前触发器事件版本 2 示例：添加和隐藏声明、作用域及组
<a name="aws-lambda-triggers-pre-token-generation-example-version-2-overview"></a>

此示例对用户的令牌进行了以下修改。

1. 在 ID 令牌中将其 `family_name` 设置为 `Doe`。

1. 防止 `email` 和 `phone_number` 声明出现在 ID 令牌中。

1. 将其 ID 令牌 `cognito:roles` 声明设置为 `"arn:aws:iam::123456789012:role\/sns_callerA","arn:aws:iam::123456789012:role\/sns_callerC","arn:aws:iam::123456789012:role\/sns_callerB"`。

1. 将其 ID 令牌 `cognito:preferred_role` 声明设置为 `arn:aws:iam::123456789012:role/sns_caller`。

1. 将作用域 `openid`、`email` 和 `solar-system-data/asteroids.add` 添加到访问令牌中。

1. 隐藏访问令牌的作用域 `phone_number` 和 `aws.cognito.signin.user.admin`。删除 `phone_number` 可阻止从 `userInfo` 中检索用户的电话号码。删除 `aws.cognito.signin.user.admin` 可阻止用户通过 Amazon Cognito 用户池 API 请求读取和修改自己的个人资料。
**注意**  
只有当访问令牌中的剩余作用域包括 `openid` 和至少一个其他标准作用域时，从作用域中删除 `phone_number` 才会阻止检索用户的电话号码。有关更多信息，请参阅 [关于范围](cognito-user-pools-define-resource-servers.md#cognito-user-pools-define-resource-servers-about-scopes)。

1. 将其 ID 和访问令牌 `cognito:groups` 声明设置为 `"new-group-A","new-group-B","new-group-C"`。

------
#### [ JavaScript ]

```
export const handler = function(event, context) {
  event.response = {
    "claimsAndScopeOverrideDetails": {
      "idTokenGeneration": {
        "claimsToAddOrOverride": {
          "family_name": "Doe"
        },
        "claimsToSuppress": [
          "email",
          "phone_number"
        ]
      },
      "accessTokenGeneration": {
        "scopesToAdd": [
          "openid",
          "email",
          "solar-system-data/asteroids.add"
        ],
        "scopesToSuppress": [
          "phone_number",
          "aws.cognito.signin.user.admin"
        ]
      },
      "groupOverrideDetails": {
        "groupsToOverride": [
          "new-group-A",
          "new-group-B",
          "new-group-C"
        ],
        "iamRolesToOverride": [
          "arn:aws:iam::123456789012:role/new_roleA",
          "arn:aws:iam::123456789012:role/new_roleB",
          "arn:aws:iam::123456789012:role/new_roleC"
        ],
        "preferredRole": "arn:aws:iam::123456789012:role/new_role",
      }
    }
  };
  // Return to Amazon Cognito
  context.done(null, event);
};
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
    "version": "2",
    "triggerSource": "TokenGeneration_Authentication",
    "region": "us-east-1",
    "userPoolId": "us-east-1_EXAMPLE",
    "userName": "JaneDoe",
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "1example23456789"
    },
    "request": {
        "userAttributes": {
            "sub": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
            "cognito:user_status": "CONFIRMED",
            "email_verified": "true",
            "phone_number_verified": "true",
            "phone_number": "+12065551212",
            "family_name": "Zoe",
            "email": "Jane.Doe@example.com"
        },
        "groupConfiguration": {
            "groupsToOverride": ["group-1", "group-2", "group-3"],
            "iamRolesToOverride": ["arn:aws:iam::123456789012:role/sns_caller1", "arn:aws:iam::123456789012:role/sns_caller2", "arn:aws:iam::123456789012:role/sns_caller3"],
            "preferredRole": ["arn:aws:iam::123456789012:role/sns_caller"]
        },
        "scopes": [
            "aws.cognito.signin.user.admin", "openid", "email", "phone"
        ]
    },
    "response": {
        "claimsAndScopeOverrideDetails": []
    }
}
```

------

## 令牌生成前事件版本 2 示例：添加包含复杂对象的声明
<a name="aws-lambda-triggers-pre-token-generation-example-version-2-complex-objects"></a>

此示例对用户的令牌进行了以下修改。

1. 将数字、字符串、布尔值和 JSON 类型的声明添加到 ID 令牌。这是版本二触发器事件可对 ID 令牌进行的唯一更改。

1. 将数字、字符串、布尔值和 JSON 类型的声明添加到访问令牌。

1. 将三个作用域添加到访问令牌。

1. 隐藏 ID 令牌和访问令牌中的 `email` 声明。

1. 隐藏访问令牌中的 `aws.cognito.signin.user.admin` 作用域。

------
#### [ JavaScript ]

```
export const handler = function(event, context) {

    var scopes = ["MyAPI.read", "MyAPI.write", "MyAPI.admin"]
    var claims = {}
    claims["aud"]= event.callerContext.clientId;
    claims["booleanTest"] = false;
    claims["longTest"] = 9223372036854775807;
    claims["exponentTest"] = 1.7976931348623157E308;
    claims["ArrayTest"] = ["test", 9223372036854775807, 1.7976931348623157E308, true];
    claims["longStringTest"] = "\{\
        \"first_json_block\": \{\
            \"key_A\": \"value_A\",\
            \"key_B\": \"value_B\"\
        \},\
        \"second_json_block\": \{\
            \"key_C\": \{\
                \"subkey_D\": [\
                    \"value_D\",\
                    \"value_E\"\
                ],\
                \"subkey_F\": \"value_F\"\
            \},\
            \"key_G\": \"value_G\"\
        \}\
    \}";
    claims["jsonTest"] = {
    	"first_json_block": {
    		"key_A": "value_A",
    		"key_B": "value_B"
    	},
    	"second_json_block": {
    		"key_C": {
    			"subkey_D": [
    				"value_D",
    				"value_E"
    			],
    			"subkey_F": "value_F"
    		},
    		"key_G": "value_G"
    	}
    };
    event.response = {
        "claimsAndScopeOverrideDetails": {
            "idTokenGeneration": {
                "claimsToAddOrOverride": claims,
                "claimsToSuppress": ["email"]
            },
            "accessTokenGeneration": {
                "claimsToAddOrOverride": claims,
                "claimsToSuppress": ["email"],
                "scopesToAdd": scopes,
                "scopesToSuppress": ["aws.cognito.signin.user.admin"]
            }
        }
    };
    console.info("EVENT response\n" + JSON.stringify(event, (_, v) => typeof v === 'bigint' ? v.toString() : v, 2))
    console.info("EVENT response size\n" + JSON.stringify(event, (_, v) => typeof v === 'bigint' ? v.toString() : v).length)
    // Return to Amazon Cognito
    context.done(null, event);
};
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
    "version": "2",
    "triggerSource": "TokenGeneration_HostedAuth",
    "region": "us-west-2",
    "userPoolId": "us-west-2_EXAMPLE",
    "userName": "JaneDoe",
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "1example23456789"
    },
    "request": {
        "userAttributes": {
            "sub": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
            "cognito:user_status": "CONFIRMED"
            "email_verified": "true",
            "phone_number_verified": "true",
            "phone_number": "+12065551212",
            "email": "Jane.Doe@example.com"
        },
        "groupConfiguration": {
            "groupsToOverride": ["group-1", "group-2", "group-3"],
            "iamRolesToOverride": ["arn:aws:iam::123456789012:role/sns_caller1"],
            "preferredRole": ["arn:aws:iam::123456789012:role/sns_caller1"]
        },
        "scopes": [
            "aws.cognito.signin.user.admin",
            "phone",
            "openid",
            "profile",
            "email"
        ]
    },
    "response": {
        "claimsAndScopeOverrideDetails": []
    }
}
```

------

## 令牌生成前事件版本 1 示例：添加新声明并隐藏现有声明
<a name="aws-lambda-triggers-pre-token-generation-version-1-add-claim"></a>

此示例将版本 1 触发器事件与令牌生成前 Lambda 函数结合使用，以添加新声明并隐藏现有声明。

------
#### [ Node.js ]

```
const handler = async (event) => {
  event.response = {
    claimsOverrideDetails: {
      claimsToAddOrOverride: {
        my_first_attribute: "first_value",
        my_second_attribute: "second_value",
      },
      claimsToSuppress: ["email"],
    },
  };

  return event;
};

export { handler };
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的测试事件：由于该代码示例不处理任何请求参数，因此您可以使用带有空请求的测试事件。有关常见请求参数的更多信息，请参阅[用户池 Lambda 触发器事件](cognito-user-pools-working-with-lambda-triggers.md#cognito-user-pools-lambda-trigger-event-parameter-shared)。

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

```
{
  "request": {},
  "response": {}
}
```

------

## 令牌生成前事件版本 1 示例：修改用户的组成员资格
<a name="aws-lambda-triggers-pre-token-generation-version-1-change-group"></a>

此示例将版本 1 触发器事件与令牌生成前 Lambda 函数结合使用，以修改用户的组成员资格。

------
#### [ Node.js ]

```
const handler = async (event) => {
  event.response = {
    claimsOverrideDetails: {
      groupOverrideDetails: {
        groupsToOverride: ["group-A", "group-B", "group-C"],
        iamRolesToOverride: [
          "arn:aws:iam::XXXXXXXXXXXX:role/sns_callerA",
          "arn:aws:iam::XXXXXXXXX:role/sns_callerB",
          "arn:aws:iam::XXXXXXXXXX:role/sns_callerC",
        ],
        preferredRole: "arn:aws:iam::XXXXXXXXXXX:role/sns_caller",
      },
    },
  };

  return event;
};

export { handler };
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
  "request": {},
  "response": {}
}
```

------

# 迁移用户 Lambda 触发器
<a name="user-pool-lambda-migrate-user"></a>

如果用户在使用密码登录时或在使用忘记密码流程时不在用户池中，Amazon Cognito 会调用此触发器。Lambda 函数成功返回后，Amazon Cognito 将在用户池中创建用户。有关利用用户迁移 Lambda 触发器进行身份验证流程的详细信息，请参阅[利用用户迁移 Lambda 触发器导入用户](cognito-user-pools-import-using-lambda.md)。

要在用户登录时或在忘记密码流程中，将用户从您的现有用户目录迁移到 Amazon Cognito 用户池，请使用此 Lambda 触发器。

**Topics**
+ [迁移用户 Lambda 触发器源](#user-pool-lambda-migrate-user-trigger-source)
+ [迁移用户 Lambda 触发器参数](#cognito-user-pools-lambda-trigger-syntax-user-migration)
+ [示例：使用现有密码迁移用户](#aws-lambda-triggers-user-migration-example-1)

## 迁移用户 Lambda 触发器源
<a name="user-pool-lambda-migrate-user-trigger-source"></a>


| triggerSource 值 | 事件 | 
| --- | --- | 
| UserMigration\$1Authentication[1](#cognito-migrate-user-passwordless-note) | 登录时的用户迁移。 | 
| UserMigration\$1ForgotPassword | 在忘记密码流程中迁移用户。 | 

1 当用户使用[无密码登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)进行身份验证时，Amazon Cognito 不会调用此触发器。

## 迁移用户 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-user-migration"></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 ]

```
{
    "userName": "string",
    "request": {
        "password": "string",
        "validationData": {
            "string": "string",
            . . .
        },
        "clientMetadata": {
            "string": "string",
      	. . .
        }
    },
    "response": {
        "userAttributes": {
            "string": "string",
            . . .
        },
        "finalUserStatus": "string",
        "messageAction": "string",
        "desiredDeliveryMediums": [ "string", . . .],
        "forceAliasCreation": boolean,
        "enableSMSMFA": boolean
    }
}
```

------

### 迁移用户请求参数
<a name="cognito-user-pools-lambda-trigger-syntax-user-migration-request"></a>

**userName**  
用户在登录时输入的用户名。

**password**  
用户在登录时输入的密码。Amazon Cognito 不会在由忘记密码流程发起的请求中发送此值。

**validationData**  
一个或多个键/值对，包含用户的登录请求中的验证数据。要将此数据传递给您的 Lambda 函数，您可以使用[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)和 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)API 操作中的 ClientMetadata 参数。

**clientMetadata**  
一个或多个键/值对，您可以将其作为自定义输入内容提供给迁移用户触发器的 Lambda 函数。要将此数据传递给您的 Lambda 函数，您可以使用[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)和 [ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)API 操作中的 ClientMetadata 参数。

### 迁移用户响应参数
<a name="cognito-user-pools-lambda-trigger-syntax-user-migration-response"></a>

**userAttributes**  
该字段为必填。  
该字段必须包含一个或多个名称/值对，Amazon Cognito 将其存储在用户池的用户配置文件中并用作用户属性。您可以同时包括标准的和自定义的用户属性。自定义属性需要使用 `custom:` 前缀，以便与标准属性区分开来。有关更多信息，请参阅[自定义属性](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-custom-attributes.html)。  
要在忘记密码流程中重置密码，用户必须拥有经过验证的电子邮件地址或经过验证的电话号码。Amazon Cognito 将包含重置密码代码的消息发送到用户属性中的电子邮件地址或电话号码。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/user-pool-lambda-migrate-user.html)

**finalUserStatus**  
您可以将此参数设置为 `CONFIRMED` 以自动确认用户，这样他们就可以使用之前的密码登录。当您将用户设置为 `CONFIRMED` 时，他们无需执行额外的操作即可登录。如果您未将此属性设置为 `CONFIRMED`，则它会设置为 `RESET_REQUIRED`。  
若 `finalUserStatus` 设置为 `RESET_REQUIRED`，则意味着用户在迁移之后，必须在登录时立即更改密码，并且您的客户端应用程序必须在身份验证中处理 `PasswordResetRequiredException`。  
使用 Lambda 触发器迁移期间，Amazon Cognito 不强制执行您为用户池配置的密码强度策略。如果密码不符合您配置的密码策略，Amazon Cognito 仍会接受密码，以便它继续迁移用户。要强制实施密码强度策略并拒绝不符合策略的密码，请验证代码中的密码强度。然后，如果密码不符合政策，则设置 finalUserStatus 为`RESET_REQUIRED`。

**messageAction**  
您可以将此参数设置为 `SUPPRESS`，以拒绝发送 Amazon Cognito 通常会向新用户发送的欢迎消息。如果您的函数未返回此参数，Amazon Cognito 会发送欢迎消息。

**desiredDeliveryMediums**  
您可以将此参数设置为 `EMAIL` 以通过电子邮件发送欢迎消息，或者设置为 `SMS` 以通过 SMS 发送欢迎消息。如果您的函数未返回此参数，Amazon Cognito 通过 SMS 发送欢迎消息。

**forceAliasCreation**  
如果您将此参数设置为，`TRUE`并且 UserAttributes 参数中的电话号码或电子邮件地址已作为其他用户的别名存在，则 API 调用会将该别名从以前的用户迁移到新创建的用户。以前的用户无法再使用该别名登录。  
如果您将此参数设置为 `FALSE` 而且别名存在，Amazon Cognito 不会迁移用户，并向客户端应用程序返回错误。  
如果您不返回此参数，Amazon Cognito 会假定其值为“false”。

**enableSMSMFA**  
将此参数设置为 `true`，要求迁移的用户完成 SMS 短信多重身份验证 (MFA) 才能登录。您的用户池必须启用 MFA。请求参数中的用户属性必须包含电话号码，否则该用户的迁移将失败。

## 示例：使用现有密码迁移用户
<a name="aws-lambda-triggers-user-migration-example-1"></a>

此示例 Lambda 函数使用现有密码迁移用户，并隐藏 Amazon Cognito 发送的欢迎消息。

------
#### [ Node.js ]

```
exports.handler = (event, context, callback) => {
  var user;

  if (event.triggerSource == "UserMigration_Authentication") {
    // authenticate the user with your existing user directory service
    user = authenticateUser(event.userName, event.request.password);
    if (user) {
      event.response.userAttributes = {
        email: user.emailAddress,
        email_verified: "true",
      };
      event.response.finalUserStatus = "CONFIRMED";
      event.response.messageAction = "SUPPRESS";
      context.succeed(event);
    } else {
      // Return error to Amazon Cognito
      callback("Bad password");
    }
  } else if (event.triggerSource == "UserMigration_ForgotPassword") {
    // Lookup the user in your existing user directory service
    user = lookupUser(event.userName);
    if (user) {
      event.response.userAttributes = {
        email: user.emailAddress,
        // required to enable password-reset code to be sent to user
        email_verified: "true",
      };
      event.response.messageAction = "SUPPRESS";
      context.succeed(event);
    } else {
      // Return error to Amazon Cognito
      callback("Bad password");
    }
  } else {
    // Return error to Amazon Cognito
    callback("Bad triggerSource " + event.triggerSource);
  }
};
```

------

# 自定义消息 Lambda 触发器
<a name="user-pool-lambda-custom-message"></a>

如果您对要发送给用户的电子邮件和短信设置了外部标准，或者您想在运行时将自己的逻辑应用于用户消息的格式化，请向您的用户池中添加自定义消息触发器。自定义消息 Lambda 会在您的用户池发送所有电子邮件和短信消息的内容之前先接收这些内容。然后，您的 Lambda 函数就有机会修改消息内容和主题。

Amazon Cognito 在发送电子邮件或电话验证消息或多重验证 (MFA) 代码前调用此触发器。您可以使用自定义消息触发器动态自定义消息。

该请求包括 `codeParameter`。这是一个字符串，用作 Amazon Cognito 传递给用户的代码的占位符。将 `codeParameter` 字符串插入消息正文中用于显示验证码的位置。Amazon Cognito 在收到此响应后，Amazon Cognito 将 `codeParameter` 字符串替换为实际验证码。

**注意**  
使用 `CustomMessage_AdminCreateUser` 触发器源时，自定义消息 Lambda 函数的输入事件将包含用户名和验证码。由于管理员创建的用户必须同时收到其用户名和验证码，因此来自您的函数的响应必须同时包含用户名和验证码的占位符变量。消息的占位符是 `request.usernameParameter` 和 `request.codeParameter` 的值。这些值通常是 `{username}` 和 `{####}`；作为最佳实践，请引用输入值，而不是对变量名称进行硬编码。

**Topics**
+ [自定义消息 Lambda 触发器源](#cognito-user-pools-lambda-trigger-syntax-custom-message-trigger-source)
+ [自定义消息 Lambda 触发器参数](#cognito-user-pools-lambda-trigger-syntax-custom-message)
+ [用于注册的自定义消息示例](#aws-lambda-triggers-custom-message-example)
+ [管理员创建用户的自定义消息示例](#aws-lambda-triggers-custom-message-admin-example)

## 自定义消息 Lambda 触发器源
<a name="cognito-user-pools-lambda-trigger-syntax-custom-message-trigger-source"></a>


| triggerSource 值 | 事件 | 
| --- | --- | 
| CustomMessage\$1SignUp | 自定义消息 – 在注册后发送确认码。 | 
| CustomMessage\$1AdminCreateUser | 自定义消息 – 向新用户发送临时密码。 | 
| CustomMessage\$1ResendCode | 自定义消息 – 向现有用户重新发送确认码。 | 
| CustomMessage\$1ForgotPassword | 自定义消息 – 针对“忘记密码”请求发送确认码。 | 
| CustomMessage\$1UpdateUserAttribute | 自定义消息 – 当用户的电子邮件或电话号码发生更改时，此触发器自动向用户发送验证码。不可用于其他属性。 | 
| CustomMessage\$1VerifyUserAttribute | 自定义消息 – 当用户针对新的电子邮件或电话号码手动请求验证码时，此触发器向用户发送验证码。 | 
| CustomMessage\$1Authentication | 自定义消息 – 在身份验证过程中发送 MFA 代码。 | 

## 自定义消息 Lambda 触发器参数
<a name="cognito-user-pools-lambda-trigger-syntax-custom-message"></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",
            . . .
        }
        "codeParameter": "####",
        "usernameParameter": "string",
        "clientMetadata": {
            "string": "string",
            . . .
        }
    },
    "response": {
        "smsMessage": "string",
        "emailMessage": "string",
        "emailSubject": "string"
    }
}
```

------

### 自定义消息请求参数
<a name="cognito-user-pools-lambda-trigger-syntax-custom-message-request"></a>

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

**codeParameter**  
一个字符串，用作自定义消息中验证码的占位符。

**usernameParameter**  
用户名。Amazon Cognito 在管理员创建的用户发出的请求中包含此参数。

**clientMetadata**  
一个或多个键值对，您可以将其作为自定义输入内容提供给为自定义消息触发器指定的 Lambda 函数。调用自定义消息函数的请求不包括在 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 操作中的 ClientMetadata 参数中[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)传递的数据。要将此数据传递给您的 Lambda 函数，您可以在以下 API 操作中使用 ClientMetadata 参数：  
+  [AdminResetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminResetUserPassword.html) 
+  [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 
+  [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)
+  [ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)
+  [GetUserAttributeVerificationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAttributeVerificationCode.html)
+  [ResendConfirmationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html)
+  [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)
+  [UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html)

### 自定义消息响应参数
<a name="cognito-user-pools-lambda-trigger-syntax-custom-message-response"></a>

在响应中，指定要在发送给用户的消息中使用的自定义文本。有关 Amazon Cognito 适用于这些参数的字符串限制，请参阅。[MessageTemplateType](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_MessageTemplateType.html)

**smsMessage**  
要发送给用户的自定义 SMS 消息。必须包含您在请求中收到的 `codeParameter` 值。

**emailMessage**  
发送给用户的自定义电子邮件。您可以在 `emailMessage` 参数中使用 HTML 格式。必须包含您在请求中收到的 `codeParameter` 值作为变量 `{####}`。只有在用户池的 `EmailSendingAccount` 属性为 `DEVELOPER` 时，Amazon Cognito 才可以使用`emailMessage` 参数。如果用户池的 `EmailSendingAccount` 属性不是 `DEVELOPER` 且返回了 `emailMessage` 参数，Amazon Cognito 会生成 400 错误代码 `com.amazonaws.cognito.identity.idp.model.InvalidLambdaResponseException`。当您选择使用 Amazon Simple Email Service (Amazon SES) 发送电子邮件时，用户池的 `EmailSendingAccount` 属性为 `DEVELOPER`。否则，该值为 `COGNITO_DEFAULT`。

**emailSubject**  
自定义消息的主题行。只有当用户池的 EmailSendingAccount属性为时，您才能使用该`emailSubject`参数`DEVELOPER`。如果用户池的 `EmailSendingAccount` 属性不是 `DEVELOPER` 且 Amazon Cognito 返回了 `emailSubject` 参数，Amazon Cognito 会生成 400 错误代码 `com.amazonaws.cognito.identity.idp.model.InvalidLambdaResponseException`。当您选择使用 Amazon Simple Email Service (Amazon SES) 发送电子邮件时，用户池的 `EmailSendingAccount` 属性为 `DEVELOPER`。否则，该值为 `COGNITO_DEFAULT`。

## 用于注册的自定义消息示例
<a name="aws-lambda-triggers-custom-message-example"></a>

当服务要求应用程序向用户发送验证码时，此示例 Lambda 函数自定义电子邮件或 SMS 消息。

Amazon Cognito 可以在多个事件中调用 Lambda 触发器：注册后、重新发送验证码时、恢复忘记的密码时或验证用户属性时。响应包括电子邮件和 SMS 消息。该消息必须包含代码参数 `"####"`。此参数是用户收到的验证码的占位符。

电子邮件的最大长度为 20000 个 UTF-8 字符。此长度包括验证码。您可以在这些电子邮件中使用 HTML 标签。

SMS 消息的最大长度为 140 个 UTF-8 个字符。此长度包括验证码。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (event.triggerSource === "CustomMessage_SignUp") {
    const message = `Thank you for signing up. Your confirmation code is ${event.request.codeParameter}.`;
    event.response.smsMessage = message;
    event.response.emailMessage = message;
    event.response.emailSubject = "Welcome to the service.";
  }
  return event;
};

export { handler };
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
	"version": "1",
	"region": "us-west-2",
	"userPoolId": "us-west-2_EXAMPLE",
	"userName": "test-user",
	"callerContext": {
		"awsSdkVersion": "aws-sdk-unknown-unknown",
		"clientId": "1example23456789"
	},
	"triggerSource": "CustomMessage_SignUp",
	"request": {
		"userAttributes": {
			"sub": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
			"cognito:user_status": "CONFIRMED",
			"email_verified": "true",
			"phone_number_verified": "true",
			"phone_number": "+12065551212",
			"email": "test-user@example.com"
		},
		"codeParameter": "{####}",
		"linkParameter": "{##Click Here##}",
		"usernameParameter": "None"
	},
	"response": {
		"smsMessage": "None",
		"emailMessage": "None",
		"emailSubject": "None"
	}
}
```

------

## 管理员创建用户的自定义消息示例
<a name="aws-lambda-triggers-custom-message-admin-example"></a>

Amazon Cognito 向此示例自定义消息 Lambda 函数发送的请求的 `triggerSource` 值为 `CustomMessage_AdminCreateUser`，并且拥有用户名和临时密码。该函数根据请求中的临时密码填入 `${event.request.codeParameter}`，并根据请求中的用户名填入 `${event.request.usernameParameter}`。

您的自定义消息必须将 `codeParameter` 和 `usernameParameter` 的值插入响应对象中的 `smsMessage` 和 `emailMessage`。在此示例中，该函数将相同的消息写入响应字段 `event.response.smsMessage` 和 `event.response.emailMessage`。

电子邮件的最大长度为 20000 个 UTF-8 字符。此长度包括验证码。您可以在这些电子邮件中使用 HTML 标签。SMS 消息的最大长度为 140 个 UTF-8 个字符。此长度包括验证码。

响应包括电子邮件和 SMS 消息。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (event.triggerSource === "CustomMessage_AdminCreateUser") {
    const message = `Welcome to the service. Your user name is ${event.request.usernameParameter}. Your temporary password is ${event.request.codeParameter}`;
    event.response.smsMessage = message;
    event.response.emailMessage = message;
    event.response.emailSubject = "Welcome to the service";
  }
  return event;
};

export { handler };
```

------

Amazon Cognito 将事件信息传递给 Lambda 函数。随后，该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中，您可以设置一个测试事件，该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件：

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

```
{
  "version": 1,
  "triggerSource": "CustomMessage_AdminCreateUser",
  "region": "<region>",
  "userPoolId": "<userPoolId>",
  "userName": "<userName>",
  "callerContext": {
      "awsSdk": "<calling aws sdk with version>",
      "clientId": "<apps client id>",
      ...
  },
  "request": {
      "userAttributes": {
          "phone_number_verified": false,
          "email_verified": true,
           ...
      },
      "codeParameter": "####",
      "usernameParameter": "username"
  },
  "response": {
      "smsMessage": "<custom message to be sent in the message with code parameter and username parameter>"
      "emailMessage": "<custom message to be sent in the message with code parameter and username parameter>"
      "emailSubject": "<custom email subject>"
  }
}
```

------

# 自定义发件人 Lambda 触发器
<a name="user-pool-lambda-custom-sender-triggers"></a>

Lambda 触发器 `CustomEmailSender` 和 `CustomSMSSender` 支持在用户池中使用第三方电子邮件和短信通知。您可以选择 SMS 和电子邮件提供商，通过 Lambda 函数代码向用户发送通知。当 Amazon Cognito 向用户发送邀请、MFA 代码、确认码、验证码或临时密码时，这些事件会激活您配置的 Lambda 函数。Amazon Cognito 将代码和临时密码（密钥）发送到您激活的 Lambda 函数。Amazon Cognito 使用 AWS KMS 客户管理的密钥对这些机密进行加密，然后. AWS Encryption SDK AWS Encryption SDK 是一个客户端加密库，可帮助您加密和解密通用数据。

**[CustomEmailSender](user-pool-lambda-custom-email-sender.md)**  
Amazon Cognito 调用此触发器向用户发送电子邮件通知。

**[自定义SMSSender](user-pool-lambda-custom-sms-sender.md)**  
Amazon Cognito 调用此触发器向用户发送 SMS 通知。

## 加密概念
<a name="user-pool-lambda-custom-sender-triggers-resources"></a>

Amazon Cognito 不会在发送给自定义发件人触发器的事件中以明文形式发送用户的代码。Lambda 函数必须解密事件中的代码。以下概念是加密架构，您的函数必须使用该架构来获取可以传递给用户的代码。

**AWS KMS**  
AWS KMS 是一项用于创建和控制 AWS KMS 密钥的托管服务。这些密钥加密您的数据。有关更多信息，请参阅[什么是 AWS Key Management Service？](/kms/latest/developerguide/overview.html)。

**KMS 密钥**  
KMS 密钥是加密密钥的逻辑表示形式。KMS 密钥包含元数据，如密钥 ID、创建日期、描述和密钥状态。KMS 密钥还包含用于加密和解密数据的密钥材料。有关更多信息，请参阅 [AWS KMS 密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys)。

**对称 KMS 密钥**  
对称 KMS 密钥是一个 256 位加密密钥，它不会退出 AWS KMS 而不加密。要使用对称 KMS 密钥，必须调用 AWS KMS。Amazon Cognito 使用对称密钥。加密和解密使用同一密钥。有关更多信息，请参阅[对称 KMS 密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#symmetric-cmks)。

## 有关自定义发件人 Lambda 触发器的需知信息
<a name="user-pool-lambda-custom-sender-triggers-things-to-know"></a>
+ 要配置用户池以使用这些 Lambda 触发器，您可以使用 AWS CLI 或开发工具包。无法从 Amazon Cognito 控制台进行这些配置。

  `UpdateUserPool` 操作可设置 Lambda 配置。对此操作的请求需要包含用户池的所有参数*和* 您要更改的参数。如果您没有提供所有相关参数，Amazon Cognito 会将任何缺失参数的值设置为其原定设置。如下面的 AWS CLI 示例所示，包括您要添加到用户池或保留在用户池中的所有 Lambda 函数的条目。有关更多信息，请参阅 [更新用户池和应用程序客户端配置](cognito-user-pool-updating.md)。

  ```
      #Send this parameter in an 'aws cognito-idp update-user-pool' CLI command, including any existing 
      #user pool configurations. This snippet also includes a pre sign-up trigger for syntax reference. The pre sign-up trigger
      #doesn't have a role in custom sender triggers.
                
        --lambda-config "PreSignUp=lambda-arn, \
                         CustomSMSSender={LambdaVersion=V1_0,LambdaArn=lambda-arn}, \
                         CustomEmailSender={LambdaVersion=V1_0,LambdaArn=lambda-arn}, \
                         KMSKeyID=key-id"
  ```

  对于使用 `UpdateUserPool` 的 JSON 正文的请求，以下 `LambdaConfig` 代码段可分配自定义的短信和电子邮件发件人函数。

  ```
  "LambdaConfig": {
     "KMSKeyID": "arn:aws:kms:us-east-1:111122223333:key/a6c4f8e2-0c45-47db-925f-87854bc9e357",
     "CustomEmailSender": {
        "LambdaArn": "arn:aws:lambda:us-east-1:111122223333:function:MyFunction",
        "LambdaVersion": "V1_0"
     },
     "CustomSMSSender": {
        "LambdaArn": "arn:aws:lambda:us-east-1:111122223333:function:MyFunction",
        "LambdaVersion": "V1_0"
     }
  ```
+ 要使用`update-user-pool` AWS CLI 命令移除自定义发送器 Lambda 触发器，请省略`CustomSMSSender`或`CustomEmailSender`参数`--lambda-config`，并包含您要在用户池中使用的所有其他触发器。

  要使用 `UpdateUserPool` API 请求删除自定义发件人 Lambda 触发器，请在包含其余用户池配置的请求正文中省略 `CustomSMSSender` 或 `CustomEmailSender` 参数。
+ Amazon Cognito HTML 会转义用户临时密码中的保留字符，例如 `<`（`&lt;`）和 `&gt;`（`>`）等。这些字符可能出现在 Amazon Cognito 发送到您的自定义电子邮件发件人函数的临时密码中，但不会出现在临时验证码中。要发送临时密码，您的 Lambda 函数在解密密码之后必须取消对这些字符的转义，然后再将消息发送给您的用户。

## 激活自定义发件人 Lambda 触发器
<a name="enable-custom-sender-lambda-trigger"></a>

要使用自定义逻辑为您的用户池发送短信或电子邮件消息，请设置自定义发件人触发器。以下步骤会将自定义短信触发器和/或自定义电子邮件触发器分配给您的用户池。添加自定义发件人触发器后，Amazon Cognito 始终向您的 Lambda 函数发送用户属性（包括电话号码）和一次性代码，而不是采用发送短信或电子邮件消息的默认行为。

1. 在 AWS Key Management Service (AWS KMS) 中创建[对称加密密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#symmetric-cmks)。Amazon Cognito 生成密钥（临时密码、验证码、身份验证一次性密码和确认码），然后使用此 KMS 密钥通过 [AWS Encryption SDK](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html) 对这些密钥进行加密。然后，您可以 AWS Encryption SDK 在 Lambda 函数中使用解密密密钥并将其以明文形式发送给用户。

1. 创建或更新您的用户池的 IAM 主体会针对 Amazon Cognito 用于加密代码的 KMS 密钥创建一次性授权。请为该主体授予对您的 KMS 密钥的 `CreateGrant` 权限。要使本示例中的 KMS 密钥策略生效，更新用户池的管理员必须以 IAM 角色 `arn:aws:iam::111222333444:role/my-example-administrator-role` 的代入角色会话身份登录。

   请将以下基于资源的策略（已针对您的环境进行修改）应用于您的 KMS 密钥。

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
       {
           "Effect": "Allow",
           "Principal": {
               "AWS": "arn:aws:iam::111122223333:role/my-example-administrator-role"
           },
           "Action": "kms:CreateGrant",
           "Resource": "arn:aws:kms:us-west-2:111122223333:key/1example-2222-3333-4444-999example",
           "Condition": {
               "StringEquals": {
                  "kms:EncryptionContext:userpool-id": "us-west-2_EXAMPLE"
               }
           }
       },
       {
           "Sid": "Allow Lambda to decrypt",
           "Effect": "Allow",
           "Principal": {
               "AWS": "arn:aws:iam::111122223333:role/my-lambda-function-role"
           },
           "Action": "kms:Decrypt",
           "Resource": "*"
       }]
   }
   ```

------

1. 为自定义发件人触发器创建 Lambda 函数。Amazon Cognito 使用 [AWS Encryption SDK ](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html)加密密钥、临时密码和授权用户 API 请求的代码。

   1. 分配一个 [Lambda 执行角色](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html)，该角色至少具有针对您的 KMS 密钥的 `kms:Decrypt` 权限。

   1. 编写 Lambda 函数代码以发送消息。您函数的输入事件将包含一个密钥。在您的函数中，使用解密密密钥 AWS Encryption SDK 并处理所有相关的元数据。然后将代码、您自己的自定义消息和目标电话号码发送到传送消息的自定义 API。

   1. 将 AWS Encryption SDK 添加到您的 Lambda 函数中。有关更多信息，请参阅 [AWS Encryption SDK 编程语言](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/programming-languages.html)。要更新 Lambda 包，请完成以下步骤：

      1. 在 AWS 管理控制台中将您的 Lambda 函数作为.zip 文件导出。

      1. 打开您的函数并添加 AWS Encryption SDK. 有关更多信息和下载链接，请参阅 *AWS Encryption SDK Developer Guide*（《Crypto SDK 开发人员指南》）中的 [AWS Encryption SDK 编程语言](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/programming-languages.html)。

      1. 压缩您的函数及 SDK 依赖项，然后将函数上传到 Lambda。有关更多信息，请参阅《AWS Lambda 开发人员指南》**中的[将 Lambda 函数部署为 .zip 文件归档](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-zip.html#configuration-function-create)。

1. 授予 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
   ```

1. 使用添加自定义发送器 Lambda 触发器的`LambdaConfig`参数生成 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求。此类触发器无法通过 Amazon Cognito 控制台添加。自定义发件人触发器要求 `LambdaConfig` 参数中必须包含 `KMSKeyID` 以及 `CustomSMSSender` 或 `CustomEmailSender`（或两者同时包含）。

# 自定义电子邮件发件人 Lambda 触发器
<a name="user-pool-lambda-custom-email-sender"></a>

当您为用户池分配自定义电子邮件发件人触发器时，如果用户事件要求 Amazon Cognito 发送电子邮件消息，则它会调用 Lambda 函数，而不是其原定设置行为。使用自定义发件人触发器，您的 AWS Lambda 函数可以通过您选择的方法和提供商向用户发送电子邮件通知。您的函数的自定义代码必须处理和传递用户池中的所有电子邮件消息。

此触发器适用于以下场景：您可能希望更好地控制用户池发送电子邮件消息的方式。您的 Lambda 函数可以自定义对 Amazon SES API 操作的调用，例如，当您想要管理多个经过验证的身份或跨 AWS 区域时。您的函数还可能将消息重定向到另一个传递媒介或第三方服务。

要了解如何配置自定义电子邮件发件人触发器，请参阅[激活自定义发件人 Lambda 触发器](user-pool-lambda-custom-sender-triggers.md#enable-custom-sender-lambda-trigger)。

## 自定义电子邮件发件人 Lambda 触发器源
<a name="trigger-source"></a>

下表显示了 Lambda 代码中自定义电子邮件触发器源的触发事件。


| `TriggerSource value` | 事件 | 
| --- | --- | 
| CustomEmailSender\$1SignUp | 用户注册，Amazon Cognito 随即发送欢迎消息。 | 
| CustomEmailSender\$1Authentication | 用户登录，Amazon Cognito 发送电子邮件 OTP 或 MFA 代码。 | 
| CustomEmailSender\$1ForgotPassword | 用户请求代码以重置其密码。 | 
| CustomEmailSender\$1ResendCode | 用户请求替换账号确认码。 | 
| CustomEmailSender\$1UpdateUserAttribute | 用户更新电子邮件地址或电话号码属性，而 Amazon Cognito 将发送代码用于验证该属性。 | 
| CustomEmailSender\$1VerifyUserAttribute | 用户创建新电子邮件地址或电话号码属性，而 Amazon Cognito 将发送代码用于验证该属性。 | 
| CustomEmailSender\$1AdminCreateUser | 您在用户池中创建新用户，而 Amazon Cognito 向其发送临时密码。 | 
| CustomEmailSender\$1AccountTakeOverNotification | Amazon Cognito 检测到接管用户账户的尝试并向用户发送通知。 | 

## 自定义电子邮件发件人 Lambda 触发器参数
<a name="custom-email-sender-parameters"></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": {
        "type": "customEmailSenderRequestV1",
        "code": "string",
        "clientMetadata": {
            "string": "string",
             . . .
            },
        "userAttributes": {
            "string": "string",
            . . .
         }
}
```

------

### 自定义电子邮件发件人请求参数
<a name="custom-email-sender-request-parameters"></a>

**类型**  
请求版本。对于自定义电子邮件发件人事件，此字符串的值始终为 `customEmailSenderRequestV1`。

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

**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 参数。Amazon Cognito 在传递给身份验证后函数的请求中不包含来自 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)API 操作的数据。  
在具有以下触发源的事件中，Amazon Cognito 会向自定义电子邮件触发函数发送 `ClientMetadata`：  
+ `CustomEmailSender_ForgotPassword`
+ `CustomEmailSender_SignUp`
+ `CustomEmailSender_Authentication`
Amazon Cognito 不会在具有源 `CustomEmailSender_AccountTakeOverNotification` 的触发事件中发送 `ClientMetadata`。

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

### 自定义电子邮件发件人响应参数
<a name="custom-email-sender-response-parameters"></a>

Amazon Cognito 不需要自定义电子邮件发件人响应中有任何其他返回信息。您的 Lambda 函数必须解释事件并解密代码，然后传送消息内容。典型的函数会组装电子邮件消息并将其定向到第三方 SMTP 中继。

## 代码示例
<a name="custom-email-sender-code-examples"></a>

以下 Node.js 示例在您的自定义电子邮件发件人 Lambda 函数中处理电子邮件事件。此示例假设您的函数定义了两个环境变量。

**`KEY_ID`**  
要用于加密和解密用户代码的 KMS 密钥的 ID。

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

**部署此函数**

1. 在开发者工作区中安装最新版本的 NodeJS。

1. 在您的工作区中新建一个 NodeJS 项目。

1. 使用 `npm init -y` 初始化您的项目。

1. 为 Lambda 函数 `touch index.mjs` 创建脚本。

1. 将以下示例的内容粘贴到 `index.mjs`。

1. 下载项目依赖关系， AWS Encryption SDK:`npm install @aws-crypto/client-node`.

1. 将项目目录压缩为文件 `zip -r my_deployment_package.zip .`。

1. [将该 ZIP 文件部署到函数](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-package.html)。

此函数示例会解密代码，并在注册事件中模拟向用户的电子邮件地址发送电子邮件消息。

```
import { KmsKeyringNode, buildClient, CommitmentPolicy } from '@aws-crypto/client-node';

// Configure the encryption SDK client with the KMS key from the environment variables
const { encrypt, decrypt } = buildClient(
    CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT
);

const generatorKeyId = process.env.KEY_ID;
const keyIds = [process.env.KEY_ARN];
const keyring = new KmsKeyringNode({ generatorKeyId, keyIds });

// Example function to simulate sending email.
// This example logs message details to CloudWatch Logs from your Lambda function.
// Update this function with custom logic that sends an email message to 'emailaddress' with body 'message'.
const sendEmail = async (emailAddress, message) => {
    // Log the destination with the email address masked.
    console.log(`Simulating email send to ${emailAddress.replace(/[^@.]/g, '*')}`);
    // Log the message with the code masked.
    console.log(`Message content: ${message.replace(/\b\d{6,8}\b/g, '********')}`);
    // Simulate API delay
    await new Promise(resolve => setTimeout(resolve, 100));
    console.log('Email sent successfully');
    return true;
};

export const handler = async (event) => {
    try {
        // Decrypt the secret code using encryption SDK
        let plainTextCode;
        if (event.request.code) {
            const { plaintext, messageHeader } = await decrypt(keyring, Buffer.from(event.request.code, 'base64'));
            plainTextCode = Buffer.from(plaintext).toString('utf-8');
        }

        // Handle different trigger sources
        if (event.triggerSource == 'CustomEmailSender_SignUp') {
            const emailAddress = event.request.userAttributes.email;
            const message = `Welcome! Your verification code is: ${plainTextCode}`;
            await sendEmail(emailAddress, message);
        }
        else if (event.triggerSource == 'CustomEmailSender_ResendCode') {
            // Handle resend code
        }
        else if (event.triggerSource == 'CustomEmailSender_ForgotPassword') {
            // Handle forgot password
        }
        else if (event.triggerSource == 'CustomEmailSender_UpdateUserAttribute') {
            // Handle update attribute
        }
        else if (event.triggerSource == 'CustomEmailSender_VerifyUserAttribute') {
            // Handle verify attribute
        }
        else if (event.triggerSource == 'CustomEmailSender_AdminCreateUser') {
            // Handle admin create user
        }
        else if (event.triggerSource == 'CustomEmailSender_Authentication') {
            // Handle authentication
        }
        else if (event.triggerSource == 'CustomEmailSender_AccountTakeOverNotification') {
            // Handle account takeover notification
        }

        return;
    } catch (error) {
        console.error('Error in custom email sender:', error);
        throw error;
    }
};
```

# 自定义 SMS 发件人 Lambda 触发器
<a name="user-pool-lambda-custom-sms-sender"></a>

当您为用户池分配自定义短信发件人触发器时，如果用户事件要求 Amazon Cognito 发送短信，则它会调用 Lambda 函数，而不是其原定设置行为。使用自定义发件人触发器，您的 AWS Lambda 函数可以通过您选择的方法和提供商向用户发送 SMS 通知。您的函数的自定义代码必须处理和传递用户池中的所有短信。

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

要了解如何配置自定义电子邮件发件人触发器，请参阅[激活自定义发件人 Lambda 触发器](user-pool-lambda-custom-sender-triggers.md#enable-custom-sender-lambda-trigger)。

## 自定义 SMS 发件人 Lambda 触发器源
<a name="trigger-source"></a>

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


| `TriggerSource value` | 事件 | 
| --- | --- | 
| CustomSMSSender\$1SignUp | 用户注册，Amazon Cognito 随即发送欢迎消息。 | 
| CustomSMSSender\$1ForgotPassword | 用户请求代码以重置其密码。 | 
| CustomSMSSender\$1ResendCode | 用户请求新代码来确认其注册。 | 
| CustomSMSSender\$1VerifyUserAttribute | 用户创建新电子邮件地址或电话号码属性，而 Amazon Cognito 将发送代码用于验证该属性。 | 
| CustomSMSSender\$1UpdateUserAttribute | 用户更新电子邮件地址或电话号码属性，而 Amazon Cognito 将发送代码用于验证该属性。 | 
| CustomSMSSender\$1Authentication | 用户登录，Amazon Cognito 发送短信 OTP 或 MFA 代码。 | 
| CustomSMSSender\$1AdminCreateUser | 您在用户池中创建新用户，而 Amazon Cognito 向其发送临时密码。 | 

## 自定义 SMS 发件人 Lambda 触发器参数
<a name="custom-sms-sender-parameters"></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": {
        "type": "customSMSSenderRequestV1",
        "code": "string",
        "clientMetadata": {
            "string": "string",
             . . .
            },
        "userAttributes": {
            "string": "string",
            . . .
         }
}
```

------

### 自定义 SMS 发件人请求参数
<a name="custom-sms-sender-request-parameters"></a>

**类型**  
请求版本。对于自定义 SMS 发件人事件，此字符串的值始终为 `customSMSSenderRequestV1`。

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

**clientMetadata**  
一个或多个键值对，您可以将它们作为自定义输入提供给自定义 SMS 发件人 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 参数。Amazon Cognito 在传递给身份验证后函数的请求中不包含来自 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)API 操作的数据。

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

### 自定义 SMS 发件人响应参数
<a name="custom-sms-sender-response-parameters"></a>

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

## 代码示例
<a name="custom-sms-sender-code-examples"></a>

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

**`KEY_ID`**  
要用于加密和解密用户代码的 KMS 密钥的 ID。

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

**部署此函数**

1. 在开发者工作区中安装最新版本的 NodeJS。

1. 在您的工作区中新建一个 NodeJS 项目。

1. 使用 `npm init -y` 初始化您的项目。

1. 为 Lambda 函数 `touch index.mjs` 创建脚本。

1. 将以下示例的内容粘贴到 `index.mjs`。

1. 下载项目依赖关系， AWS Encryption SDK:`npm install @aws-crypto/client-node`.

1. 将项目目录压缩为文件 `zip -r my_deployment_package.zip .`。

1. [将该 ZIP 文件部署到函数](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-package.html)。

```
import { KmsKeyringNode, buildClient, CommitmentPolicy } from '@aws-crypto/client-node';

// Configure the encryption SDK client with the KMS key from the environment variables
const { encrypt, decrypt } = buildClient(
    CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT
);

const generatorKeyId = process.env.KEY_ID;
const keyIds = [process.env.KEY_ARN];
const keyring = new KmsKeyringNode({ generatorKeyId, keyIds });

// Example function to simulate sending SMS.
// This example logs message details to CloudWatch Logs from your Lambda function.
// Update this function with custom logic that sends an SMS message to 'phoneNumber' with body 'message'.
const sendSMS = async (phoneNumber, message) => {
    // Log the destination with the phone number masked.
    console.log(`Simulating SMS send to ${phoneNumber.replace(/[^+]/g, '*')}`);
    // Log the message with the code masked.
    console.log(`Message content: ${message.replace(/\b\d{6,8}\b/g, '********')}`);    
    // Simulate API delay
    await new Promise(resolve => setTimeout(resolve, 100));
    console.log('SMS sent successfully');
    return true;
};

export const handler = async (event) => {
    try {
        // Decrypt the secret code using encryption SDK
        let plainTextCode;
        if (event.request.code) {
            const { plaintext, messageHeader } = await decrypt(keyring, Buffer.from(event.request.code, 'base64'));
            plainTextCode = Buffer.from(plaintext).toString('utf-8');
        }

        // Handle different trigger sources
        if (event.triggerSource == 'CustomSMSSender_SignUp') {
            const phoneNumber = event.request.userAttributes.phone_number;
            const message = `Welcome! Your verification code is: ${plainTextCode}`;
            await sendSMS(phoneNumber, message);
        }
        else if (event.triggerSource == 'CustomSMSSender_ResendCode') {
            // Handle resend code
        }
        else if (event.triggerSource == 'CustomSMSSender_ForgotPassword') {
            // Handle forgot password
        }
        else if (event.triggerSource == 'CustomSMSSender_UpdateUserAttribute') {
            // Handle update attribute
        }
        else if (event.triggerSource == 'CustomSMSSender_VerifyUserAttribute') {
            // Handle verify attribute
        }
        else if (event.triggerSource == 'CustomSMSSender_AdminCreateUser') {
            // Handle admin create user
        }
        return;
    } catch (error) {
        console.error('Error in custom SMS sender:', error);
        throw error;
    }
};
```

**Topics**
+ [自定义 SMS 发件人 Lambda 触发器源](#trigger-source)
+ [自定义 SMS 发件人 Lambda 触发器参数](#custom-sms-sender-parameters)
+ [代码示例](#custom-sms-sender-code-examples)
+ [使用自定义 SMS 发件人函数评估 SMS 消息功能](#sms-to-email-example)

## 使用自定义 SMS 发件人函数评估 SMS 消息功能
<a name="sms-to-email-example"></a>

自定义 SMS 发件人 Lambda 函数接受您的用户池将发送的 SMS 消息，并且该函数根据您的自定义逻辑传送内容。Amazon Cognito 将 [自定义 SMS 发件人 Lambda 触发器参数](#custom-sms-sender-parameters) 发送到您的函数。您的函数可以用这些信息做您想做的事。例如，您可以将代码发送到 Amazon Simple Notification Service (Amazon SNS) 主题。Amazon SNS 主题订阅者可以是 SMS 消息、HTTPS 端点或电子邮件地址。

[要使用自定义短信发送器 Lambda 函数为 Amazon Cognito 短信创建测试环境，请参阅上的 aws-sample [amazon-cognito-user-pools development-and-testing-with 库sms-redirected-to-email中的--](https://github.com/aws-samples/amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email)。 GitHub](https://github.com/aws-samples)存储库包含可以创建新用户池或使用已有的用户池的 AWS CloudFormation 模板。这些模板创建 Lambda 函数和 Amazon SNS 主题。模板分配为自定义 SMS 发件人触发器的 Lambda 函数将您的 SMS 消息重定向到 Amazon SNS 主题的订阅者。

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

**重要**  
不要使用 [amazon-cognito-user-pool-development-and-testing-with-](https://github.com/aws-samples/amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email) 中的模板sms-redirected-to-email来构建生产环境。解决方案中的自定义 SMS 发件人 Lambda 函数*模拟* SMS 消息，但 Lambda 函数将它们全部发送到一个中央电子邮件地址。在生产 Amazon Cognito 用户池中发送 SMS 消息之前，您必须完成 [Amazon Cognito 用户池的短信设置](user-pool-sms-settings.md)中显示的要求。

# 管理用户池中的用户
<a name="managing-users"></a>

创建用户群体后，您可以创建、确认和管理用户账户。借助 Amazon Cognito 用户池组，您可以通过将 IAM 角色映射到组来管理您的用户及其对资源的访问。

管理 Amazon Cognito 用户池中的用户涉及各种配置选项和管理任务。用户池可以扩展到数百万用户。这种规模的用户目录需要同样可扩展和可重复的管理工具。您可能需要创建许多用户配置文件、管理不活跃的用户、生成治理和合规报告，或者设置自助工具，让用户自行处理大部分工作。创建用户池后，您可以控制用户如何注册和确认账户，包括要求验证电子邮件或电话号码。管理员还可以直接创建用户账户并自定义欢迎消息和密码要求。

用户池有用户组，您可以根据用户的组成员资格来管理对资源的访问权限。您可以为这些组分配 IAM 角色，从而使用身份池来管理对 AWS 服务的访问权限。ID 令牌和访问令牌中均存在用户的组成员资格。有了这些信息，您就可以在应用程序运行时或使用诸如 Amazon Verified Permissions 之类的策略引擎作出访问控制决策。

用户池通常有许多用户。您会发现自己经常需要搜索和更新用户账户。Amazon Cognito 控制台和 API 支持根据用户名、电子邮件和电话号码等标准属性查询用户。管理员还可以重置密码、禁用账户和查看用户事件历史记录。

为了迁移现有用户数据，Amazon Cognito 可以选择从 CSV 文件导入用户，也可以在用户首次登录时使用 [Lambda 触发器](user-pool-lambda-migrate-user.md)自动迁移用户。这些选项支持用户从其他用户目录转换到您的用户池。

您可以使用用户池中的用户管理特征来精细控制用户生命周期和身份验证体验。自助注册、管理员创建的账户、组和迁移工具相结合，使 Amazon Cognito 用户池成为灵活的用户目录。

**Topics**
+ [配置用户创建策略](user-pool-settings-admin-create-user-policy.md)
+ [注册并确认用户账户](signing-up-users-in-your-app.md)
+ [以管理员身份创建用户账户](how-to-create-user-accounts.md)
+ [向用户池添加组](cognito-user-pools-user-groups.md)
+ [管理和搜索用户账户](how-to-manage-user-accounts.md)
+ [密码、账户恢复和密码策略](managing-users-passwords.md)
+ [将用户导入一个用户池](cognito-user-pools-import-users.md)
+ [使用用户属性](user-pool-settings-attributes.md)

# 配置用户创建策略
<a name="user-pool-settings-admin-create-user-policy"></a>

您的用户池可以允许用户注册，您也可以以管理员身份创建用户。您还可以控制注册后的验证和确认过程由用户掌控的程度。例如，您可能需要审查注册并根据外部验证流程接受注册。此配置，或*管理员创建用户策略*，还可设置用户无法再确认其用户账户之前的时间长度。

作为软件的客户身份和访问管理（CIAM）平台，Amazon Cognito 可以满足公众客户的需求。接受注册并拥有应用程序客户端的用户池，无论有没有托管登录，都可以为互联网上知道您的可公开发现的应用程序客户端 ID 并请求注册的任何人创建用户配置文件。注册的用户配置文件可接收访问和身份令牌，还可以访问您为应用程序授权的资源。在用户池中激活注册之前，请查看您的选项并确保配置符合您的安全标准。请按照以下步骤所述，谨慎设置**启用自行注册**和 `AllowAdminCreateUserOnly`。

------
#### [ AWS 管理控制台 ]

用户池的**注册**菜单包含在用户池中注册和以管理员身份创建用户的一些设置。

**配置注册体验**

1. 在 **Cognito 辅助验证和确认**中，选择是否**允许 Cognito 自动发送消息以进行验证和确认**。启用此设置后，Amazon Cognito 会向新用户发送电子邮件或短信，其中包含他们必须向您的用户池出示的代码。这将确认他们对电子邮件地址或电话号码的所有权，将等效属性设置为已验证，并确认用于登录的用户账户。您选择的**要验证的属性**将决定验证消息的传送方式和目的地。

1. 在创建用户时，**验证属性更改**并不重要，但与属性验证有关。可以允许已更改但尚未验证其[登录属性的](user-pool-settings-attributes.md#user-pool-settings-aliases.title)用户继续使用其新属性值或原始属性值登录。有关更多信息，请参阅 [当用户更改其电子邮件或电话号码时应进行验证](signing-up-users-in-your-app.md#verifying-when-users-change-their-email-or-phone-number)。

1. **必填属性**显示用户注册或您创建用户之前必须为其提供值的属性。只能在创建用户池时设置必需属性。

1. **自定义属性**对用户创建和注册过程很重要，因为只有在首次创建用户时才能为*不可变的*自定义属性设置值。有关自定义属性的更多信息，请参阅[自定义属性](user-pool-settings-attributes.md#user-pool-settings-custom-attributes)。

1. 如果您希望用户能够使用[未经身份验证的](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pools-API-operations.html#user-pool-apis-auth-unauth) `SignUp` API 生成新账户，请在**自助注册**中选择**启用自行注册**。如果您禁用自助注册，则只能在 Amazon Cognito 控制台中或通过 API 请求[AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html)以管理员身份创建新用户。在自助注册处于非活动状态的用户池中，[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)API 请求会返回`NotAuthorizedException`，托管登录不会显示**注册**链接。

对于您计划以管理员身份创建用户的用户池，可以在**身份验证方法**菜单中**管理员设置的临时密码到期时间**下的设置中配置临时密码的持续时间。

以管理员身份创建用户的另一个重要元素是邀请消息。创建新用户时，Amazon Cognito 会给他们发送一条包含您的应用程序链接的消息，以便他们可以首次登录。可以在**身份验证方法**菜单中的**消息模板**下自定义这个消息模板。

您可以使用客户端密钥配置[机密应用程序客户端](user-pool-settings-client-apps.md#user-pool-settings-client-app-client-types.title)（通常是 Web 应用程序），以防止在没有应用程序客户端密钥的情况下注册。作为安全最佳实践，请勿在公共应用程序客户端（通常是移动应用程序）中分发应用程序客户端密钥。您可以在 Amazon Cognito 控制台的**应用程序客户端**菜单中使用客户端密钥创建应用程序客户端。

------
#### [ Amazon Cognito user pools API ]

您可以通过编程方式在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求中设置用于在用户池中创建用户的参数。

该[AdminCreateUserConfig](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-AdminCreateUserConfig)元素为用户池的以下属性设置值。

1. 启用自助注册

1. 向管理员创建的新用户发送的邀请消息

如果将以下示例添加到完整的 API 请求正文中，可设置一个用户池（自助注册为非活动状态）和一封基本的邀请电子邮件。

```
"AdminCreateUserConfig": { 
      "AllowAdminCreateUserOnly": true,
      "InviteMessageTemplate": { 
         "EmailMessage": "Your username is {username} and temporary password is {####}.",
         "EmailSubject": "Welcome to ExampleApp",
         "SMSMessage": "Your username is {username} and temporary password is {####}."
      }
   }
```

[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求的以下附加参数控制新用户的创建。

[AutoVerifiedAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-AutoVerifiedAttributes)  
注册新用户时要[自动向其发送消息的](user-pool-settings-email-phone-verification.md#user-pool-settings-email-phone-verification.title)属性、电子邮件地址或电话号码。

[策略](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-Policies)  
用户池[密码策略](managing-users-passwords.md#user-pool-settings-policies.title)。

[架构](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-Schema)  
用户池[自定义属性](user-pool-settings-attributes.md#user-pool-settings-custom-attributes.title)。它们对用户的创建和注册过程很重要，因为只有在首次创建用户时才能为*不可变的*自定义属性设置值。  
此参数还将为您的用户池设置必填属性。如果将以下文本插入到完整 API 请求正文的 `Schema` 元素中，将把 `email` 属性设为必填属性。  

```
{
            "Name": "email",
            "Required": true
}
```

------

# 注册并确认用户账户
<a name="signing-up-users-in-your-app"></a>

可通过以下任一方法将用户账户添加到您的用户池中：
+ 用户在您用户池的客户端应用程序中进行注册。这可以是移动应用程序或 Web 应用程序。
+ 您可以将用户账户导入到用户池中。有关更多信息，请参阅 [通过 CSV 文件将用户导入用户池中](cognito-user-pools-using-import-tool.md)。
+ 您可以在用户池中创建用户账户并邀请用户登录。有关更多信息，请参阅 [以管理员身份创建用户账户](how-to-create-user-accounts.md)。

自行注册的用户必须得到确认才可登录。导入和创建的用户已经过确认，但他们必须在首次登录时创建自己的密码。以下部分将介绍确认过程以及电子邮件和电话验证。

**注册时的密码**  
Amazon Cognito 要求所有用户在注册时提供密码，但以下情况除外。如果满足*所有*这些条件，则可以在注册操作中忽略密码。

1. [无密码登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)在您的用户池和应用程序客户端中处于活动状态。

1. 您的应用程序是使用 AWS SDK 中的身份验证模块定制的。托管登录和托管 UI 始终要求提供密码。

1. 用户为您允许的无密码登录方法（电子邮件或短信一次性密码 ()OTPs）提供属性值。例如，如果您允许使用电子邮件和电话 OTP 登录，则用户可以提供电话号码或电子邮件地址，但是如果您只允许使用电子邮件登录，则他们必须提供电子邮件地址。

1. 您的用户池会[自动验证](#allowing-users-to-sign-up-and-confirm-themselves)用户可在无密码登录中使用的属性。

1. 对于任何给定的[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)请求，用户都不会为 P [asswor](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html#CognitoUserPools-SignUp-request-Password) d 参数提供值。

## 用户账户确认概览
<a name="signup-confirmation-verification-overview"></a>

下图阐明了确认过程：

![\[当用户输入确认代码时，将自动验证电子邮件或电话。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/amazon-cognito-sign-in-confirm-user.png)


用户账户可以处于以下任一状态：

**已注册（未确认）**  
用户已成功注册，但在用户账户得到确认之前无法登录。在此状态下，用户已启用，但未得到确认。  
自行注册的新用户由此状态开始。

**已确认**  
用户账户已确认，用户可以登录。当用户输入代码或点击电子邮件链接以确认其用户账户时，系统将自动验证电子邮件或电话号码。代码或链接的有效期为 24 小时。  
如果管理员或预注册 Lambda 触发器确认了用户账户，则可能没有与该账户关联的经验证的电子邮件或电话号码。

**需要重置密码**  
用户账户已确认，但用户必须请求代码并重置其密码，然后才可以登录。  
由管理员或开发人员导入的用户账户以此状态开始。

**强制更改密码**  
用户账户已确认，用户可以使用临时密码进行登录。但在首次登录时，用户必须将其密码更改为新值，然后才能执行任何其他操作。  
由管理员或开发人员创建的用户账户以此状态开始。

**已禁用**  
在可以删除用户账户之前，必须禁用该用户的登录访问权限。

**更多资源**
+ [使用 Amazon Cognito 检测和修复不活跃的用户账户](https://aws.amazon.com/blogs/security/detecting-and-remediating-inactive-user-accounts-with-amazon-cognito/)

## 在注册时验证联系人信息
<a name="allowing-users-to-sign-up-and-confirm-themselves"></a>

当新用户注册您的应用程序时，您可能希望他们提供至少一种联系方式。例如，利用用户的联系人信息，您可以：
+ 在用户选择重置其密码时发送临时密码。
+ 在更新用户的个人信息或财务信息后向用户发送通知。
+ 发送促销信息（例如，特别优惠或折扣）。
+ 发送账户摘要或账单提醒。

对于像这样的使用案例，将消息发送到经过验证的目的地非常重要。否则，您可能会将消息发送到错误键入的无效电子邮件地址或电话号码。或者更糟糕的是，您可能会将敏感信息发送给冒充您的用户的坏人。

为了帮助确保您仅将消息发送给正确的人员，请配置您的 Amazon Cognito 用户池以使用户在注册时必须提供以下内容：

1. 一个电子邮件地址或电话号码。

1. Amazon Cognito 发送到该电子邮件地址或电话号码的验证码。如果 24 小时过去并且您的用户的代码或链接不再有效，请调用 [ResendConfirmationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html)API 操作生成并发送新的代码或链接。

通过提供验证码，用户可以证明他们有权访问收到该代码的邮箱或手机。在用户提供该代码后，Amazon Cognito 将通过以下方式更新用户池中的用户相关信息：
+ 将用户的状态设置为 `CONFIRMED`。
+ 更新用户的属性以指示已验证电子邮件地址或电话号码。

要查看此信息，您可以使用 Amazon Cognito 控制台。或者，您可以使用 `AdminGetUser` API 操作、带的`admin-get-user` AWS CLI命令或其中一个中的相应操作 AWS SDKs。

如果用户具有经验证的联系方式，Amazon Cognito 会在用户请求重置密码时自动向其发送消息。

### 确认和验证用户属性的其他操作
<a name="allowing-users-to-sign-up-and-confirm-themselves-other-actions"></a>

以下用户活动会验证用户属性。您无需将这些属性设置为自动验证：列出的操作在所有情况下都会将其标记为已验证。

**电子邮件地址**  

1. 使用电子邮件一次性密码（OTP）成功完成[无密码身份验证](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)。

1. 使用电子邮件 OTP 成功完成[多重身份验证（MFA）](user-pool-settings-mfa.md)。

**Phone number（电话号码）**  

1. 使用短信 OTP 成功完成[无密码身份验证](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)。

1. 使用短信 OTP 成功完成 [MFA](user-pool-settings-mfa.md)。

### 配置您的用户池以要求电子邮件或手机验证
<a name="verification-configure"></a>

验证用户的电子邮件地址和电话号码时，确保可以联系到用户。完成中的以下步骤， AWS 管理控制台 将您的用户池配置为要求您的用户确认其电子邮件地址或电话号码。

**注意**  
如果您的账户中还没有用户池，请参阅[用户池入门](getting-started-user-pools.md)。

**配置用户池**

1. 导航到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 从导航窗格中选择**用户池**。从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**登录**菜单，然后找到**属性验证和用户账户确认**。选择**编辑**。

1. 在 **Cognito 辅助验证和确认**下，选择是否**允许 Cognito 自动发送消息以进行验证和确认**。启用此设置后，当用户注册或您创建用户配置文件时，Amazon Cognito 会向您选择的用户联系人属性发送消息。为验证属性并确认登录的用户配置文件，Amazon Cognito 会通过消息向用户发送代码或链接。用户随后必须在您的 UI 中输入相应代码，这样，您的应用才能在 `ConfirmSignUp` 或 `AdminConfirmSignUp` API 请求中对其进行确认。
**注意**  
您还可以禁用 **Cognito 辅助验证和确认**并使用经过身份验证的 API 操作或 Lambda 触发器验证属性并确认用户。  
如果您选择此选项，则 Amazon Cognito 不会在用户注册时发送验证码。如果您要使用自定义身份验证流程验证至少一种联系方式，而不使用来自 Amazon Cognito 的验证码，请选择此选项。例如，您可以使用一个预注册 Lambda 触发器，该触发器将自动验证属于特定域的电子邮件地址。  
如果您不验证用户的联系人信息，用户可能无法使用您的应用程序。请记住，用户需要经验证的联系人信息才能：  
**重置密码** – 当用户在您的应用程序中选择调用 `ForgotPassword` API 操作的选项时，Amazon Cognito 会将临时密码发送到用户的电子邮件地址或电话号码。Amazon Cognito 仅在用户具有至少一个经验证的联系方式时发送此密码。
**通过使用电子邮箱地址或电话号码作为别名进行登录** – 如果您将用户池配置为允许这些别名，则用户只能在别名经过验证后使用别名进行登录。有关更多信息，请参阅 [自定义登录属性](user-pool-settings-attributes.md#user-pool-settings-aliases)。

1. 选择您的**要验证的属性**：  
**发送 SMS 消息，验证电话号码**  
Amazon Cognito 将在用户注册时通过 SMS 消息发送验证码。如果您通常通过 SMS 消息与用户通信，请选择此选项。例如，如果您要发送交付通知、约会确认或提醒，则将需要使用经过验证的电话号码。确认账户时，用户电话号码将成为已验证属性；您必须采取其它操作来验证用户电子邮件地址并与其进行通信。  
**发送电子邮件消息，验证电子邮件地址**  
Amazon Cognito 将在用户注册时通过电子邮件发送验证码。如果您通常通过电子邮件与用户通信，请选择此选项。例如，如果您要发送账单、订单摘要或特别优惠，则将需要使用经过验证的电子邮件地址。确认账户时，用户电子邮件地址将成为已验证属性；您必须采取其它操作来验证用户电话号码并与其进行通信。  
**如果电话号码可用，则发送 SMS 消息，否则发送电子邮件**  
如果您不要求所有用户都拥有相同的经验证的联系方式，请选择此选项。在这种情况下，您的应用程序中的注册页面可能会要求用户仅验证其首选联系方式。当 Amazon Cognito 发送验证码时，会将该代码发送到来自您应用程序的 `SignUp` 请求中提供的联系方式。如果用户同时提供了电子邮件地址和电话号码，并且您的应用程序在 `SignUp` 请求中提供了这两种联系方式，Amazon Cognito 将仅向电话号码发送验证码。  
如果您要求用户同时验证电子邮件地址和电话号码，则选择此选项。Amazon Cognito 将在用户注册时验证一种联系方式，而且您的应用程序必须在用户登录后验证另一种联系方式。有关更多信息，请参阅 [在您要求用户确认电子邮件地址和电话号码的情况下](#verification-email-plus-phone)。

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

### 使用电子邮件或电话验证的身份验证流程
<a name="verification-flow"></a>

如果您的用户池要求用户验证其联系人信息，则当用户注册时，您的应用程序必须促进以下流程：

1. 用户通过输入用户名、电话号码、 and/or 电子邮件地址以及可能的其他属性来注册您的应用程序。

1. Amazon Cognito 服务接收来自应用程序的注册请求。验证该请求包含注册所需的所有属性后，该服务将完成注册过程并向用户的手机（通过 SMS 消息）或电子邮件发送确认码。代码的有效期为 24 小时。

1. 该服务向应用程序返回信息，表示注册过程已完成且用户账户正等待确认。响应中包含关于确认代码所发送到位置的信息。此时，用户账户处于未确认状态，而且用户的电子邮件地址和电话号码未经验证。

1. 现在，应用程序会提示用户输入确认代码。用户无需立即输入代码。但是，用户只有在输入确认代码后才可登录。

1. 用户在应用程序中输入确认代码。

1. 应用程序调用 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html) 将代码发送到 Amazon Cognito 服务，该服务将验证代码并在代码正确时将用户账户设置为已确认状态。成功确认用户账户之后，Amazon Cognito 服务会自动将用于确认（电子邮件地址或电话号码）的属性标记为已验证。除非此属性的值发生更改，否则用户无需再次进行验证。

1. 此时，用户账户处于已确认状态，用户可以登录。

### 在您要求用户确认电子邮件地址和电话号码的情况下
<a name="verification-email-plus-phone"></a>

Amazon Cognito 在用户注册时仅验证一种联系方式。如果 Amazon Cognito 必须在验证电子邮件地址或电话号码之间进行选择，则会选择通过 SMS 消息发送验证码来验证电话号码。例如，如果您将用户池配置为允许用户验证电子邮件地址或电话号码，并且您的应用程序在注册时提供了这两个属性，则 Amazon Cognito 将仅验证电话号码。在用户验证其电话号码后，Amazon Cognito 会将用户的状态设置为 `CONFIRMED`，并允许用户登录您的应用程序。

在用户登录后，您的应用程序会提供相应选项来验证在注册期间未验证的联系方式。为了验证第二种联系方式，您的应用程序将调用 `VerifyUserAttribute` API 操作。请注意，此操作需要 `AccessToken` 参数，而 Amazon Cognito 只为经过身份验证的用户提供访问令牌。因此，您只能在用户登录后验证第二种联系方式。

如果您要求用户同时验证电子邮件地址和电话号码，请执行以下操作：

1. 配置用户池以允许用户验证电子邮件地址或电话号码。

1. 在应用程序的注册流程中，要求用户提供电子邮件地址和电话号码。调用 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html) API 操作，并为 `UserAttributes` 参数提供电子邮件地址和电话号码。此时，Amazon Cognito 会向用户的手机发送一个验证码。

1. 在应用程序界面中，会显示一个确认页面以供用户输入验证码。通过调用 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html) API 操作来确认用户。此时，用户的状态为 `CONFIRMED`，并且用户的电话号码已验证，但电子邮件地址未验证。

1. 显示登录页，并通过调用 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API 操作对用户进行身份验证。对用户进行身份验证后，Amazon Cognito 将向您的应用程序返回访问令牌。

1. 调用 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAttributeVerificationCode.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAttributeVerificationCode.html) API 操作。在请求中指定以下参数：
   + `AccessToken` – Amazon Cognito 在用户登录时返回的访问令牌。
   + `AttributeName` – 将 `"email"` 指定为属性值。

   Amazon Cognito 将向用户的电子邮件地址发送一个验证码。

1. 显示一个确认页面以供用户输入验证码。当用户提交代码时，请调用 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifyUserAttribute.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifyUserAttribute.html) API 操作。在请求中指定以下参数：
   + `AccessToken` – Amazon Cognito 在用户登录时返回的访问令牌。
   + `AttributeName` – 将 `"email"` 指定为属性值。
   + `Code` – 用户提供的验证码。

   此时，电子邮件地址已验证。

## 允许用户在您的应用程序中注册但以用户池管理员身份进行确认
<a name="signing-up-users-in-your-app-and-confirming-them-as-admin"></a>

您可能不希望您的用户池自动在用户池中发送验证消息，但仍希望允许任何人注册账户。例如，该模型为人工审查新的注册请求以及批量验证和处理注册留出了空间。您可以在 Amazon Cognito 控制台中或通过 IAM 身份验证的 API 操作确认新的用户账户。[AdminConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminConfirmSignUp.html)无论您的用户池是否发送验证消息，您都能以管理员身份确认用户账户。

您只能使用此方法确认用户的自助注册。要确认您以管理员身份创建的用户，请创建`Permanent`设置为[AdminSetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserPassword.html)的 API 请求`True`。

1. 用户通过输入用户名、电话号码、 and/or 电子邮件地址以及可能的其他属性来注册您的应用程序。

1. Amazon Cognito 服务接收来自应用程序的注册请求。验证该请求包含注册所需的所有属性之后，该服务将完成注册过程，并向应用程序返回信息，表示注册已完成且正在等待确认。此时，用户账户处于未确认状态。账户经过确认后，用户才可登录。

1. 确认用户的账户。您必须使用 AWS 凭据登录 AWS 管理控制台 或签署 API 请求才能确认账户。

   1. 要在 Amazon Cognito 控制台中确认用户，请导航到**用户**菜单，选择要确认的用户，然后从**操作**菜单中选择**确认**。

   1. 要在 AWS API 或 CLI 中确认用户，请创建 [AdminConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminConfirmSignUp.html)API 请求，或者[admin-confirm-sign-up](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-confirm-sign-up.html)在 AWS CLI。

1. 此时，用户账户处于已确认状态，用户可以登录。

## 计算密钥哈希值
<a name="cognito-user-pools-computing-secret-hash"></a>

作为最佳实践，请将客户端密钥分配给您的机密应用程序客户端。当您向应用程序客户端分配客户端密钥时，您的 Amazon Cognito 用户池 API 请求必须包括一个哈希值，用于包含请求正文中的客户端密钥。为了验证您对以下列表中 API 操作的客户端密钥的了解，请将客户端密钥与应用程序客户端 ID 和用户的用户名连接起来，然后对该字符串进行 base64 编码。

应用程序将用户登录到具有密钥哈希值的客户端时，您可以使用任何用户池登录属性的值作为密钥哈希值的用户名元素。应用程序在使用 `REFRESH_TOKEN_AUTH` 的身份验证操作中请求新令牌时，用户名元素的值取决于您的登录属性。如果您的用户池没有将 `username` 用作登录属性，请通过用户的访问令牌或 ID 令牌中的 `sub` 声明设置密钥哈希用户名值。如果 `username` 为登录属性，请通过 `username` 声明设置密钥哈希用户名值。

以下 Amazon Cognito 用户池 APIs 接受参数中的客户端密钥哈希值。`SecretHash`
+ [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html)
+ [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html)
+ [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)
+ [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html)
+ [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)

此外，以下内容 APIs 接受`SECRET_HASH`参数中的客户端密钥哈希值，无论是在身份验证参数中还是在质询响应中。


| API 操作 | SECRET\$1HASH 的父参数 | 
| --- |--- |
| InitiateAuth | AuthParameters | 
| AdminInitiateAuth | AuthParameters | 
| RespondToAuthChallenge | ChallengeResponses | 
| AdminRespondToAuthChallenge | ChallengeResponses | 

密钥哈希值是 Base 64 编码的加密哈希消息身份验证代码（HMAC，Hash Message Authentication Code），使用用户池客户端的私有密钥、用户名以及消息中的客户端 ID 进行计算。以下伪代码显示如何计算此值。在此伪代码中，`+`表示串联，表示使用 Hmac 生成 HMAC 值的函数，并`HMAC_SHA256``Base64`表示生成 Base-64 编码SHA256版本的哈希输出的函数。

```
Base64 ( HMAC_SHA256 ( "Client Secret Key", "Username" + "Client Id" ) )
```

有关如何计算和使用`SecretHash`参数的详细概述，请参阅[如何解决我的 Amazon Cognito 用户池 API 中的 “无法验证客户端的秘密哈希” 错误？](https://aws.amazon.com/premiumsupport/knowledge-center/cognito-unable-to-verify-secret-hash/)<client-id> 在 AWS 知识中心中。

您可以在服务器端应用程序代码中使用以下代码示例：

------
#### [ Shell ]

```
echo -n "[username][app client ID]" | openssl dgst -sha256 -hmac [app client secret] -binary | openssl enc -base64
```

------
#### [ Java ]

```
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
 
public static String calculateSecretHash(String userPoolClientId, String userPoolClientSecret, String userName) {
    final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
    
    SecretKeySpec signingKey = new SecretKeySpec(
            userPoolClientSecret.getBytes(StandardCharsets.UTF_8),
            HMAC_SHA256_ALGORITHM);
    try {
        Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
        mac.init(signingKey);
        mac.update(userName.getBytes(StandardCharsets.UTF_8));
        byte[] rawHmac = mac.doFinal(userPoolClientId.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(rawHmac);
    } catch (Exception e) {
        throw new RuntimeException("Error while calculating ");
    }
}
```

------
#### [ Python ]

```
import sys
import hmac, hashlib, base64 
username = sys.argv[1] 
app_client_id = sys.argv[2] 
key = sys.argv[3] 
message = bytes(sys.argv[1]+sys.argv[2],'utf-8') 
key = bytes(sys.argv[3],'utf-8') 
secret_hash = base64.b64encode(hmac.new(key, message, digestmod=hashlib.sha256).digest()).decode() 
print("SECRET HASH:",secret_hash)
```

------

## 无需验证电子邮件或电话号码即可确认用户账户
<a name="confirming-user-without-verification-of-email-or-phone-number"></a>

预注册 Lambda 触发器可用于在注册时自动确认用户账户，而无需提供确认码或者验证电子邮件或电话号码。通过此方法进行确认的用户可立即登录，而无需接收代码。

您还可通过此触发器将用户的电子邮件或电话号码标记为已验证。

**注意**  
虽然这种方法对刚入门的用户而言很方便，但建议至少自动验证电子邮件或电话号码之一。否则，如果用户忘记密码，可能就无法进行恢复。

如果您不要求用户在注册时接收并输入确认码，也不在预注册 Lambda 触发器中自动验证电子邮件和电话号码，则您将承担对于该用户账户不具备经验证的电子邮件地址或电话号码的风险。用户可以稍后验证电子邮件地址或电话号码。但是，如果用户忘记自己的密码且没有经验证的电子邮件地址或电话号码，则用户将被锁定而无法使用账户，因为忘记密码流程需要经验证的电子邮件或电话号码以便向用户发送验证码。

## 当用户更改其电子邮件或电话号码时应进行验证
<a name="verifying-when-users-change-their-email-or-phone-number"></a>

在您配置了多个登录名的用户池中，用户可以在登录时输入电话号码或电子邮件地址作为用户名。当用户在应用程序中更新其电子邮件地址或电话号码时，Amazon Cognito 会立即向他们发送带有验证码的消息，用于验证其对新属性值的所有权。要启用自动发送这些验证码，请参阅[配置电子邮件或电话验证](user-pool-settings-email-phone-verification.md)。

收到验证码的用户必须在请求中将该验证码提供给 Amazon Cognito。[VerifyUserAttribute](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifyUserAttribute.html)提供验证码后，他们的属性将被标记为已验证。通常，当用户更新其电子邮件地址或电话号码时，您需要先验证他们是否拥有这个新值，然后他们才能使用新值登录和接收消息。用户池有一个可配置的选项，用于确定用户是否必须验证其电子邮件地址或电话号码的更新信息。

此选项是用户池属性 `AttributesRequireVerificationBeforeUpdate`。在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-UserAttributeUpdateSettings)或[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#CognitoUserPools-UpdateUserPool-request-UserAttributeUpdateSettings)请求中对其进行配置，或者在 Amazon Cognito 控制台**的 “**注册**” 菜单中使用待更新时保持原始属性值处于活动状态**设置。

您的用户池如何处理电子邮件地址和电话号码的更新与用户池的用户名配置有关。用户池用户名可以位于*用户名属性*配置中，其中登录名为电子邮件地址、电话号码或两者兼而有之。它们也可以位于*别名属性*配置中，其中 `username` 属性是登录名，电子邮件地址、电话号码或首选用户名作为备用登录名。有关更多信息，请参阅[自定义登录属性](user-pool-settings-attributes.md#user-pool-settings-aliases)。

 您也可以使用自定义消息 Lambda 触发器来自定义验证消息。有关更多信息，请参阅 [自定义消息 Lambda 触发器](user-pool-lambda-custom-message.md)。当用户的电子邮件地址或电话号码未经验证时，您的应用程序应通知用户必须验证该属性，并为用户提供一个按钮或链接来输入其验证码。

下表描述了当用户更改其登录属性的值时，`AttributesRequireVerificationBeforeUpdate` 和别名设置如何确定结果。


| 用户名配置 | 用户必须验证新属性时的行为 | 用户不需要验证新属性时的行为 | 
| --- | --- | --- | 
| 用户名属性 | 原始属性仍处于已验证状态，有资格登录，且为原始值。当用户验证新值时，Amazon Cognito 会更新属性值，将其标记为已验证，并使其符合登录资格。 | Amazon Cognito 将属性更新为新值。新值具有登录资格。当用户验证新值时，Amazon Cognito 会将其标记为已验证。 | 
| 别名属性 | 原始属性仍处于已验证状态，有资格登录，且为原始值。当用户验证新值时，Amazon Cognito 会更新属性值，将其标记为已验证，并使其符合登录资格。 | Amazon Cognito 将属性更新为新值。原始属性值或新属性值均无登录资格。当用户验证新值时，Amazon Cognito 会更新属性值，将其标记为已验证，并使其符合登录资格。 | 

**示例 1**  
用户 1 使用电子邮件地址 `user1@example.com` 登录您的应用程序，用户名为 `user1`（别名属性）。您的用户池配置为验证登录属性的更新并自动发送验证消息。他们请求将其电子邮件地址更新为 `user1+foo@example.com`。他们通过 `user1+foo@example.com` 接收验证电子邮件，并且只能使用电子邮件地址 `user1@example.com` *重新登录*。之后，他们输入验证码，并且只能使用电子邮件地址 `user1+foo@example.com` 重新登录。

**示例 2**  
用户 2 使用电子邮件地址 `user2@example.com` 登录您的应用程序，并提供用户名（别名属性）。您的用户池配置为*不*验证登录属性的更新并自动发送验证消息。他们请求将其电子邮件地址更新为 `user2+bar@example.com`。他们通过 `user2+bar@example.com` 接收验证电子邮件，并且*无法重新登录*。之后，他们输入验证码，并且只能使用电子邮件地址 `user2+bar@example.com` 重新登录。

**示例 3**  
用户 3 使用电子邮件地址 `user3@example.com` 登录您的应用程序，没有提供用户名（用户名属性）。您的用户池配置为*不*验证登录属性的更新并自动发送验证消息。他们请求将其电子邮件地址更新为 `user3+baz@example.com`。他们通过 `user3+baz@example.com` 接收验证电子邮件，但是他们*可以立即登录*，无需使用验证码执行任何其他操作。

## 针对由管理员或开发人员创建的用户账户的确认和验证过程
<a name="confirmation-and-verification-of-users-whose-accounts-youve-created"></a>

由管理员或开发人员创建的用户账户已经处于已确认状态，所以用户无需输入确认代码。Amazon Cognito 服务向这些用户发送的邀请消息包含用户名和临时密码。用户需要在登录前更改密码。有关更多信息，请参阅[自定义电子邮件和 SMS 消息](how-to-create-user-accounts.md#creating-a-new-user-customize-messages)中的 [以管理员身份创建用户账户](how-to-create-user-accounts.md)和[使用 Lambda 触发器自定义用户池工作流](cognito-user-pools-working-with-lambda-triggers.md)中的自定义消息触发器。

## 针对导入的用户账户的确认和验证过程
<a name="confirmation-and-verification-of-users-whose-accounts-youve-imported"></a>

使用 AWS 管理控制台、CLI 或 API 中的用户导入功能（参见[通过 CSV 文件将用户导入用户池中](cognito-user-pools-using-import-tool.md)）创建的用户账户已处于已确认状态，因此用户无需输入确认码。没有发送邀请消息。但是，导入的用户账户要求用户首先调用 `ForgotPassword` API 来请求代码，然后通过调用 `ConfirmForgotPassword` API 来使用发送的代码创建密码，之后方可登录。有关更多信息，请参阅 [要求导入的用户重置密码](cognito-user-pools-using-import-tool.md#cognito-user-pools-using-import-tool-password-reset)。

导入用户账户时，用户的电子邮件或电话号码必须已标记为已验证，从而用户无需验证即可登录。

## 在测试应用程序时发送电子邮件
<a name="managing-users-accounts-email-testing"></a>

当用户在您的用户池的客户端应用程序中创建和管理其账户时，Amazon Cognito 将向用户发送电子邮件。如果您将用户池配置为要求电子邮件验证，Amazon Cognito 将在以下情况下发送电子邮件：
+ 用户注册。
+ 用户更新其电子邮件地址。
+ 用户执行一项调用 `ForgotPassword` API 操作的操作。
+ 您以管理员身份创建用户账户。

根据发起电子邮件递送的操作，电子邮件将包含验证码或临时密码。您的用户必须接收这些电子邮件并理解消息。否则，他们可能无法登录并使用您的应用程序。

要确保电子邮件成功发送并且邮件看起来正确，请测试应用程序中从 Amazon Cognito 启动电子邮件传送的操作。例如，通过使用应用程序中的注册页面或通过使用 `SignUp` API 操作，您可以通过使用测试电子邮件地址进行注册来启动电子邮件传送。在通过此方式进行测试时，请记住以下几点：

**重要提示**  
当您使用电子邮件地址测试从 Amazon Cognito 启动电子邮件传送的操作时，请勿使用虚假的电子邮件地址（没有邮箱的电子邮件地址）。使用真实的电子邮件地址才能接收来自 Amazon Cognito 的电子邮件，而不会创建*查无此人的邮件*。  
在 Amazon Cognito 未能将电子邮件传送到收件人邮箱时会产生查无此人的邮件，如果邮箱不存在，则始终会发生这种情况。  
Amazon Cognito 限制了持续出现硬退邮件的 AWS 账户可以发送的电子邮件数量。

当您测试启动电子邮件传送的操作时，请使用下列电子邮件地址之一以防止出现查无此人的邮件：
+ 您拥有的用于测试的电子邮件账户的地址。当您使用自己的电子邮件地址时，您将收到 Amazon Cognito 发送的电子邮件。利用此电子邮件，您可以使用验证码来测试应用程序中的注册体验。如果您为用户池自定义了电子邮件，则可检查自定义项看起来是否正确。
+ 邮箱模拟器地址：*success@simulator.amazonses.com*。如果您使用模拟器地址，Amazon Cognito 将成功发送电子邮件，但您无法查看。当您不需要使用验证码并且不需要检查电子邮件时，此选项很有用。
+ 添加了任意标签的邮箱模拟器地址（如 *success\$1user1@simulator.amazonses.com* 或 *success\$1user2@simulator.amazonses.com*）。Amazon Cognito 可成功向这些地址发送电子邮件，但您无法查看其发送的电子邮件。当您希望通过向用户池添加多个测试用户来测试注册过程，并且每个测试用户都具有一个唯一的电子邮件地址时，此选项很有用。

# 配置电子邮件或电话验证
<a name="user-pool-settings-email-phone-verification"></a>

您可以在**身份验证方法**菜单下选择电子邮件或电话验证的设置。有关多重验证 (MFA) 的详细信息，请参阅[SMS 文本消息 MFA](user-pool-settings-mfa-sms-email-message.md)。

Amazon Cognito 使用 Amazon SNS 发送 SMS 消息。如果您 AWS 服务 之前没有发送过来自亚马逊 Cognito 或其他任何公司的短信，Amazon SNS 可能会将您的账户置于短信沙箱中。建议您在将账户从沙盒移到生产环境之前，向已验证的电话号码发送测试消息。此外，如果您计划向美国的目标电话号码发送短信，则必须从 Amazon Pinpoint 获取源 ID 或发件人 ID。要为 Amazon Cognito 用户池配置 SMS 消息，请参阅 [Amazon Cognito 用户池的短信设置](user-pool-sms-settings.md)。

Amazon Cognito 可以自动验证电子邮件地址或电话号码。要进行此验证，Amazon Cognito 将发送验证码或验证链接。对于电子邮件地址，Amazon Cognito 可以通过电子邮件发送代码或链接。当您在 Amazon Cognito 控制台的**消息模板**菜单中编辑**验证消息**模板时，您可以选择**验证类型**，即**代码**或**链接**。有关更多信息，请参阅 [自定义电子邮件验证消息](cognito-user-pool-settings-message-customizations.md#cognito-user-pool-settings-email-verification-message-customization)。

对于电话号码，Amazon Cognito 以 SMS 文本消息的形式发送代码。

Amazon Cognito 必须验证电话号码或电子邮件地址来确认用户，帮助他们恢复忘记的密码。或者，您可以使用注册前 Lambda 触发器或使用 API 操作自动确认用户[AdminConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminConfirmSignUp.html)。有关更多信息，请参阅 [注册并确认用户账户](signing-up-users-in-your-app.md)。

验证代码或链接的有效期为 24 小时。

如果您选择要求通过电子邮件地址或电话号码进行验证，则在用户注册时，Amazon Cognito 将自动发送验证代码或链接。如果用户池已配置了 [自定义 SMS 发件人 Lambda 触发器](user-pool-lambda-custom-sms-sender.md) 或 [自定义电子邮件发件人 Lambda 触发器](user-pool-lambda-custom-email-sender.md)，则会改为调用该函数。

**注意**  
Amazon SNS 会另外收取用于验证电话号码的 SMS 文本消息费用。发送电子邮件不收费。有关 Amazon SNS 定价的信息，请参阅 [Worldwide SMS 定价](https://aws.amazon.com/sns/sms-pricing/)。有关提供 SMS 消息收发服务的最新国家/地区列表，请参阅[支持的区域和国家/地区](https://docs.aws.amazon.com/sns/latest/dg/sms_supported-countries.html)。
当您在应用程序中测试从 Amazon Cognito 生成电子邮件的操作时，请使用 Amazon Cognito 可以发送到而不会查无此人的邮件的真实电子邮件地址。有关更多信息，请参阅 [在测试应用程序时发送电子邮件](signing-up-users-in-your-app.md#managing-users-accounts-email-testing)。
忘记密码流程要求通过用户的电子邮件或电话号码来验证用户。

**重要**  
如果用户同时注册了电话号码和电子邮件地址，并且用户池设置需要验证这两个属性，那么 Amazon Cognito 会通过 SMS 消息将验证码发送到电话号码上。Amazon Cognito 尚未验证电子邮件地址，因此您的应用程序必须致电[GetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html)以查看电子邮件地址是否在等待验证。如果确实需要验证，则应用程序必须致电[GetUserAttributeVerificationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAttributeVerificationCode.html)以启动电子邮件验证流程。然后它必须通过致电提交验证码[VerifyUserAttribute](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifyUserAttribute.html)。

您可以调整 AWS 账户 和单条消息的短信支出配额。该限额仅适用于发送 SMS 消息的费用。有关更多信息，请参阅**什么是账户级和消息级支出配额及其运作方式？** 在 [Amazon SNS FAQs](https://aws.amazon.com/sns/faqs/) 中。

Amazon Cognito 使用您创建用户池的地方或下表中传统的 Amazon SNS **备用区域的 Amazon SNS** 资源发送短信。 AWS 区域 亚太地区（首尔）区域中的 Amazon Cognito 用户池例外。这些用户池使用您在亚太地区（东京）区域中的 Amazon SNS 配置。有关更多信息，请参阅 [选择 S AWS 区域 MS 消息](user-pool-sms-settings.md#sms-choose-a-region)。


| Amazon Cognito 区域 | 旧版 Amazon SNS 备用区域 | 
| --- | --- | 
| 美国东部（俄亥俄州） | 美国东部（弗吉尼亚州北部） | 
| 亚太地区（孟买） | 亚太地区（新加坡） | 
| 亚太地区（首尔） | 亚太地区（东京） | 
| 加拿大（中部） | 美国东部（弗吉尼亚州北部） | 
| 欧洲地区（法兰克福） | 欧洲地区（爱尔兰） | 
| 欧洲地区（伦敦） | 欧洲地区（爱尔兰） | 

**示例：**如果您的 Amazon Cognito 用户池位于亚太地区（孟买）区域，并且您增加了在 ap-southeast-1 区域中的支出限额，则可能不希望请求单独增加 ap-south-1 的支出限额。而是可以使用亚太地区（新加坡）中的 Amazon SNS 资源。

## 验证对于电子邮件地址和电话号码的更新
<a name="user-pool-settings-verifications-verify-attribute-updates"></a>

在用户更改电子邮件地址或电话号码属性的值后，这些属性可以立即变为活动但未经验证的状态。Amazon Cognito 还可以要求您的用户在 Amazon Cognito 更新属性之前验证新值。当您要求用户首先验证新值时，他们可以使用原始值进行登录和接收消息，直到他们验证新值。

当您的用户可以使用其电子邮件地址或电话号码作为用户池中的登录别名时，他们的已更新属性的登录名取决于您是否要求验证已更新的属性。当您要求用户验证已更新的属性时，用户可以使用原始属性值登录，直到他们验证新值。如果您不要求用户验证已更新的属性，则在验证新值之前，用户无法使用新属性值或原始属性值登录或接收消息。

例如，您的用户池允许使用电子邮件地址别名登录，并要求用户在更新时验证其电子邮件地址。Sue 以 `sue@example.com` 身份登录，想将她的电子邮件地址更改为 `sue2@example.com`，但是不小心输入了 `ssue2@example.com`。Sue 没有收到验证电子邮件，所以她无法验证 `ssue2@example.com`。Sue 以 `sue@example.com` 身份登录，然后在您的应用程序中重新提交表单，以将她的电子邮件地址更新为 `sue2@example.com`。她收到此电子邮件，向您的应用程序提供验证码，然后开始以 `sue2@example.com` 身份登录。

**当用户更新属性并且您的用户池验证新的属性值时**
+ 在确认代码以验证新值之前，用户可以使用原始属性值登录。
+ 用户只有在确认代码以验证新值后，才能使用新属性值登录。
+ 如果您在 [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)API 请求`true`中`phone_number_verified`将`email_verified`或设置为，则他们可以在确认 Amazon Cognito 发送给他们的代码之前登录。

**当用户更新属性而您的用户池未验证新的属性值时**
+ 用户无法使用原始属性值登录或接收消息。
+ 在确认代码以验证新属性值之前，用户无法使用新属性值登录或接收除确认码之外的消息。
+ 如果您在 [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)API 请求`true`中`phone_number_verified`将`email_verified`或设置为，则他们可以在确认 Amazon Cognito 发送给他们的代码之前登录。

## 当用户更新其电子邮件地址或电话号码时，需要进行属性验证


1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 在导航窗格中，选择 **用户池**，然后选择要编辑的用户池。

1. 在**注册**菜单中，在**属性验证和用户账户确认**下选择**编辑**。

1. 选择 **Keep original attribute value active when an update is pending**（等待更新时，保持原始属性值处于活动状态）。

1. 在 **Active attribute values when an update is pending**（等待更新时的活动属性值）下，选择您希望在 Amazon Cognito 更新值之前要求用户验证的属性。

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

要要求使用 Amazon Cognito API 进行属性更新验证，您可以在请求中设置`AttributesRequireVerificationBeforeUpdate`参数。[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)

## 授权 Amazon Cognito 代表您发送消息。
<a name="user-pool-settings-verifications-iam-role-for-sms"></a>

要代表您向您的用户发送短信，Amazon Cognito 需要具有您的权限。要授予该权限，您可以创建一个 AWS Identity and Access Management (IAM) 角色。在 Amazon Cognito 控制台的**身份验证方法**菜单的“SMS”下，选择**编辑**以设置角色。

# 配置 MFA、身份验证、验证和邀请消息
<a name="cognito-user-pool-settings-message-customizations"></a>

借助 Amazon Cognito，您可以自定义短信和电子邮件身份验证、验证以及用户邀请消息，从而增强应用程序的安全性和用户体验。对于某些消息，您可以在基于代码的验证或一键式链接验证之间进行选择。本主题讨论如何在 Amazon Cognito 控制台中对身份验证和验证通信进行个性化设置。

在**消息模板**菜单中，您可以自定义：
+ 用于一次性密码（OTP）和多重（MFA）身份验证的电子邮件和短信模板
+ 您的 SMS 和电子邮件验证消息
+ 电子邮件的验证类型–代码或链接
**注意**  
当用户注册或重新发送确认码时，Amazon Cognito 会在验证消息中发送包含您的基于链接的模板的链接。来自属性更新和密码重置操作的电子邮件使用代码模板。
+ 您的用户邀请消息
+ 流经用户池的电子邮件的 FROM 和 REPLY-TO 电子邮件地址

**注意**  
只有在选择要求进行电话号码和电子邮件验证后，才会显示短信和电子邮件验证消息模板。同样，只有 MFA 设置为 **required**（必填）或 **optional**（可选）时，才会显示 SMS MFA 消息模板。

**Topics**
+ [消息模板](#cognito-user-pool-settings-message-templates)
+ [自定义电子邮件和短信 MFA 消息](#cognito-user-pool-settings-SMS-message-customization)
+ [自定义电子邮件验证消息](#cognito-user-pool-settings-email-verification-message-customization)
+ [自定义用户邀请消息](#cognito-user-pool-settings-user-invitation-message-customization)
+ [自定义您的电子邮件地址](#cognito-user-pool-settings-email-address-customization)
+ [授权 Amazon Cognito 代表您发送 Amazon SES 电子邮件（通过自定义 FROM 电子邮件地址）](#cognito-user-pool-settings-ses-authorization-to-send-email)

## 消息模板
<a name="cognito-user-pool-settings-message-templates"></a>

您可以使用消息模板，在消息中插入占位符。Amazon Cognito 使用相应的值替换占位符。您可以在任何类型的消息模板中引用*通用模板占位符*，但并非所有消息类型中都会出现这些值。


**通用模板占位符**  

|  说明  |  令牌  | 消息类型 | 
| --- | --- | --- | 
| 验证代码 | \$1\$1\$1\$1\$1\$1 | 验证、确认和 MFA 消息 | 
| 临时密码 | \$1\$1\$1\$1\$1\$1 | 忘记密码和邀请消息 | 
| 用户名 | \$1username\$1 | 邀请和高级安全消息 | 

其中一个具有[威胁防护](cognito-user-pool-settings-threat-protection.md)的可用自动响应是通知用户，Amazon Cognito 检测到潜在恶意活动。您可以使用高级安全模板占位符执行以下操作：
+ 包括某个事件的特定详细信息，例如 IP 地址、城市、国家/地区、登录时间、设备名称。Amazon Cognito 威胁防护可以分析这些详细信息。
+ 验证一键式链接是否有效。
+ 使用事件 ID、反馈令牌和用户名构建您自己的一键式链接。

**注意**  
要生成一键式链接并在高级安全电子邮件模板中使用 `{one-click-link-valid}` 和 `{one-click-link-invalid}` 占位符，您必须已经为用户池配置了域。

威胁防护功能可添加以下占位符，您可以将其插入到消息模板中。这些占位符适用于**自适应身份验证消息**，即 Amazon Cognito 向已对其会话进行风险级别评估的用户发送的通知。要使用这些变量配置消息模板，请在 Amazon Cognito 控制台中更新威胁防护的**全功能**配置，或者在请求中[SetRiskConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetRiskConfiguration.html)提交模板。


**高级安全模板占位符**  

|  说明  |  令牌  | 
| --- | --- | 
| IP 地址 | \$1ip-address\$1 | 
| 城市 | \$1city\$1 | 
| 国家/地区 | \$1country\$1 | 
| 登录时间 | \$1login-time\$1 | 
| 设备名称 | \$1device-name\$1 | 
| 一键式链接有效 | \$1one-click-link-valid\$1 | 
| 一键式链接无效 | \$1one-click-link-invalid\$1 | 
| 事件 ID | \$1event-id\$1 | 
| 反馈令牌 | \$1feedback-token\$1 | 

## 自定义电子邮件和短信 MFA 消息
<a name="cognito-user-pool-settings-SMS-message-customization"></a>

要自定义用于[多重身份验证（MFA）](user-pool-settings-mfa.md)的短信和电子邮件，请从 Amazon Cognito 用户池控制台的**消息模板**菜单编辑 **MFA 消息**。

**重要**  
您的自定义消息必须包含 `{####}` 占位符。该占位符会在消息发送之前替换为身份验证代码。

Amazon Cognito 设置的短信（包括验证码）的最大长度为 140 个 UTF-8 字符。

### 自定义 SMS 验证消息
<a name="cognito-user-pool-settings-SMS-verification-message-customization"></a>

要自定义用于电话号码验证的短信，请从用户池的**消息模板**菜单编辑**验证消息**模板。

**重要**  
您的自定义消息必须包含 `{####}` 占位符。该占位符会在消息发送之前替换为验证代码。

消息的最大长度为 140 个 UTF-8 字符，其中包括验证代码。

## 自定义电子邮件验证消息
<a name="cognito-user-pool-settings-email-verification-message-customization"></a>

要使用 Amazon Cognito 验证用户池中用户的电子邮件地址，您可以向用户发送一封电子邮件，其中包含用户可以点击的链接或可以输入的代码。

要自定义用于电子邮件地址验证消息的电子邮件主题和消息内容，请从用户池的**消息模板**菜单编辑**验证消息**模板。在编辑**验证消息**模板时，您可以选择**验证类型**，即**代码**或**链接**。

当您选择**代码**作为验证类型时，您的自定义消息必须包含 `{####}` 占位符。发送消息时，验证代码会替换占位符。

当您选择**链接**作为验证类型时，您的自定义消息必须包含格式为 `{##Verify Your Email##}` 的占位符。您可以更改占位符之间的文本字符串，例如 `{##Click here##}`。标题为 *Verify Your Email*（验证您的电子邮件）的验证链接将替换此占位符。

电子邮件验证消息的链接将您的用户定向到类似于以下示例的 URL。

```
https://<your user pool domain>/confirmUser/?client_id=abcdefg12345678&user_name=emailtest&confirmation_code=123456
```

消息的最大长度为 20000 个 UTF-8 字符，其中包括验证代码（如果有）。您可以在此消息中使用 HTML 标签来格式化内容。

## 自定义用户邀请消息
<a name="cognito-user-pool-settings-user-invitation-message-customization"></a>

您可以通过从**消息模板**菜单编辑**邀请消息**模板，来自定义 Amazon Cognito 通过短信或电子邮件发送给新用户的用户邀请消息。

**重要**  
您的自定义消息必须包含 `{username}` 和 `{####}` 占位符。当 Amazon Cognito 发送邀请消息时，它会将这些占位符替换为您用户的用户名和密码。

SMS 消息的最大长度为 140 个 UTF-8 字符，其中包括验证代码。电子邮件的最大长度为 20000 个 UTF-8 字符，其中包括验证代码。您可以在电子邮件中使用 HTML 标签来格式化内容。

## 自定义您的电子邮件地址
<a name="cognito-user-pool-settings-email-address-customization"></a>

默认情况下，Amazon Cognito 通过 **no-reply@verificationemail.com** 向用户池中的用户发送电子邮件。您可以选择指定自定义 FROM 和 REPLY-TO 电子邮件地址来代替 **no-reply@verificationemail.com**。

**自定义 FROM 和 REPLY-TO 电子邮件地址**

1. 导航到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)，选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**身份验证方法**菜单。在 **Email**（电子邮件）下，选择 **Edit**（编辑）。

1. 选择 **SES Region**（SES 区域）。

1. 从在您所选 **SES Region**（SES 区域）中已经过 Amazon SES 验证的电子邮件地址列表中，选择 **FROM email address**（发件人电子邮件地址）。要使用来自经过验证的域名的电子邮件地址，请在 AWS Command Line Interface 或 AWS API 中配置电子邮件设置。有关更多信息，请参阅《Amazon Simple Email Service 开发人员指南》**中的[在 Amazon SES 中验证电子邮件地址和域](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-addresses-and-domains.html)。

1. 从您所选 **SES Region**（SES 区域）中配置集的列表中，选择 **Configuration set**（配置集）。

1. 为您的电子邮件消息输入易记且格式为 `John Stiles <johnstiles@example.com>` 的 **FROM sender name**（FROM 发件人名称）。

1. 要自定义 REPLY-TO 电子邮件地址，请在 **REPLY-TO email address**（REPLY-TO 电子邮件地址）字段中输入有效的电子邮件地址。

## 授权 Amazon Cognito 代表您发送 Amazon SES 电子邮件（通过自定义 FROM 电子邮件地址）
<a name="cognito-user-pool-settings-ses-authorization-to-send-email"></a>

您可以将 Amazon Cognito 配置为从自定义 FROM 电子邮件地址而不是默认地址发送电子邮件。要使用自定义地址，您必须授予 Amazon Cognito 权限，才能从经过 Amazon SES 验证的身份发送电子邮件。大多数情况下，您可以创建发送授权策略来授予权限。有关更多信息，请参阅《Amazon Simple Email Service 开发人员指南》**中的[使用 Amazon SES 的发送授权](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization.html)。

当您将用户池配置为使用 Amazon SES 处理电子邮件时，Amazon Cognito 会在您的账户中创建 `AWSServiceRoleForAmazonCognitoIdpEmailService` 角色来授予对 Amazon SES 的访问权限。使用 `AWSServiceRoleForAmazonCognitoIdpEmailService` 服务相关角色时无需发送授权策略。只需在用户池中使用默认电子邮件功能*和*经过验证的 Amazon SES 身份作为 FROM 地址时，才需要添加发送授权策略。

有关 Amazon Cognito 创建的服务相关角色的更多信息，请参阅[对 Amazon Cognito 使用服务相关角色](using-service-linked-roles.md)。

以下示例发送授权策略授予 Amazon Cognito 使用经 Amazon SES 验证的身份的有限能力。Amazon Cognito 在代表 `aws:SourceArn` 中的用户池和 `aws:SourceAccount` 条件中的账户时才能发送电子邮件。有关更多示例，请参阅《Amazon Simple Email Service 开发人员指南》**中的 [Amazon SES 发送授权策略示例](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-policy-examples.html)。

**注意**  
在此示例中，“Sid”值为唯一标识语句的任意字符串。有关策略语法的更多信息，请参阅《Amazon Simple Email Service 开发人员指南》**中的 [Amazon SES 发送授权策略](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-policies.html)。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "stmnt1234567891234",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "email.cognito-idp.amazonaws.com"
                ]
            },
            "Action": [
                "SES:SendEmail",
                "SES:SendRawEmail"
            ],
            "Resource": "arn:aws:ses:us-east-1:111122223333:identity/support@example.com",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "111122223333"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:cognito-idp:us-east-1:111122223333:userpool/us-east-1_EXAMPLE"
                }
            }
        }
    ]
}
```

------

当您从下拉菜单中选择 Amazon SES 身份时，Amazon Cognito 控制台会为您添加相似策略。如果您使用 CLI 或 API 配置用户池，则必须将与前例结构相同的策略附加到您的 Amazon SES 身份。

# 以管理员身份创建用户账户
<a name="how-to-create-user-accounts"></a>

用户池不仅仅是客户身份和访问管理（CIAM）用户目录，互联网上的任何人都可以在您的应用程序中注册用户配置文件。您可以禁用自助注册。您可能已经认识您的客户，并且只想接纳那些事先获得授权的客户。您可以使用[私有 SAML 2.0 或 OIDC 身份提供者](cognito-user-pools-identity-federation.md)、通过[导入用户](cognito-user-pools-import-users.md)、通过[在注册时筛选用户](user-pool-lambda-pre-sign-up.md)，或者通过使用管理 API 操作创建用户，您可以在应用程序周围设置手动身份验证护栏。您的用户管理创建工作流程可以是编程的，即在用户在其他系统中注册后对其进行配置，也可以在 Amazon Cognito 控制台中进行 case-by-case或测试。

当您以管理员身份创建用户时，Amazon Cognito 会为他们设置临时密码并发送欢迎或邀请消息。他们可以点击邀请消息中的链接进行首次登录、设置密码并确认其账户。以下页面说明了如何创建新用户和配置欢迎消息。有关使用用户池 API 和 AWS SDK 或 CDK 创建用户的更多信息，请参阅[AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html)。

创建用户池后，您可以使用 AWS 管理控制台、以及 AWS Command Line Interface 或 Amazon Cognito API 创建用户。您可以为用户池中的新用户创建配置文件，并通过 SMS 或电子邮件向用户发送带有注册说明的欢迎消息。

以下是管理员如何管理用户池中的用户的一些示例。
+ 在 Amazon Cognito 控制台中或通过 `AdminCreateUser` API 操作创建新用户配置文件。
+ 将无密码 username-and-password、密钥和自定义[身份验证流程](amazon-cognito-user-pools-authentication-flow-methods.md)提供给您的用户池和应用程序客户端。
+ 设置用户属性值。
+ 创建自定义属性。
+ 在 `AdminCreateUser` API 请求中设置不可变[自定义属性](user-pool-settings-attributes.md#user-pool-settings-custom-attributes)的值。此功能在 Amazon Cognito 控制台中不可用。
+ 指定临时密码，创建没有密码的用户，或者允许 Amazon Cognito 自动生成密码。
+ 创建新用户并自动确认其账户，验证他们的电子邮件地址或验证他们的电话号码。
+ 通过 AWS 管理控制台 或 Lambda 触发器（如自定义消息、自定义短信发送器和[自定义电子邮件发[件人）为新用户指定自定义短信](user-pool-lambda-custom-sms-sender.md)和[电子邮件](user-pool-lambda-custom-email-sender.md)邀请消息](user-pool-lambda-custom-message.md)。
+ 指定是否通过 SMS、电子邮件或两者发送邀请消息。
+ 通过调用 `AdminCreateUser` API，并为 `RESEND` 参数指定 `MessageAction`，向现有用户重新发送欢迎消息。
+ 创建用户时[禁止](#admincreateuserwalkthrough-step-invitationmessage)发送邀请消息。
+ 为新用户账户指定长达 90 天的到期时间限制。
+ 允许用户自行注册或要求只能由管理员添加新用户。

管理员还可以在服务器端应用程序中使用 AWS 凭据登录用户。有关更多信息，请参阅 [API 和 SDK 身份验证的授权模型](authentication-flows-public-server-side.md)。

## 用户身份验证流程和创建用户
<a name="how-to-create-user-accounts-flows"></a>

根据用户池的配置，以管理员身份创建用户的选项会有所不同。*身份验证流程*或可供用户登录和 MFA 的方法可以更改您创建用户以及向他们发送的消息的方式。以下是用户池中可用的一些身份验证流程。
+ 用户名和密码
+ 通行密钥
+ 使用第三方登录 IdPs
+ 无需密码，使用电子邮件和短信一次性密码 () OTPs
+ 使用电子邮件、短信和身份验证器应用程序进行多因素身份验证 OTPs
+ 使用 Lambda 触发器的自定义身份验证

有关如何配置这些登录因素的更多信息，请参阅[使用 Amazon Cognito 用户池进行身份验证](authentication.md)。

## 创建无密码用户
<a name="how-to-create-user-accounts-thingstoknow-passwordless"></a>

如果您为用户池启用了无密码登录，则可以创建无密码用户。要创建无密码用户，必须为可用的无密码登录因素提供属性值。例如，如果您的用户池中提供电子邮件 OTP 无密码登录，则可以创建一个没有密码和电子邮件地址属性的用户。如果新用户只能通过密码执行身份验证流程，例如通行密钥或用户名密码，则必须为每个新用户创建或生成临时密码。

**创建新的无密码用户**
+ 在 Amazon Cognito 控制台中选择**请勿设置密码**
+ 忽略 `AdminCreateUser` API 请求的 `TemporaryPassword` 参数或将其留空

**无密码用户会自动得到确认**  
通常，当您创建新用户时，他们会获得临时密码并进入 `FORCE_CHANGE_PASSWORD` 状态。当您创建无密码用户时，他们会立即进入 `CONFIRMED` 状态。您无法向这些处于 `CONFIRMED` 状态的用户重新发送确认码。

**邀请消息会针对无密码用户发生变化。**  
默认情况下，Amazon Cognito 会向新用户发送一条[邀请消息](cognito-user-pool-settings-message-customizations.md#cognito-user-pool-settings-user-invitation-message-customization)，显示 `Your username is {userName} and your password is {####}.`。当您创建无密码用户时，消息会显示为 `Your username is {userName}.`。自定义您的邀请消息，以反映您是否要为用户设置密码。请在无密码身份验证模型中忽略 `{####}` 密码变量。

**当无密码因素可用时，您无法自动生成密码**  
如果您已将用户池配置为支持电子邮件或电话 OTP 无密码登录，则无法自动生成密码。对于每位将拥有密码的用户，在创建其配置文件时都必须设置一个临时密码。

**无密码用户必须具有所有必需属性的值**  
在创建*无*密码用户时，只有当用户为用户池中已标记为必填的所有属性都提供值时，您的请求才会成功。这适用于任何必需属性，而不仅仅是发送 OTP 所需的电话号码和电子邮件属性。

## 创建稍后将提供必需属性值的用户
<a name="how-to-create-user-accounts-thingstoknow-password-restrictions"></a>

您可能想在用户池中要求提供属性，但在以管理员身份创建用户之后，在应用程序中的用户交互期间收集这些属性。管理员可以在使用*临时密码*创建用户时忽略必需属性的值。您不能忽略无密码用户的必需属性值。

缺少必需属性值且使用临时密码的用户在首次登录时会收到 [NEW\$1PASSWORD\$1REQUIRED](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html#CognitoUserPools-RespondToAuthChallenge-request-ChallengeResponses) 质询。然后，他们可以在 `requiredAttributes` 参数中为缺少的必需属性提供一个值。只有当所有必需属性都[可变](user-pool-settings-attributes.md#user-pool-settings-custom-attributes)时，才能创建带有密码但没有必需属性的用户。只有当必需属性可从用户登录时使用的应用程序客户端[写入](user-pool-settings-client-apps.md#cognito-user-pools-app-idp-settings-about)时，用户才能通过 `NEW_PASSWORD_REQUIRED` 质询和必需属性值完成登录。

当您为管理员创建的用户设置永久密码时，他们的状态会更改为 `CONFIRMED`，并且您的用户池在他们首次登录时不会提示他们输入新密码*或*必需属性。

## 在中创建新用户 AWS 管理控制台
<a name="creating-a-new-user-using-the-console"></a>

您可以设置用户密码要求、配置发送给用户的邀请和验证消息，以及使用 Amazon Cognito 控制台添加新用户。

### 设置密码策略并启用自行注册
<a name="set-user-password-policy"></a>

您可以配置设置以最大限度地降低密码复杂性，以及用户是否可以在您的用户池 APIs 中使用公共方式进行注册。

**配置密码策略**

1. 导航到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)，选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**身份验证方法**菜单并找到**密码策略**。选择**编辑**。

1. 选择**自定义**的**密码策略模式**。

1. 选择**密码最小长度**。有关密码长度要求的限制，请参阅[用户池资源配额](https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html#limits-hard)。

1. 选择**密码复杂性**要求。

1. 选择管理员设置的密码应在多长时间内有效。

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

**允许自助注册**

1. 导航到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)，选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**注册**菜单并找到**自助注册**。选择**编辑**。

1. 选择是否**启用自助注册**。自助注册通常用于需要在不分发客户端密钥或 AWS Identity and Access Management (IAM) API 凭证的情况下在用户池中注册新用户的公共应用程序客户端。
**禁用自助注册**  
如果您不启用自助注册，则必须通过使用 IAM API 凭证的管理 API 操作或通过联合提供商登录来创建新用户。

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

### 自定义电子邮件和 SMS 消息
<a name="creating-a-new-user-customize-messages"></a>

**自定义用户消息**

当您邀请用户登录、注册用户账户或登录并提示用户进行多重身份验证（MFA）时，您可以自定义 Amazon Cognito 发送给用户的消息。
**注意**  
当您在用户池中创建用户并邀请他们登录时将发送**邀请消息**。Amazon Cognito 将初始登录信息发送到用户的电子邮件地址或电话号码。  
当用户在您的用户池中注册用户账户时将发送**验证消息**。Amazon Cognito 向用户发送代码。当用户向 Amazon Cognito 提供代码时，他们会验证自己的联系人信息并确认自己的账户以进行登录。验证代码的有效期为 24 小时。  
当您在用户池中启用 SMS MFA，并且已配置 SMS MFA 的用户登录并提示输入 MFA 时，将发送 **MFA 消息**。

1. 导航到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)，选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**消息模板**菜单并选择**验证消息**、**邀请消息**或 **MFA 消息**，然后选择**编辑**。

1. 自定义所选消息类型的消息。
**注意**  
自定义消息时，必须包括消息模板中的所有变量。如果变量（例如，**\$1\$1\$1\$1\$1\$1**）不包括在内，您的用户将没有足够的信息来完成消息操作。  
有关更多信息，请参阅[消息模板](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-settings-message-templates.html)。

1. 

   1. **验证消息**

      1. 选择用于**电子邮件**消息的**验证类型**。**代码**验证将发送用户必须输入的数字代码。**链接**验证将发送一个链接，用户可以点击该链接以验证其联系人信息。用于**链接**消息变量中的文本显示为超链接文本。例如，使用变量 \$1\$1\$1Click here\$1\$1\$1 的消息模板在电子邮件中显示为[单击此处]()。

      1. 输入用于**电子邮件**消息的**电子邮件主题**。

      1. 输入用于**电子邮件**消息的自定义**电子邮件消息**模板。您可以使用 HTML 自定义此模板。

      1. 输入用于 **SMS** 消息的自定义 **SMS 消息**模板。

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

   1. **邀请消息**

      1. 输入用于**电子邮件**消息的**电子邮件主题**。

      1. 输入用于**电子邮件**消息的自定义**电子邮件消息**模板。您可以使用 HTML 自定义此模板。

      1. 输入用于 **SMS** 消息的自定义 **SMS 消息**模板。

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

   1. **MFA 消息**

      1. 输入用于 **SMS** 消息的自定义 **SMS 消息**模板。

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

### 创建用户
<a name="creating-a-new-user-using-the-users-tab"></a>

**创建用户**

您可以从 Amazon Cognito 控制台为用户池创建新用户。通常，用户可以在设置密码后登录。要使用电子邮件地址登录，用户必须验证 `email` 属性。要使用电话号码登录，用户必须验证 `phone_number` 属性。要以管理员身份确认账户，您还可以使用 AWS CLI 或 API，或者使用联合身份提供商创建用户个人资料。有关更多信息，请参阅 [Amazon Cognito API 参考](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/)。

1. 导航到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)，选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**用户**菜单，然后选择**创建用户**。

1. 检查**用户池登录和安全要求**以获取有关密码要求、可用的账户恢复方法和用户池的别名属性的指导。

1. <a name="admincreateuserwalkthrough-step-invitationmessage"></a>选择您希望如何发送**邀请消息**。选择 SMS 消息和/或电子邮件消息。要禁止邀请消息，请选择**不要发送邀请**。
**注意**  
在您可以发送邀请消息之前，请在用户池的**身份验证方法**菜单中使用 Amazon Simple Notification Service 和 Amazon Simple Email Service 配置发件人和 AWS 区域 。收件人消息和数据费率适用。Amazon SES 单独向您收取电子邮件消息费用，Amazon SNS 单独向您收取 SMS 消息费用。

1. 选择用于新用户的**用户名**。

1. 选择您是要为用户**创建密码**，还是让 Amazon Cognito **生成密码**。如果用户池中提供[无密码登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)，则生成密码的选项不可用。任何临时密码都必须遵守用户池密码策略。

1. 选择**创建**。

1. 选择**用户**菜单，然后选择用户的**用户名**条目。添加和编辑**用户属性**和**组成员资格**。查看**用户事件历史记录**。

# 向用户池添加组
<a name="cognito-user-pools-user-groups"></a>

借助对 Amazon Cognito 用户池中组的支持，您可以创建和管理组、将用户添加到组以及从组中删除用户。使用组可创建用户集合以管理其权限或表示不同类型的用户。您可以为群组分配 AWS Identity and Access Management (IAM) 角色来定义群组成员的权限。

您可以使用组以在用户池中创建用户集合，这通常用于为这些用户设置权限。例如，您可以为作为您网站和应用程序的读者、贡献者或编辑者的用户创建单独的组。通过使用与组关联的 IAM 角色，您还可以为那些不同的组设置不同的权限，从而只有贡献者可以将内容放置在 Amazon S3 中，并且只有编辑者可以通过 Amazon API Gateway 中的 API 发布内容。

Amazon Cognito 会为您添加到用户池中的每个 OIDC 和社交身份[提供商 (](cognito-user-pools-identity-federation.md#cognito-user-pools-identity-federation-how-it-works)IdP) 创建一个用户组。 SAMl该组的名称采用 `[user pool ID]_[IdP name]` 格式，例如 `us-east-1_EXAMPLE_MYSSO` 或 `us-east-1_EXAMPLE_Google`。每个自动生成的唯一 IdP 用户配置文件都会自动添加到该组。[关联用户](cognito-user-pools-identity-federation-consolidate-users.md)不会自动添加到该组，但您可以通过另外的流程将其配置文件添加到该组。

您可以通过、和 CLI 在用户池中 AWS 管理控制台创建和管理群组。 APIs作为开发者（使用 AWS 证书），您可以创建、读取、更新、删除和列出用户池的群组。您还可以将用户添加到组和从组中删除用户。

在用户池中使用组不会产生额外费用。有关更多信息，请参阅 [Amazon Cognito 定价](https://aws.amazon.com/cognito/pricing/)。

## 向组分配 IAM 角色
<a name="assigning-iam-roles-to-groups"></a>

您可以使用组通过 IAM 角色控制资源的权限。IAM 角色包含信任策略和权限策略。角色的[信任](https://docs.aws.amazon.com/cognito/latest/developerguide/role-trust-and-permissions.html)策略指定谁可使用该角色。[权限](https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html#access-policies)策略指定组成员可以访问的操作和资源。在您创建 IAM 角色时，请设置角色的信任策略以允许您的组用户担任该角色。请在角色的权限策略中，指定您希望组具有的权限。

在 Amazon Cognito 中创建组时，可以通过提供角色的 [ARN](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns) 指定 IAM 角色。当组成员使用 Amazon Cognito 登录时，他们可以从身份池接收临时凭证。他们的权限由关联的 IAM 角色确定。

单个用户可处于多个组中。作为开发人员，当一个用户位于多个组中时，您可以使用以下选项自动选择 IAM 角色：
+ 您可以为每个组分配优先级值。将选择优先级较高（值较低）的组，并应用其关联的 IAM 角色。
+ 在通过身份池为用户请求 AWS 凭证时，您的应用程序还可以在参数中指定角色 ARN，从可用角色中[GetCredentialsForIdentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html)`CustomRoleARN`进行选择。指定的 IAM 角色必须与适用于用户的角色相匹配。

## 将优先级值分配到组
<a name="assigning-precedence-values-to-groups"></a>

一个用户可属于多个组。在用户的访问令牌和 ID 令牌中，`cognito:groups` 声明包含用户所属的所有组的列表。`cognito:roles` 断言包含与这些组对应的角色列表。

由于一个用户可以属于多个组，因此可为每个组分配一个优先级。这是一个非负数值，用于指定该组相对于用户池中用户所属其它组的优先级。零是代表最高优先级的值。具有较低优先级值的组优先于具有较高或空优先级值的组。如果一个用户属于两个或更多组，则具有最低优先级值的组的 IAM 角色将应用于用户 ID 令牌中的 `cognito:preferred_role` 声明。

两个组可以具有相同的优先级值。如果发生这种情况，则两个组之间不存在优先情况。如果具有相同优先级值的两个组还具有相同的角色 ARN，则该角色将用于每个组中用户的 ID 令牌的 `cognito:preferred_role` 陈述。如果两个群组的角色不同 ARNs，则不会在用户的 ID 令牌中设置`cognito:preferred_role`声明。

## 使用组控制使用 Amazon API Gateway 的权限
<a name="using-groups-to-control-permission-with-amazon-api-gateway"></a>

您可以使用用户池中的组控制使用 Amazon API Gateway 的权限。用户所属的组包含在 `cognito:groups` 声明中的用户池的 ID 令牌和访问令牌中。您可以通过请求向 Amazon API Gateway 提交 ID 或访问令牌，并使用 Amazon Cognito 用户池授权方获取 REST API。有关更多信息，请参阅[《API Gateway 开发人员指南》](https://docs.aws.amazon.com/apigateway/latest/developerguide/)中的[使用 Amazon Cognito 用户池作为授权方控制对 REST API 的访问](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html)。

您还可以使用自定义 JWT 授权方授权访问 Amazon API Gateway HTTP API。有关更多信息，请参阅《[API Gateway 开发](https://docs.aws.amazon.com/apigateway/latest/developerguide/)者指南》中的 “[ APIs 使用 JWT 授权者控制 HTTP 访问权限](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html)”。

## 组的限制
<a name="user-pool-user-groups-limitations"></a>

用户组受以下限制的约束：
+ 您可以创建的组的数量受 [Amazon Cognito 服务配额](quotas.md)的限制。
+ 不能对组进行嵌套。
+ 不能搜索组中的用户。
+ 不能按名称搜索组，但可以列出组。

## 在中创建新群组 AWS 管理控制台
<a name="creating-a-new-group-using-the-console"></a>

使用以下过程创建新组。

**创建新组。**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**组**菜单，然后选择**创建组**。

1. 在 **Create a group**（创建组）页面的 **Group name**（组名称）中，为您的新组输入一个易记名称。

1. 您可以选择使用以下任意字段提供有关此组的其它信息：
   + **Description**（说明）– 输入有关这个新组将用于什么的详细信息。
   + **Precedence**（优先顺序）– Amazon Cognito 根据给定用户所属群组具有的较低优先级值，评估并应用所有群组权限。将选择优先级较低的组，并应用其关联的 IAM 角色。有关更多信息，请参阅 [将优先级值分配到组](#assigning-precedence-values-to-groups)。
   + **IAM role**（IAM 角色）– 当您需要控制对资源的权限时，您可以为组分配 IAM 角色。如果您要将用户池与身份池集成，并且身份池配置为从令牌中选择角色，则 **IAM role (IAM 角色)** 设置将确定在用户的 ID 令牌中分配哪个角色。有关更多信息，请参阅 [向组分配 IAM 角色](#assigning-iam-roles-to-groups)。
   + **Add users to this group**（将用户添加到此组）– 创建后将现有用户添加为该组的成员。

1. 选择 **Create**（创建）以确认。

# 管理和搜索用户账户
<a name="how-to-manage-user-accounts"></a>

用户池可以包含数百万个用户。对于管理员来说，使用这种规模的数据集是一项挑战。Amazon Cognito 提供了用于查找和修改用户配置文件的工具。查找用户的主要方法是 Amazon Cognito 控制台的 “**用户**” 菜单，以及。[ListUsers](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html)在检索用户信息的方法中，这些选项不会像例如那样对成本产生影响[AdminGetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminGetUser.html)。

本指南的这一部分包含有关在用户池中查找和更新用户配置文件的信息。

## 查看用户属性
<a name="manage-user-accounts-viewing-user-attributes"></a>

请使用以下过程在 Amazon Cognito 控制台中查看用户属性。

**查看用户属性**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**用户**菜单，然后在列表中选择用户。

1. 在用户详细信息页面，您可以在 **User attributes**（用户属性）中查看哪些属性与用户关联。

## 重置用户的密码
<a name="manage-user-accounts-reset-user-password"></a>

请使用以下过程在 Amazon Cognito 控制台重置用户的密码。

**重置用户的密码**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**用户**菜单，然后在列表中选择用户。

1. 在用户详细信息页面上，选择 **Actions**（操作）、**Reset password**（重置密码）。

1. 在 **Reset password**（重置密码）对话框中，查看信息，准备就绪后，选择 **Reset**（重置）。

   该操作会立即导致向用户发送确认代码，并通过将用户状态更改为 `RESET_REQUIRED` 来禁用用户的当前密码。**Reset password**（重置密码）代码的有效期为 1 小时。

## 启用、禁用和删除用户账户
<a name="manage-user-accounts-enable-disable"></a>

您可以删除未使用的用户配置文件，或者如果您想临时阻止访问，可将其禁用。用户可以删除自己的账户，但只有用户池管理员才能启用和禁用用户账户。

**删除的影响**  
用户无法使用已删除的用户账户登录，要重新获得访问权限，必须注册或重新创建用户。

**禁用账户的影响**  
当您禁用用户账户时，Amazon Cognito 会自动使所有经过身份验证的会话失效，停用用户账户的登录，并[撤销他们的访问权限和刷新令牌](token-revocation.md)。当用户尝试登录您禁用的账户时，Amazon Cognito 会返回 `invalid_request` 错误及 `User is not enabled` 消息。这种行为不会随着应用程序客户端的[用户存在披露设置](cognito-user-pool-managing-errors.md)而改变。您可以禁用本地用户账户和联合用户账户的本地配置文件。当用户通过托管登录或经典的托管 UI 登录，然后您禁用其账户，在他们尝试使用维护其经过身份验证的会话的浏览器 Cookie 再次登录时，Amazon Cognito 会将他们重定向到登录页面。

**启用账户的影响**  
启用账户后，用户可以立即登录账户。默认情况下，用户账户处于启用状态。用户的属性和密码与其账户被禁用之前相同。无论您是禁用用户账户还是单独撤销刷新令牌，您的应用程序撤销的令牌在您启用拥有该令牌的用户账户后都将保持无效。

------
#### [ Delete a user account (console) ]

**删除用户账户**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**用户**菜单，然后选中列表中用户名旁边的单选按钮。

1. 选择**删除**。

1. 选择**禁用用户访问**。

1. 选择**删除**。

------
#### [ Delete a user account (API) ]

用户可以通过自助服务 access-token-authorized [DeleteUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUser.html)API 操作删除其账户。以下是一个示例 `DeleteUser` 请求正文。

```
{
   "AccessToken": "eyJra456defEXAMPLE"
}
```

管理员可以通过 IAM 授权的 [AdminDeleteUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDeleteUser.html)API 操作删除用户帐户。以下是一个示例 `AdminDeleteUser` 请求正文。

```
{
   "Username": "testuser",
   "UserPoolId": "us-west-2_EXAMPLE"
}
```

------
#### [ Disable a user account (console) ]

**禁用用户账户**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**用户**菜单，然后在列表中选择用户的用户名。

1. 在用户详细信息页面上，选择**操作**、**禁用用户访问**。

1. 在由此创建的对话框中，选择**禁用**。

------
#### [ Disable a user account (API) ]

管理员可以通过 IAM 授权的 [AdminDisableUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDisableUser.html)API 操作禁用用户帐户。以下是一个示例 `AdminDisableUser` 请求正文。

```
{
   "Username": "testuser",
   "UserPoolId": "us-west-2_EXAMPLE"
}
```

------
#### [ Enable a user account (console) ]

**启用用户账户**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**用户**菜单，然后在列表中选择用户的用户名。

1. 在用户详细信息页面上，选择**操作**、**启用用户访问**。

1. 在由此创建的对话框中，选择**启用**。

------
#### [ Enable a user account (API) ]

管理员可以通过 IAM 授权的 [AdminEnableUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminEnableUser.html)API 操作启用用户帐户。以下是一个示例 `AdminEnableUser` 请求正文。

```
{
   "Username": "testuser",
   "UserPoolId": "us-west-2_EXAMPLE"
}
```

------

## 搜索用户属性
<a name="manage-user-accounts-searching-user-attributes"></a>

如果您已创建用户池，则可以在 AWS 管理控制台的 **Users**（用户）面板中搜索。您也可以使用 Amazon Cognito [ListUsers API](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html)，它接受**筛选**器参数。

您可以搜索以下任何标准属性。自定义属性不可搜索。
+ username（区分大小写）
+ email
+ phone\$1number
+ name
+ given\$1name
+ family\$1name
+ preferred\$1username
+ cognito:user\$1status（在控制台中称为**Status**（状态））（区分大小写）
+ status（在控制台中称为**Enabled**（已启用））（区分大小写）
+ sub

**注意**  
您还可以使用客户端筛选条件列出用户。服务器端筛选条件匹配的属性不超过 1 个。对于高级搜索，请使用客户端筛选条件，其中包含 AWS Command Line Interface中 `list-users` 操作的 `--query` 参数。使用客户端筛选器时，会 ListUsers 返回零个或多个用户的分页列表。您可以连续接收多个结果为零的页面。对返回的每个分页令牌重复查询，直到您收到一个空的分页令牌值，然后查看合并结果。  
有关服务器端和客户端筛选的更多信息，请参阅《 AWS Command Line Interface 用户指南》中的[筛选 AWS CLI 输出](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-filter.html)。

## 使用搜索用户 AWS 管理控制台
<a name="cognito-user-pools-manage-user-accounts-searching-for-users-using-console"></a>

如果您已创建用户池，则可以在 AWS 管理控制台的 **Users**（用户）面板中搜索。

AWS 管理控制台 搜索始终是前缀（“以” 开头）搜索。

**在 Amazon Cognito 控制台中搜索用户**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。系统可能会提示您输入 AWS 凭证。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**用户**菜单，然后在搜索字段中输入用户名。请注意，某些属性值区分大小写 [例如，**Username**（用户名）]。

   您还可以通过调整搜索筛选条件来查找用户，将范围缩小到其它用户属性，如 **Email**（电子邮件）、**Phone number**（电话号码）或 **Last name**（姓）。

## 使用 `ListUsers` API 搜索用户
<a name="cognito-user-pools-searching-for-users-using-listusers-api"></a>

 [要从您的应用程序中搜索用户，请使用亚马逊 Cognito ListUsers API。](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html)此 API 使用以下参数：
+  `AttributesToGet`：一组字符串，其中每个字符串均为将针对搜索结果中的每位用户返回的用户属性的名称。要检索所有属性，请不要包含 `AttributesToGet` 参数或文本字符串值为 `null` 的请求 `AttributesToGet`。
+  `Filter`：筛选条件字符串，格式为 "`AttributeName` `Filter-Type` "`AttributeValue`""。筛选条件字符串中的引号必须使用反斜杠 (`\`) 字符进行转义。例如 `"family_name = \"Reddy\""`。如果筛选条件字符串为空，`ListUsers` 将返回用户池中的所有用户。
  +  `AttributeName`：要搜索的属性的名称。一次只能搜索一个属性。
**注意**  
您只能搜索标准属性。自定义属性不可搜索。这是因为只有索引属性可搜索，而自定义属性不可索引。
  +  `Filter-Type`：对于精确匹配，请使用 `=`，例如 `given_name = "Jon"`。对于前缀 (“starts with”) 匹配，请使用 `^=`，例如 `given_name ^= "Jon"`。
  +  `AttributeValue`：必须为每位用户匹配的属性值。
+  `Limit`：要返回的最大用户数。
+  `PaginationToken`：可从之前的搜索中获取更多结果的令牌。Amazon Cognito 会在一小时后让分页令牌过期。
+  `UserPoolId`：应对其执行搜索的用户池的用户池 ID。

所有搜索都区分大小写。搜索结果按以 `AttributeName` 字符串命名的属性进行升序排列。

## 使用 `ListUsers` API 的示例
<a name="cognito-user-pools-searching-for-users-listusers-api-examples"></a>

以下示例将返回所有用户并包括所有属性。

```
{
    "AttributesToGet": null,
    "Filter": "",
    "Limit": 10,
    "UserPoolId": "us-east-1_samplepool"
}
```

以下示例将返回电话号码以“\$11312”开头的所有用户并包括所有属性。

```
{
    "AttributesToGet": null,
    "Filter": "phone_number ^= \"+1312\"",
    "Limit": 10,
    "UserPoolId": "us-east-1_samplepool"
}
```

以下示例将返回姓氏为“Reddy”的前 10 位用户。对于每个用户，搜索结果包含用户的名字、电话号码和电子邮件地址。如果用户池中有 10 个以上相匹配的用户，则响应将包含一个分页标记。

```
{
    "AttributesToGet": [
        "given_name", 
        "phone_number", 
        "email"
    ],
    "Filter": "family_name = \"Reddy\"",
    "Limit": 10,
    "UserPoolId": "us-east-1_samplepool"
}
```

如果上一示例返回分页标记，则以下示例将返回与同一筛选条件字符串相匹配的接下来的 10 位用户。

```
{
    "AttributesToGet": [
        "given_name", 
        "phone_number", 
        "email"
    ],
    "Filter": "family_name = \"Reddy\"",
    "Limit": 10,
    "PaginationToken": "pagination_token_from_previous_search",
    "UserPoolId": "us-east-1_samplepool"
}
```

# 密码、账户恢复和密码策略
<a name="managing-users-passwords"></a>

所有登录到用户池的用户（甚至是[联合用户](cognito-terms.md#terms-federateduser)）都为其用户配置文件分配了密码。[本地用户](cognito-terms.md#terms-localuser)和[关联用户](cognito-terms.md#terms-linkeduser)在登录时必须提供密码。联合用户不使用用户池密码，而是使用其身份提供者（IdP）登录。您可以允许用户自行重置密码、以管理员身份重置或更改密码，以及[设置密码复杂度和历史策略](#user-pool-settings-policies)。

Amazon Cognito 不以明文形式存储用户密码。而是通过用户特定的加密盐来存储每个用户密码的哈希值。因此，您无法从用户池中的用户配置文件检索现有密码。作为一项最佳实践，请不要在任何地方存储明文用户密码。当用户忘记密码时，执行密码重置。

## 密码重置和恢复
<a name="user-pool-password-reset-and-recovery"></a>

用户忘记了自己的密码。您可能希望他们能够自己重置密码，或者您可能希望由管理员为他们重置密码。Amazon Cognito 用户池有这两种模式的选项。指南的这一部分介绍用户池设置和用于密码重置的 API 操作。

[ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)API 操作和托管登录选项**忘记密码了吗？** 向用户发送验证码，当他们确认自己拥有正确的密码时，他们便有机会设置新密码[ConfirmForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html)。这是自助式密码恢复模式。

**恢复未经验证的用户**  
您可以向已验证其电子邮件地址或电话号码的用户发送恢复消息。如果他们没有已确认的恢复电子邮件或电话，用户池管理员可以将其电子邮件地址或电话号码标记为已验证。在 Amazon Cognito 控制台中编辑用户的**用户属性**，然后选中**将电话号码标记为已验证**或**将电子邮件地址标记为已验证**旁边的复选框。您也可以在[AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)请求中将`email_verified`或设置`phone_number_verified`为 true。对于新用户，[ResendConfirmationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html)API 操作会向他们的电子邮件地址或电话号码发送新的验证码，他们就可以完成自助确认和验证。

**以管理员身份重置密码**  
[AdminSetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserPassword.html)和 [AdminResetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminResetUserPassword.html)API 操作是管理员启动的密码重置方法。 `AdminSetUserPassword`设置临时或永久密码，并以与相同的方式`AdminResetUserPassword`向用户发送密码重置代码。`ForgotPassword`

### 配置密码重置和恢复
<a name="user-pool-password-reset-and-recovery-configure"></a>

Amazon Cognito 会根据您在控制台中创建用户池时选择的必需属性和登录选项自动选择您的账户恢复选项。您可以修改这些默认设置。

用户首选 MFA 方法会影响他们可用于恢复密码的方法。首选 MFA 方式为电子邮件的用户无法通过电子邮件接收密码重置代码。首选 MFA 方式为短信的用户无法通过短信接收密码重置代码。

当用户不符合条件，无法使用首选密码重置方法时，您的[密码恢复](#user-pool-password-reset-and-recovery)设置必须提供替代选项。例如，您的恢复机制可能将电子邮件列为第一优先选项，而电子邮件 MFA 可能是您的用户池中的一个选项。在这种情况下，添加短信消息账户恢复作为第二个选项，或者使用管理 API 操作为这些用户重置密码。

对于没有有效恢复方式的用户发起的密码重置请求，Amazon Cognito 会返回 `InvalidParameterException` 错误响应。

**注意**  
用户无法在同一电子邮件地址或电话号码上接收 MFA 验证码和密码重置验证码。如果他们使用电子邮件中的一次性密码 (OTPs) 进行 MFA，则必须使用 SMS 消息进行账户恢复。如果他们使用 OTPs 来自短信的 MFA，则必须使用电子邮件进行账户恢复。在具有 MFA 的用户池中，如果用户有电子邮件地址的属性但没有电话号码，或者有电话号码但没有电子邮件地址，则他们可能无法完成自助密码恢复。  
要防止用户无法在使用此配置的用户池中重置密码的情况，请设置 `email` 和 `phone_number` [属性（按需设置）](user-pool-settings-attributes.md)。或者，您可以设置相关流程，在用户注册时或管理员创建用户配置文件时，始终收集并设置这些属性。当用户同时具备这两个属性时，Amazon Cognito 会自动将密码重置验证码发送到*不是*用户 MFA 因素的目的地。

以下过程在用户池中配置自助账户恢复。

------
#### [ Configure self-service password reset (API/SDK) ]

该`AccountRecoverySetting`参数是用户池参数，用于设置用户在 [ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)API 请求中或选择 “**忘记密码？” 时可以用来恢复密码**的方法。 在托管登录中。 `ForgotPassword`向经过验证的电子邮件或经过验证的电话号码发送恢复码。恢复代码的有效期为 1 小时。当您为用户池指定 [AccountRecoverySetting](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AccountRecoverySettingType.html) 时，Amazon Cognito 会根据您设置的优先级选择代码发送目标。

当您定义 `AccountRecoverySetting` 并且用户配置了 SMS MFA 时，不能将 SMS 用作账户恢复机制。此设置的优先级已确定，其中 `1` 为最高优先级。Amazon Cognito 仅向指定方法之一发送验证。以下示例 `AccountRecoverySetting` 将电子邮件地址设置为账户恢复代码的主要目标，如果用户没有电子邮件地址属性，则回退到短信。

```
"AccountRecoverySetting": { 
   "RecoveryMechanisms": [ 
      { 
         "Name": "verified_email",
         "Priority": 1
      },
      { 
         "Name": "verified_phone_number",
         "Priority": 2
      }
   ]
}
```

值 `admin_only` 会关闭自助账户恢复，而是要求用户联系他们的管理员进行密码重置。您不能将 `admin_only` 与任何其他账户恢复机制一起使用。以下

```
"AccountRecoverySetting": { 
   "RecoveryMechanisms": [ 
      { 
         "Name": "admin_only",
         "Priority": 1
      }
   ]
}
```

如果未指定 `AccountRecoverySetting`，Amazon Cognito 会先将恢复码发送到经过验证的电话号码，如果用户没有电话号码属性，则会发送到经过验证的电子邮件地址。

有关 `AccountRecoverySetting` 的更多信息，请参阅 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)和 [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)。

------
#### [ Configure self-service password reset (console) ]

从用户池的**登录**菜单配置账户恢复和密码重置选项。

**设置用户账户恢复**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**登录**菜单。找到**用户账户恢复**，然后选择**编辑**。

1. 要允许用户重置自己的密码，请选择**启用自助账户恢复**。

1. 为用户池发送给用户的密码恢复代码配置发送方式。在**用户账户恢复消息的发送方法**下，选择一个可用选项。最佳做法是，选择具有辅助消息发送方法的选项，例如**如果电子邮件可用，则使用电子邮件发送，否则使用短信**。借助辅助发送方法，Amazon Cognito 在向用户发送代码时，可以要求用户使用与 MFA 不同的媒介来重置密码。

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

------

### 忘记密码行为
<a name="forgot-password"></a>

在给定时间内，作为忘记密码和操作的一部分，我们允许用户尝试请求或输入密码重置码 5 到 20 次。 confirm-forgot-password确切的值取决于与请求关联的风险参数。请注意，这种行为可能会发生变化。

## 添加用户池密码要求
<a name="user-pool-settings-policies"></a>

作为用户池的最佳安全实践，应该设置强大、复杂的密码。特别是在对互联网开放的应用程序中，弱密码会将用户的凭证暴露给会猜测密码并尝试访问您的数据的系统。密码越复杂，就越难猜出。Amazon Cognito 为注重安全的管理员提供了其他工具 ACLs，例如[威胁防护](cognito-user-pool-settings-threat-protection.md#cognito-user-pool-settings-threat-protection.title)和[AWS WAF 网络](user-pool-waf.md#user-pool-waf.title)，但是您的密码策略是用户目录安全的核心要素。

Amazon Cognito 用户池中本地用户的密码不会自动过期。妥善的做法是在外部系统中记录用户密码重置的时间、日期和元数据。通过记录密码使用期限的外部日志，您的应用程序或 Lambda 触发器可以查找用户的密码使用期限，并在给定时间后要求重置。

您可以将用户池配置为要求密码具有最低复杂性，以符合您的安全标准。复杂密码的最小长度为至少八个字符。还必须包括大写字母、数字和特殊字符的组合。

通过基础版或增值版功能计划，您还可以设置密码重用策略。您可以阻止用户将其新密码重置为与其当前密码相同，也不得与最多 23 个以前的其他密码中的任何一个相同，即用户不能将新密码设置为这 24 个密码中的任何一个。

**设置用户池密码策略**

1. 创建一个用户池并导航到**配置安全要求**步骤，或访问现有用户池并导航到**身份验证方法**菜单。

1. 导航到**密码策略**。

1. 选择**密码策略模式**。**Cognito 默认**使用推荐的最低设置来配置您的用户池。您也可以选择一项**自定义**密码策略。

1. 设置**密码最小长度**。所有用户都必须使用长度大于或等于这个值的密码进行注册或创建。您可以将这个最小值设置为 99，但用户可以设置最长 256 个字符的密码。

1. 在**密码要求**下配置密码的复杂性规则。选择您希望在每个用户的密码中至少包含一个的字符类型（数字、特殊字符、大写字母和小写字母）。

   可以要求密码中至少包含以下字符之一：在 Amazon Cognito 确认密码中包含所需的最少字符后，用户的密码可以包含任何类型的额外字符，但不得超过最大密码长度。
   + 大写和小写[基本拉丁](https://en.wikipedia.org/wiki/ISO_basic_Latin_alphabet)字母
   + 数字
   + 以下特殊字符。

     ```
     ^ $ * . [ ] { } ( ) ? " ! @ # % & / \ , > < ' : ; | _ ~ ` = + - 
     ```
   + 非前导、非结尾的空格字符。

1. 为**管理员设置的临时密码到期时间**设置一个值。超过此期限，您通过 Amazon Cognito 控制台或 `AdminCreateUser` 创建的新用户将无法登录和设置新密码。使用临时密码登录后，他们的用户账户永远不会过期。要在 Amazon Cognito 用户池 API 中更新密码时长，请在您的[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求[TemporaryPasswordValidityDays ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_PasswordPolicyType.html#CognitoUserPools-Type-PasswordPolicyType-TemporaryPasswordValidityDays)中为设置一个值。

1. 为**防止使用之前的密码**设置一个值（如果有）。要使用此功能，请在用户池中选择基础版或增值版[功能计划](cognito-sign-in-feature-plans.md)。此参数的值是在用户重置密码时阻止新密码匹配的先前密码数。

要重置已过期用户账户的访问权限，请执行以下操作之一：
+ 发送新的临时密码并使用已`MessageAction`设置为的 [AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserPassword.html)API 请求重置过期时间`RESEND`。
+ 删除用户配置文件并创建新的用户配置文件。
+ 在 [AdminResetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminResetUserPassword.html)API 请求中生成新的确认码。

# 将用户导入一个用户池
<a name="cognito-user-pools-import-users"></a>

您可以使用以下两种方式将用户从现有用户目录或用户数据库导入或迁移到 Amazon Cognito 用户池中。您可以利用用户迁移 Lambda 触发器，在用户首次使用 Amazon Cognito 登录时迁移用户。借助这种方法，用户可以继续使用其现有的密码，不必在迁移到用户池后重置密码。或者，您可以上传 CSV 文件 (包含所有用户的用户配置文件属性)，批量迁移用户。以下各部分分别介绍了这两种方法。

**更多资源**
+ [将用户迁移到 Amazon Cognito 用户池的方法](https://aws.amazon.com/blogs/security/approaches-for-migrating-users-to-amazon-cognito-user-pools/)
+ [AWS re: inforce 2023-迁移到亚马逊 Cognito](https://www.youtube.com/watch?v=OkDj9uXWwCc)

**Topics**
+ [利用用户迁移 Lambda 触发器导入用户](cognito-user-pools-import-using-lambda.md)
+ [通过 CSV 文件将用户导入用户池中](cognito-user-pools-using-import-tool.md)

# 利用用户迁移 Lambda 触发器导入用户
<a name="cognito-user-pools-import-using-lambda"></a>

使用这种方法，当用户首次登录您的应用程序或请求重置密码时，您可以将用户从现有用户目录无缝迁移到用户池。向您的用户池添加一个 [迁移用户 Lambda 触发器](user-pool-lambda-migrate-user.md) 函数，它会接收有关尝试登录的用户的元数据，并从外部身份源返回用户配置文件信息。有关此 Lambda 触发器的详细信息以及示例代码（包括请求和响应参数），请参阅[迁移用户 Lambda 触发器参数](user-pool-lambda-migrate-user.md#cognito-user-pools-lambda-trigger-syntax-user-migration)。

在开始迁移用户之前，请在您的 AWS 账户中创建一个用户迁移 Lambda 函数，并将该 Lambda 函数设置为您的用户池中的用户迁移触发器。向您的 Lambda 函数添加授权策略，该策略仅允许 Amazon Cognito 服务账户主体 `cognito-idp.amazonaws.com` 调用该 Lambda 函数，并且只能在您自己的用户池的上下文中进行。有关更多信息，请参阅[对 AWS Lambda 使用基于资源的策略（Lambda 函数策略）](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html)。

**登录流程**

1. 用户打开您的应用程序并使用 Amazon Cognito 用户池 API 或通过托管登录进行登录。有关如何简化使用 Amazon Cogn APIs ito 登录的更多信息，请参阅。[将 Amazon Cognito 身份验证和授权与 Web 和移动应用程序集成](cognito-integrate-apps.md)

1. 您的应用程序将用户名和密码发送至 Amazon Cognito。如果您的应用程序具有使用 AWS SDK 构建的自定义登录界面，则您的应用程序必须使用[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)或[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)与`USER_PASSWORD_AUTH`或`ADMIN_USER_PASSWORD_AUTH`流程。当您的应用使用其中一个流程时，开发工具包会将密码发送到服务器。
**注意**  
在添加用户迁移触发器之前，请在您的应用程序客户端的设置中激活 `USER_PASSWORD_AUTH` 或 `ADMIN_USER_PASSWORD_AUTH` 流程。您必须使用这些流程而不是默认 `USER_SRP_AUTH` 流程。Amazon Cognito 必须向您的 Lambda 函数发送密码，以便它可以验证您的用户在另一个目录中的身份验证。SRP 会在您的 Lambda 函数中隐藏您用户的密码。

1. Amazon Cognito 检查提交的用户名是否与用户池中的用户名或别名匹配。您可以将用户的电子邮件地址、电话号码或首选用户名设置为用户池中的别名。如果用户不存在，Amazon Cognito 会将参数（包括用户名和密码）发送到您的 [迁移用户 Lambda 触发器](user-pool-lambda-migrate-user.md) 函数。

1. 您的 [迁移用户 Lambda 触发器](user-pool-lambda-migrate-user.md) 函数使用您的现有用户目录或用户数据库检查用户，或验证用户身份。该函数返回 Amazon Cognito 存储在用户池的用户配置文件中的用户属性。仅当提交的用户名与别名属性匹配时，您才能返回 `username` 参数。如果您希望用户继续使用其现有密码，您的函数将在 Lambda 响应中将属性 `finalUserStatus` 设置为 `CONFIRMED`。您的应用程序必须返回 [迁移用户 Lambda 触发器参数](user-pool-lambda-migrate-user.md#cognito-user-pools-lambda-trigger-syntax-user-migration) 中显示的所有 `"response"` 参数。
**重要**  
不要在您的用户迁移 Lambda 代码中记录整个请求事件对象。此请求事件对象包括用户的密码。如果您不对日志进行消毒，则密码会显示在 CloudWatch 日志中。

1. Amazon Cognito 在您的用户池中创建用户配置文件，并将令牌返回您的应用程序客户端。

1. 您的应用程序执行令牌接收，接受用户身份验证，然后继续处理请求的内容。

迁移用户后，请使用 `USER_SRP_AUTH` 进行登录。安全远程密码 (SRP) 协议不会通过网络发送密码，并为您在迁移期间使用的 `USER_PASSWORD_AUTH` 流程提供安全优势。

如果迁移期间出现错误（包括客户端设备或网络问题），您的应用程序会从 Amazon Cognito 用户池 API 接收错误响应。发生这种情况时，Amazon Cognito 可能会也可能不会在您的用户池中创建用户账户。然后，用户应尝试再次登录。如果登录反复失败，请尝试在您的应用程序中使用忘记密码流程重置用户密码。

忘记密码流程还会使用 `UserMigration_ForgotPassword` 事件源调用您的 [迁移用户 Lambda 触发器](user-pool-lambda-migrate-user.md) 函数。由于用户在请求密码重置时没有提交密码，因此 Amazon Cognito 在发送到您的 Lambda 函数的事件中不包含密码。您的函数只能在现有用户目录中查找用户并返回属性，以添加到用户池中的用户配置文件中。在您的函数完成其调用并将其响应返回给 Amazon Cognito 后，您的用户池将通过电子邮件或 SMS 发送密码重置代码。在您的应用程序中，提示您的用户输入确认码和新密码，然后[ConfirmForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html)通过 API 请求将该信息发送给 Amazon Cognito。您还可以在托管登录中使用内置的忘记密码流程页面。

**其他资源**
+ [将用户迁移到 Amazon Cognito 用户池的方法](https://aws.amazon.com/blogs/security/approaches-for-migrating-users-to-amazon-cognito-user-pools/)

# 通过 CSV 文件将用户导入用户池中
<a name="cognito-user-pools-using-import-tool"></a>

如果您有外部身份存储，并且有时间为新的本地用户准备用户池，那么在迁移到 Amazon Cognito 用户池，选择从逗号分隔值（CSV）文件批量导入用户既省时省力，又可降低成本。CSV 文件导入是先下载和填入模板文件，然后在导入任务中将该文件移交给用户池的过程。您可以使用 CSV 导入来快速创建测试用户。您还可以通过编程的方式，使用读取 API 请求从外部身份存储中获取数据，然后解析这些数据的详细信息和属性，再将它们写入到文件中。

导入过程会设置所有用户属性的值，不过 **password** 除外。不支持导入密码，因为安全妥善做法要求密码不能为纯文本，而我们不支持导入哈希。这意味着，用户必须在首次登录时更改密码。使用此方法导入用户时，用户处于 `RESET_REQUIRED` 状态。

从 CSV 导入用户最省力的方法是在用户池中激活[无密码登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)。借助电子邮件地址和电话号码属性以及正确的用户池配置，用户可以在导入任务完成后立即使用电子邮件或短信一次性密码 (OTPs) 登录。有关更多信息，请参阅 [要求导入的用户重置密码](#cognito-user-pools-using-import-tool-password-reset)。

您也可以使用 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserPassword.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserPassword.html) API 请求，将 `Permanent` 参数设置为 `true` 来设置用户的密码。CSV 导入不会计入用户池中按月计费的活跃用户 (MAUs)。但是，确实会生成密码重置操作。 MAUs要在导入大量可能不会立即处于活动状态的带密码用户时控制成本，请将您的应用程序设置为在用户登录并收到 `RESET_REQUIRED` 质询时提示他们输入新密码。

**注意**  
每个用户的创建日期就是将该用户导入用户池中的日期。创建日期不是导入的属性之一。

**创建用户导入任务的步骤**

1. 在 AWS Identity and Access Management (IAM) 控制台中创建 Amazon L CloudWatch ogs 角色。

1. 创建用户导入 .csv 文件。

1. 创建并运行用户导入任务。

1. 上传用户导入 .csv 文件。

1. 启动并运行用户导入任务。

1.  CloudWatch 用于查看事件日志。

1. 要求导入的用户重置密码。

**更多资源**
+ [Cognito 用户配置文件导出参考架构](https://aws.amazon.com/solutions/implementations/cognito-user-profiles-export-reference-architecture/)，用于在用户池之间导出用户账户

**Topics**
+ [创建日 CloudWatch 志 IAM 角色](#cognito-user-pools-using-import-tool-cli-cloudwatch-iam-role)
+ [创建用户导入 CSV 文件](#cognito-user-pools-using-import-tool-csv-header)
+ [创建并运行 Amazon Cognito 用户池导入任务](#cognito-user-pools-creating-import-job)
+ [在 CloudWatch 控制台中查看用户池导入结果](#cognito-user-pools-using-import-tool-cloudwatch)
+ [要求导入的用户重置密码](#cognito-user-pools-using-import-tool-password-reset)

## 创建日 CloudWatch 志 IAM 角色
<a name="cognito-user-pools-using-import-tool-cli-cloudwatch-iam-role"></a>

如果您使用的是 Amazon Cognito CLI 或 API，则需要创建一个 CloudWatch IAM 角色。以下过程介绍如何创建一个 IAM 角色，Amazon Cognito 可以使用该角色将导入任务的结果写入日志。 CloudWatch 

**注意**  
在 Amazon Cognito 控制台中创建导入作业时，您可以同时创建 IAM 角色。当您选择 **Create a new IAM role**（创建新 IAM 角色）时，Amazon Cognito 会自动对该角色应用相应的信任策略和 IAM policy。

**创建用于用户池导入的 CloudWatch Logs IAM 角色 (AWS CLI，API)**

1. 登录 AWS 管理控制台 并打开 IAM 控制台，网址为[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)。

1. 为创建新的 IAM 角色 AWS 服务。有关详细说明，请参阅《AWS Identity and Access Management 用户指南》**中的[为 AWS 服务创建一个角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html#roles-creatingrole-service-console)。

   1. 当您为 **Trusted entity type**（可信实体类型）选择 **Use case**（使用案例）时，请选择任意服务。Amazon Cognito 目前未在服务使用案例中列出。

   1. 在 **Add permissions**（添加权限）屏幕中，选择 **Create policy**（创建策略）并插入以下策略声明。例如，*REGION* AWS 区域 替换为用户池中的`us-east-1`。例如*ACCOUNT*，用您的 AWS 账户 身份证替换`111122223333`。

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

****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "logs:CreateLogGroup",
                      "logs:CreateLogStream",
                      "logs:DescribeLogStreams",
                      "logs:PutLogEvents"
                  ],
                  "Resource": [
                      "arn:aws:logs:us-east-1:111122223333:log-group:/aws/cognito/*"
                  ]
              }
          ]
      }
      ```

------

1. 由于您在创建角色时没有选择 Amazon Cognito 作为可信实体，因此您现在必须手动编辑该角色的信任关系。在 IAM 控制台的导航窗格中选择 **Roles**（角色），然后选择您创建的新角色。

1. 选择 **Trust relationships（信任关系）**选项卡。

1. 选择**编辑信任策略**。

1. 将以下策略声明粘贴到 **Edit trust policy**（编辑信任策略）中，替换任何现有文本：

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

****  

   ```
   {
           "Version":"2012-10-17",		 	 	 
           "Statement": [
               {
                   "Effect": "Allow",
                   "Principal": {
                       "Service": "cognito-idp.amazonaws.com"
                   },
                   "Action": "sts:AssumeRole"
               }
           ]
       }
   ```

------

1. 选择**更新策略**。

1. 记下 角色 ARN。您在创建导入作业时需要此 ARN。

## 创建用户导入 CSV 文件
<a name="cognito-user-pools-using-import-tool-csv-header"></a>

您必须先创建逗号分隔值（CSV，Comma-Separated Value）文件，在其中包含要导入的用户及其属性，然后才能将现有用户导入用户池中。从用户池中，您可以检索其标头反映了您的用户池的属性架构的用户导入文件。然后，您可以插入符合 [设置 CSV 文件的格式](#cognito-user-pools-using-import-tool-formatting-csv-file) 中的格式要求的用户信息。

### 下载 CSV 文件标头（控制台）
<a name="cognito-user-pools-using-import-tool-downloading-csv-header-console"></a>

使用以下步骤下载 CSV 标头文件。

**下载 CSV 文件标头**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。系统可能会提示您输入 AWS 凭证。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**用户**菜单。

1. 在 **Import users**（导入用户）部分中，选择 **Create an import job**（创建导入作业）。

1. 在 **Upload CSV**（上传 CSV）下，选择 *template.csv* 链接并下载 CSV 文件。

### 下载 CSV 文件标头（AWS CLI）
<a name="cognito-user-pools-using-import-tool-downloading-csv-header-using-cli"></a>

要获取正确的标题列表，请从**用户**菜单中的**导入用户**下选择**创建导入作业**。在随后的对话框中，选择 `template.csv` 链接以下载包含您的用户池属性的模板文件。

您也可以运行以下 CLI 命令，其中*USER\$1POOL\$1ID*是要将用户导入到的用户池的用户池标识符：

```
aws cognito-idp get-csv-header --user-pool-id "USER_POOL_ID"
```

示例响应:

```
{
    "CSVHeader": [
        "name",
        "given_name",
        "family_name",
        "middle_name",
        "nickname",
        "preferred_username",
        "profile",
        "picture",
        "website",
        "email",
        "email_verified",
        "gender",
        "birthdate",
        "zoneinfo",
        "locale",
        "phone_number",
        "phone_number_verified",
        "address",
        "updated_at",
        "cognito:mfa_enabled",
        "cognito:username"
    ],
    "UserPoolId": "USER_POOL_ID"
}
```

### 设置 CSV 文件的格式
<a name="cognito-user-pools-using-import-tool-formatting-csv-file"></a>

 下载的用户导入 CSV 标头文件类似于以下字符串。它还包括您已添加到用户池的所有自定义属性。

```
cognito:username,name,given_name,family_name,middle_name,nickname,preferred_username,profile,picture,website,email,email_verified,gender,birthdate,zoneinfo,locale,phone_number,phone_number_verified,address,updated_at,cognito:mfa_enabled
```

编辑 CSV 文件，以使文件包含此标头和用户的属性值，并根据以下规则设置格式：

**注意**  
有关属性值（如电话号码的正确格式）的更多信息，请参阅[使用用户属性](user-pool-settings-attributes.md)。
+ 文件的第一行是已下载的包含用户属性名称的标头行。
+ CSV 文件中列的顺序不重要。
+ 第一行之后的每一行都包含用户的属性值。
+ 标头中的所有列都必须存在，但您不需要在每一列中提供值。
+ 以下属性为必需属性：
  + **cognito:username**
  + **email\$1verified** 或 **phone\$1number\$1verified**
    + 每个用户至少有一个自动验证属性必须为 `true`。自动验证的属性是新用户加入您的用户池时，Amazon Cognito 自动向其发送验证码的电子邮件地址或电话号码。
    + 用户池必须至少有一个自动验证属性，要么是 **email\$1verified**，要么是 **phone\$1number\$1verified**。如果用户池没有自动验证属性，则导入任务不会启动。
    + 如果用户池只有一个自动验证属性，则该属性必须针对每个用户进行验证。例如，如果用户池只有 **phone\$1number** 为自动验证属性，则每个用户的 **phone\$1number\$1verified** 值都必须为 `true`。
**注意**  
对于重置其密码的用户，用户必须拥有经过验证的电子邮件或电话号码。Amazon Cognito 将包含重置密码代码的消息发送到 CSV 文件中指定的电子邮件或电话号码。如果将消息发送到电话号码，则通过 SMS 消息发送。有关更多信息，请参阅 [在注册时验证联系人信息](signing-up-users-in-your-app.md#allowing-users-to-sign-up-and-confirm-themselves)。
  + **email**（如果 **email\$1verified** 为 `true`）
  + **phone\$1number**（如果 **phone\$1number\$1verified** 为 `true`）
  + 创建用户池时标记为必需的所有属性
+ 字符串式的属性值*不* 应该用引号括起来。
+ 如果属性值包含逗号，则您必须在逗号前使用反斜杠 (\$1)。这是因为 CSV 文件中的字段使用逗号分隔。
+ CSV 文件内容应采用不含字节顺序标记的 UTF-8 格式。
+ **cognito:username** 字段是必填项，并且在用户池中必须是唯一的。它可以是任何 Unicode 字符串。但是，它不能包含空格或制表符。
+ **出生日期**值（如果存在）必须采用以下格式**mm/dd/yyyy**。也就是说，如果生日日期为 1985 年 2 月 1 日，则必须编码为 **02/01/1985**。
+ **cognito:mfa\$1enabled** 字段必须符合用户池的 MFA 要求。如果您已将用户池设置为需要进行多重身份验证（MFA），则所有用户的此字段都必须为 `true` 或为空。如果您已将 MFA 设置为关闭，则所有用户的此字段都必须为 `false` 或为空。空值将导入的用户启用 MFA 的状态设置为用户池所需的状态。无论是否设置 `cognito:mfa_enabled` 值，您都可以在没有有效 MFA 因素的情况下将用户导入到要求 MFA 的用户池中。处于此状态的用户已激活 MFA，但在配置电子邮件属性、电话号码属性或 TOTP 之前无法登录，并且该配置是用户池中的有效 MFA 因素。
+ 最大长度为 16000 个字符。
+ CSV 文件的最大大小为 100MB。
+ 文件中的最大行（用户）数为 5,00000。此最大值不包括标题行。
+ **updated\$1at** 字段值应为纪元时间（用秒表示），例如：**1471453471**。
+ 属性值中的所有前导空格或尾部空格均应去除。

以下列表是没有自定义属性的用户池的 CSV 导入文件示例。您的用户池架构可能与此示例有所不同。在这种情况下，您必须在从用户池下载的 CSV 模板中提供测试值。

```
cognito:username,name,given_name,family_name,middle_name,nickname,preferred_username,profile,picture,website,email,email_verified,gender,birthdate,zoneinfo,locale,phone_number,phone_number_verified,address,updated_at,cognito:mfa_enabled
John,,John,Doe,,,,,,,johndoe@example.com,TRUE,,02/01/1985,,,+12345550100,TRUE,123 Any Street,,FALSE
Jane,,Jane,Roe,,,,,,,janeroe@example.com,TRUE,,01/01/1985,,,+12345550199,TRUE,100 Main Street,,FALSE
```

## 创建并运行 Amazon Cognito 用户池导入任务
<a name="cognito-user-pools-creating-import-job"></a>

本节介绍如何使用 Amazon Cognito 控制台和 AWS Command Line Interface ()AWS CLI创建和运行用户池导入任务。

**Topics**
+ [从 CSV 文件导入用户（控制台）](#cognito-user-pools-using-import-tool-console)
+ [导入用户（AWS CLI）](#cognito-user-pools-using-import-tool-cli)

### 从 CSV 文件导入用户（控制台）
<a name="cognito-user-pools-using-import-tool-console"></a>

以下过程介绍了如何从 CSV 文件导入用户。

**从 CSV 文件导入用户（控制台）**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。系统可能会提示您输入 AWS 凭证。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**用户**菜单。

1. 在 **Import users**（导入用户）部分中，选择 **Create an import job**（创建导入作业）。

1. 在 **Create import job**（创建导入作业）页面上，输入 **Job name**（作业名称）。

1. 选择 **Create a new IAM role**（创建新的 IAM 角色）或者 **Use an existing IAM role**（使用现有 IAM 角色）。

   1. 如果您选择 **Create a new IAM role**（创建新的 IAM 角色），请输入新角色的名称。Amazon Cognito 将自动创建具有正确权限和信任关系的角色。创建导入作业的 IAM 主体必须具有创建 IAM 角色的权限。

   1. 如果您选择 **Use an existing IAM role**（使用现有 IAM 角色），请从 **IAM role selection**（IAM 角色选择）下的列表中选择一个角色。此角色必须具有 [创建日 CloudWatch 志 IAM 角色](#cognito-user-pools-using-import-tool-cli-cloudwatch-iam-role) 中所述的权限和信任策略。

1. 在**上传 CSV** 下，选择**选择文件**并附加准备好的 CSV 文件。

1. 选择 **Create job**（创建作业）可提交作业，但稍后再启动。选择 **Create and start job**（创建并启动作业）可提交您的作业并立即启动。

1. 如果您创建了作业但未启动作业，则可以稍后再启动。在**用户**菜单的**导入用户**下，选择导入作业，然后选择**开始**。您也可以从 AWS SDK 提交 [StartUserImportJob](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_StartUserImportJob.html)API 请求。

1. 在**用户**菜单的**导入用户**下，监控用户导入作业的进度。如果您的作业不成功，则可以选择 **Status**（状态）值。要了解更多详细信息，请选择**查看 CloudWatch 日志以了解更多详细信息**，然后在 CloudWatch 日志控制台中查看所有问题。

### 导入用户（AWS CLI）
<a name="cognito-user-pools-using-import-tool-cli"></a>

以下 CLI 命令可用于将用户导入到用户池：
+ `create-user-import-job`
+ `get-csv-header`
+ `describe-user-import-job`
+ `list-user-import-jobs`
+ `start-user-import-job`
+ `stop-user-import-job`

要获取这些命令的命令行选项列表，请使用 `help` 命令行选项。例如：

```
aws cognito-idp get-csv-header help
```

#### 创建用户导入任务
<a name="cognito-user-pools-using-import-tool-cli-creating-user-import-job"></a>

创建 CSV 文件后，通过运行以下 CLI 命令创建用户导入任务，其中*JOB\$1NAME*是您为任务选择的名称，*USER\$1POOL\$1ID*是要向其中添加新用户的用户池的用户池 ID，*ROLE\$1ARN*也是您在中收到的角色 ARN：[创建日 CloudWatch 志 IAM 角色](#cognito-user-pools-using-import-tool-cli-cloudwatch-iam-role)

```
aws cognito-idp create-user-import-job --job-name "JOB_NAME" --user-pool-id "USER_POOL_ID" --cloud-watch-logs-role-arn "ROLE_ARN"
```

响应中*PRE\$1SIGNED\$1URL*返回的有效期为 15 分钟。在此之后，它将过期，而您必须创建新的用户导入任务以获取新的 URL。

**Example 响应：**  

```
{
    "UserImportJob": {
        "Status": "Created",
        "SkippedUsers": 0,
        "UserPoolId": "USER_POOL_ID",
        "ImportedUsers": 0,
        "JobName": "JOB_NAME",
        "JobId": "JOB_ID",
        "PreSignedUrl": "PRE_SIGNED_URL",
        "CloudWatchLogsRoleArn": "ROLE_ARN",
        "FailedUsers": 0,
        "CreationDate": 1470957431.965
    }
}
```

#### 用户导入任务的状态值
<a name="cognito-user-pools-using-import-tool-cli-status-values-for-user-import-job"></a>

在对用户导入命令的响应中，您将看到以下 `Status` 值当中的其中一个值：
+ `Created` – 任务已创建但未启动。
+ `Pending` – 转换状态。您已启动任务，但它尚未开始导入用户。
+ `InProgress` – 任务已启动，正在导入用户。
+ `Stopping` – 您已停止任务，但任务尚未停止导入用户。
+ `Stopped` – 您已停止任务，且任务已停止导入用户。
+ `Succeeded` – 任务已成功完成。
+ `Failed` – 任务因错误而停止。
+ `Expired` – 您创建了一个任务，但未在 24-48 小时内启动任务。与任务关联的所有数据已删除，且任务无法启动。

#### 上传 CSV 文件
<a name="cognito-user-pools-using-import-tool-cli-uploading-csv-file"></a>

使用以下 `curl` 命令将包含用户数据的 CSV 文件上传到您从 `create-user-import-job` 命令的响应中获取的预签名 URL。

```
curl -v -T "PATH_TO_CSV_FILE" -H "x-amz-server-side-encryption:aws:kms" "PRE_SIGNED_URL"
```

在此命令的输出中，查找 `"We are completely uploaded and fine"` 这一短语。此短语表示文件已成功上传。运行导入作业后，您的用户池不会将信息保留在导入文件中。在它们完成或过期后，Amazon Cognito 会删除上传的 CSV 文件。

#### 描述用户导入任务
<a name="cognito-user-pools-using-import-tool-cli-describing-user-import-job"></a>

要获取用户导入任务的描述，请使用以下命令，其中*USER\$1POOL\$1ID*是您的用户池 ID，*JOB\$1ID*是您创建用户导入任务时返回的任务 ID。

```
aws cognito-idp describe-user-import-job --user-pool-id "USER_POOL_ID" --job-id "JOB_ID"
```

**Example 示例响应:**  

```
{
    "UserImportJob": {
        "Status": "Created",
        "SkippedUsers": 0,
        "UserPoolId": "USER_POOL_ID",
        "ImportedUsers": 0,
        "JobName": "JOB_NAME",
        "JobId": "JOB_ID",
        "PreSignedUrl": "PRE_SIGNED_URL",
        "CloudWatchLogsRoleArn":"ROLE_ARN",
        "FailedUsers": 0,
        "CreationDate": 1470957431.965
    }
}
```

在前面的示例输出中，*PRE\$1SIGNED\$1URL*是您将 CSV 文件上传到的网址。*ROLE\$1ARN*是您在创建角色时收到的 CloudWatch 日志角色 ARN。

#### 列出用户导入任务
<a name="cognito-user-pools-using-import-tool-cli-listing-user-import-jobs"></a>

要列出用户导入任务，请使用以下命令：

```
aws cognito-idp list-user-import-jobs --user-pool-id "USER_POOL_ID" --max-results 2
```

**Example 示例响应:**  

```
{
    "UserImportJobs": [
        {
            "Status": "Created",
            "SkippedUsers": 0,
            "UserPoolId": "USER_POOL_ID",
            "ImportedUsers": 0,
            "JobName": "JOB_NAME",
            "JobId": "JOB_ID",
            "PreSignedUrl":"PRE_SIGNED_URL",
            "CloudWatchLogsRoleArn":"ROLE_ARN",
            "FailedUsers": 0,
            "CreationDate": 1470957431.965
        },
        {
            "CompletionDate": 1470954227.701,
            "StartDate": 1470954226.086,
            "Status": "Failed",
            "UserPoolId": "USER_POOL_ID",
            "ImportedUsers": 0,
            "SkippedUsers": 0,
            "JobName": "JOB_NAME",
            "CompletionMessage": "Too many users have failed or been skipped during the import.",
            "JobId": "JOB_ID",
            "PreSignedUrl":"PRE_SIGNED_URL",
            "CloudWatchLogsRoleArn":"ROLE_ARN",
            "FailedUsers": 5,
            "CreationDate": 1470953929.313
        }
    ],
    "PaginationToken": "PAGINATION_TOKEN"
}
```

任务按创建日期 (从近到远) 排列。第二个任务之后的*PAGINATION\$1TOKEN*字符串表示此列表命令还有其他结果。要列出更多结果，请使用 `--pagination-token` 选项，如下所示：

```
aws cognito-idp list-user-import-jobs --user-pool-id "USER_POOL_ID" --max-results 10 --pagination-token "PAGINATION_TOKEN"
```

#### 启动用户导入任务
<a name="cognito-user-pools-using-import-tool-cli-starting-user-import-job"></a>

要启动用户导入任务，请使用以下命令：

```
aws cognito-idp start-user-import-job --user-pool-id "USER_POOL_ID" --job-id "JOB_ID"
```

每个账户每次只能有一个导入任务处于活动状态。

**Example 示例响应:**  

```
{
    "UserImportJob": {
        "Status": "Pending",
        "StartDate": 1470957851.483,
        "UserPoolId": "USER_POOL_ID",
        "ImportedUsers": 0,
        "SkippedUsers": 0,
        "JobName": "JOB_NAME",
        "JobId": "JOB_ID",
        "PreSignedUrl":"PRE_SIGNED_URL",
        "CloudWatchLogsRoleArn": "ROLE_ARN",
        "FailedUsers": 0,
        "CreationDate": 1470957431.965
    }
}
```

#### 停止用户导入任务
<a name="cognito-user-pools-using-import-tool-cli-stopping-user-import-job"></a>

要停止正在进行的用户导入任务，请使用以下命令。停止任务后，无法重新启动该任务。

```
aws cognito-idp stop-user-import-job --user-pool-id "USER_POOL_ID" --job-id "JOB_ID"
```

**Example 示例响应:**  

```
{
    "UserImportJob": {
        "CompletionDate": 1470958050.571,
        "StartDate": 1470958047.797,
        "Status": "Stopped",
        "UserPoolId": "USER_POOL_ID",
        "ImportedUsers": 0,
        "SkippedUsers": 0,
        "JobName": "JOB_NAME",
        "CompletionMessage": "The Import Job was stopped by the developer.",
        "JobId": "JOB_ID",
        "PreSignedUrl":"PRE_SIGNED_URL",
        "CloudWatchLogsRoleArn": "ROLE_ARN",
        "FailedUsers": 0,
        "CreationDate": 1470957972.387
    }
}
```

## 在 CloudWatch 控制台中查看用户池导入结果
<a name="cognito-user-pools-using-import-tool-cloudwatch"></a>

您可以在 Amazon CloudWatch 控制台中查看导入任务的结果。

**Topics**
+ [查看结果](#cognito-user-pools-using-import-tool-viewing-the-results)
+ [解析结果](#cognito-user-pools-using-import-tool-interpreting-the-results)

### 查看结果
<a name="cognito-user-pools-using-import-tool-viewing-the-results"></a>

以下步骤介绍了如何查看用户池导入结果。

**查看用户池导入结果的步骤**

1. 登录 AWS 管理控制台 并打开 CloudWatch 控制台，网址为[https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)。

1. 选择 **Logs (日志)**。

1. 为用户池导入任务选择日志组。日志组名称的形式为 `/aws/cognito/userpools/USER_POOL_ID/USER_POOL_NAME`。

1. 为刚运行的用户导入任务选择日志。日志名称的格式为*JOB\$1ID*/*JOB\$1NAME*。日志中的结果按行号引用用户。日志中不会写入用户数据。对于每个用户，都将出现类似于以下内容的行：
   + `[SUCCEEDED] Line Number 5956 - The import succeeded.`
   + `[SKIPPED] Line Number 5956 - The user already exists.`
   + `[FAILED] Line Number 5956 - The User Record does not set any of the auto verified attributes to true. (Example: email_verified to true).`

### 解析结果
<a name="cognito-user-pools-using-import-tool-interpreting-the-results"></a>

成功导入的用户的状态设置为 “PasswordReset”。

在以下情况下，将不会导入用户，但导入任务将继续：
+ 自动验证属性未设置为 `true`。
+ 用户数据与架构不匹配。
+ 由于内部错误，无法导入用户。

在以下情况下，导入任务将失败：
+ 无法担任 CloudWatch Amazon Logs 角色，该角色的访问策略不正确，或者已被删除。
+ 用户池已删除。
+ Amazon Cognito 无法解析 .csv 文件。

## 要求导入的用户重置密码
<a name="cognito-user-pools-using-import-tool-password-reset"></a>

如果您的用户池仅提供基于密码的登录，则在导入用户后，用户必须重置其密码。他们第一次登录时可以输入*任何*密码。Amazon Cognito 会在 API 响应您的应用程序的登录请求时提示他们输入新密码。

如果您的用户池具有无密码身份验证因素，Amazon Cognito 会默认采用适用于导入的用户的身份验证因素。他们不会被提示输入新密码，并且可以立即使用无密码电子邮件或短信 OTP 登录。您也可以提示用户设置密码，以便他们可以完成其他登录方法，例如用户名密码和通行密钥。以下条件适用于导入用户后的无密码登录。

1. 您必须使用与可用无密码登录因素相对应的属性导入用户。如果用户可以使用电子邮件地址登录，则必须导入 `email` 属性。如果是电话号码，则必须导入 `phone_number` 属性。如果两者兼而有之，则为任一属性导入一个值。

1. 通常，用户在必须重置其密码的 `RESET_REQUIRED` 状态下导入。如果用户在导入后能够使用无密码因素登录，则 Amazon Cognito 会将其状态设置为 `CONFIRMED`。

有关无密码身份验证的更多信息，包括如何设置无密码身份验证以及如何在应用程序中构造身份验证流程，请参阅[使用 Amazon Cognito 用户池进行身份验证](authentication.md)。

以下过程描述了您导入 CSV 文件后，处于 `RESET_REQUIRED` 状态的本地用户在自定义构建的登录机制中的用户体验。如果您的用户通过托管登录进行登录，请让他们选择**忘记密码？**选项，提供他们的电子邮件或短信中的代码，然后设置密码。

**要求导入的用户重置密码**

1. 在您的应用程序中，通过 `InitiateAuth` 使用随机密码以静默方式为当前用户尝试登录。

1. 启用了 `PreventUserExistenceErrors` 时，Amazon Cognito 返回 `NotAuthorizedException`。否则返回 `PasswordResetRequiredException`。

1. 您的应用程序发出 `ForgotPassword` API 请求并重置用户的密码。

   1. 应用程序在 `ForgotPassword` API 请求中提交用户名。

   1. Amazon Cognito 向经过验证的电子邮件或电话发送代码。目标取决于您在 CSV 文件中为 `email_verified` 和 `phone_number_verified` 提供的值。对 `ForgotPassword` 请求的响应指明了代码的目标。
**注意**  
必须将您的用户池配置为验证电子邮件或电话号码。有关更多信息，请参阅 [注册并确认用户账户](signing-up-users-in-your-app.md)。

   1. 您的应用程序向用户显示一条消息，以检查发送代码的位置，并提示用户输入代码和新密码。

   1. 用户在应用程序中输入代码和新密码。

   1. 应用程序在 `ConfirmForgotPassword` API 请求中提交代码和新密码。

   1. 您的应用程序重定向用户以进行登录。

# 使用用户属性
<a name="user-pool-settings-attributes"></a>

属性是各种条目的信息，用于帮助您标识单个用户，如名称、电子邮件和电话号码。新的用户池有一组默认*标准属性*。您也可以在中的用户池定义中添加自定义属性 AWS 管理控制台。本主题将详细介绍这些属性，并为您提供有关如何设置用户池的提示。

请勿将所有与用户相关的信息都应存储在属性中。例如，将频繁变化的用户数据（如使用情况统计数据或游戏分数）保存在单独的数据存储（如 Amazon Cognito Sync 或 Amazon DynamoDB）中。

在将输入的用户属性字符串值提交到用户池之前，请对其进行清理。分析提议的用户属性值的一种方法是使用 Lambda 触发器，例如[注册前](user-pool-lambda-pre-sign-up.md)。

**注意**  
一些文档和标准将属性称为*成员*。

**Topics**
+ [标准属性](#cognito-user-pools-standard-attributes)
+ [用户名和首选用户名](#user-pool-settings-usernames)
+ [自定义登录属性](#user-pool-settings-aliases)
+ [自定义属性](#user-pool-settings-custom-attributes)
+ [属性权限和范围](#user-pool-settings-attribute-permissions-and-scopes)

## 标准属性
<a name="cognito-user-pools-standard-attributes"></a>

Amazon Cognito 根据 [OpenID Connect 规范](http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)为所有用户分配一组标准属性。默认情况下，标准和自定义属性值可以是长度不超过 2048 个字符的任何字符串，但是某些属性值有格式限制。

标准属性是：
+ `name`
+ `family_name`
+ `given_name`
+ `middle_name`
+ `nickname`
+ `preferred_username`
+ `profile`
+ `picture`
+ `website`
+ `gender`
+ `birthdate`
+ `zoneinfo`
+ `locale`
+ `updated_at`
+ `address`
+ `email`
+ `phone_number`
+ `sub`

除 `sub` 外，默认情况下，对于所有用户，标准属性都是可选的。要将某个属性设置为必需属性，请在用户池创建过程中，选择属性旁边的 **Required**（必需）复选框。Amazon Cognito 为每个用户的 `sub` 属性分配一个唯一的用户标识符值。只能验证 **email** 和 **phone\$1number** 属性。

标准属性具有预定义的属性，您可以在 [DescribeUserPool API 响应](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPool.html#API_DescribeUserPool_ResponseSyntax)的`SchemaAttributes`参数中查看这些属性。您可以为这些属性设置自定义值，例如数据类型、可变性和长度限制。要修改标准属性属性，请在[CreateUserPool 架构参数](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-Schema)中设置其自定义值。您还可以在架构中设置必需的属性。在 Amazon Cognito 控制台中创建用户池时，您无法修改标准属性的属性。

**注意**  
 如果您将某个标准属性标记为 **Required**（必需），则用户必须为该属性提供一个值才能注册。要创建用户而不给出必填属性的值，管理员可以使用 [AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html)API。创建用户池后，您无法在必需属性和非必需属性之间切换属性。标准属性详细信息和格式限制

**birthdate**  
值必须是格式中有效的 10 个字符的日期 YYYY-MM-DD。

**电子邮件**  
用户和管理员可以验证电子邮件地址值。  
具有适当 AWS 账户 权限的管理员可以更改用户的电子邮件地址，也可以将其标记为已验证。使用 [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)API 或 [admin-update-user-attributes](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-update-user-attributes.html) AWS Command Line Interface (AWS CLI) 命令将电子邮件地址标记为已验证。使用此命令，管理员可以将 `email_verified` 属性更改为 `true`。您也可以在 Amazon Cognito 控制台的**用户**菜单中编辑用户，以将电子邮件地址标记为已验证。  
值必须是[有效的电子邮件地址字符串](https://datatracker.ietf.org/doc/html/rfc3696#section-3)，遵循标准电子邮件格式，带有 @ 符号和域，长度不超过 2048 个字符。

**phone\$1number**  
如果 SMS 多重验证 (MFA) 处于活动状态，用户必须提供电话号码。有关更多信息，请参阅 [向用户池添加 MFA](user-pool-settings-mfa.md)。  
用户和管理员可以验证电话号码值。  
具有适当 AWS 账户 权限的管理员可以更改用户的电话号码，也可以将其标记为已验证。使用 [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)API 或[admin-update-user-attributes](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-update-user-attributes.html) AWS CLI 命令将电话号码标记为已验证。使用此命令，管理员可以将 `phone_number_verified` 属性更改为 `true`。您也可以在 Amazon Cognito 控制台的**用户**菜单中编辑用户，以将电话号码标记为已验证。  
电话号码必须遵循以下格式规则：电话号码必须以加号 (**\$1**) 开头，后面紧跟国家/地区代码。电话号码只能包含 **\$1** 号和数字。先删除电话号码中的任何其他字符，如圆括号、空格或短划线 (**-**)，然后再将该值提交给服务。例如，美国境内的电话号码必须遵循以下格式：**\$114325551212**。

**preferred\$1username**  
您可以将 `preferred_username` 选择为必需或别名，但不能同时选择这两者。如果`preferred_username`是别名，则可以向 [UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html)API 操作发出请求，并在确认用户后添加属性值。

**sub**  
根据 `sub` 属性对用户编制索引和进行搜索。`sub` 属性是每个用户池中的唯一用户标识符。用户可以更改如 `phone_number` 和 `email` 等属性。`sub` 属性具有固定的值。有关查找用户的更多信息，请参阅[管理和搜索用户账户](how-to-manage-user-accounts.md)。

### 查看必需属性
<a name="how-to-edit-standard-attributes"></a>

通过以下过程可查看给定用户池的必需属性。

**注意**  
在创建用户池后，您无法更改必需属性。

**查看必需属性**

1. 前往 [Amazon Cognito](https://console.aws.amazon.com/cognito/home) AWS 管理控制台如果控制台提示您，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**注册**菜单。

1. 在 **Required attributes**（必需属性）部分中，查看用户池的必需属性。

## 用户名和首选用户名
<a name="user-pool-settings-usernames"></a>

`username` 值是一个单独的属性，与 `name` 属性不同。每个用户都有 `username` 属性。Amazon Cognito 会自动为联合用户生成用户名。您必须提供 `username` 属性以在 Amazon Cognito 目录中创建本地用户。创建用户后，您将无法更改 `username` 属性的值。

开发人员可以使用 `preferred_username` 属性为用户提供一个他们可以更改的用户名。有关更多信息，请参阅 [自定义登录属性](#user-pool-settings-aliases)。

如果您的应用程序不需要用户名，就不必要求用户提供用户名。您的应用程序可以在后台为用户创建唯一的用户名。如果您希望用户使用电子邮件地址和密码注册和登录，这非常有用。有关更多信息，请参阅 [自定义登录属性](#user-pool-settings-aliases)。

在用户池中，`username` 必须是唯一的。`username` 可重复使用，但只能是在您已将其删除且不再使用它的情况下。有关属性的字符串限制的信息，请参阅 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html#CognitoUserPools-SignUp-request-Username)API 请求的*用户名`username`*属性。

## 自定义登录属性
<a name="user-pool-settings-aliases"></a>

创建用户池时，如果您希望用户能够使用电子邮件地址或电话号码作为其用户名进行注册和登录，则可以设置*用户名属性*。或者，您可以设置*别名属性*为用户提供选项：用户可以在注册时包含多个属性，然后使用用户名、首选用户名、电子邮件地址或电话号码登录。

**重要**  
创建用户池后，您无法更改此设置。

### 如何在别名属性和用户名属性之间进行选择
<a name="user-pool-settings-aliases-settings"></a>


| 您的要求 | 别名属性 | 用户名属性 | 
| --- |--- |--- |
| 用户有多个登录属性 | 是¹ | No² | 
| 用户必须先验证电子邮件地址或电话号码，然后才能使用该地址或电话号码登录 | 是 | 否 | 
| 使用重复的电子邮件地址或电话号码注册用户并防止出现UsernameExistsException错误³ | 是 | 否 | 
| 可以将相同的电子邮件地址或电话号码属性值分配给多个用户 | 是⁴ | 否 | 

¹ 可用的登录属性包括用户名、电子邮件地址、电话号码和首选用户名。

² 可以使用电子邮件地址或电话号码进行登录。

³ 当用户使用可能重复的电子邮件地址或电话号码注册但没有用户名时，您的用户池不会生成 `UsernameExistsException` 错误。此行为独立于**防止用户名存在错误**，此错误适用于登录操作，但不适用于注册操作。

⁴ 只有最后验证了该属性的用户才能使用该属性登录。

#### 选项 1：多个登录属性（别名属性）
<a name="user-pool-settings-aliases-settings-option-1"></a>

当用户有用户名但也可以使用某个属性登录时，该属性便是*别名*。如果您想允许用户在登录表单的用户名字段中在其用户名和其他属性值之间进行选择，则可以设置别名。`username` 属性是一个固定值，用户无法更改。如果您将某个属性标记为别名，用户就可以使用该属性代替用户名来登录。您可以将电子邮件地址、电话号码和首选用户名属性标记为别名。例如，如果您选择电子邮件地址和电话号码作为用户池的别名，该用户池中的用户就可以将用户名、电子邮件地址或电话号码与密码一起使用进行登录。

要选择别名属性，请在创建用户池时选择 **User Name**（用户名）和至少一个其他登录选项。

**注意**  
将用户池配置为不区分大小写时，用户可以使用小写或大写字母进行注册或使用别名登录。有关更多信息，请参阅 *Amazon Cognito 用户池 API* 参考[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)中的。

如果您选择电子邮件地址作为别名，Amazon Cognito 不接受与有效电子邮件地址格式匹配的用户名。同样，如果您选择电话号码作为别名，Amazon Cognito 将不接受与有效的电话号码格式相匹配的用户池的用户名。

**注意**  
在用户池中，别名值必须是唯一的。如果您为电子邮件地址或电话号码配置别名，那么提供的值只能在一个账户中处于已验证状态。在注册期间，如果您的用户提供电子邮件地址或电话号码作为别名值，而另一用户已使用该别名值，注册将成功。然而，当用户尝试使用此电子邮件（或电话号码）确认账户并输入有效的代码时，Amazon Cognito 会返回 `AliasExistsException` 错误。该错误向用户指出，已存在使用此电子邮件地址（或电话号码）的账户。此时，用户可以放弃新账户的创建，并尝试重置旧账户的密码。如果用户继续创建新账户，您的应用程序必须使用 `forceAliasCreation` 选项调用 `ConfirmSignUp` API。`ConfirmSignUp` 和 `forceAliasCreation` 结合会将别名从以前的账户移至新创建的账户，并在以前的账户中将此属性标记为未经验证。

只有在您的用户验证电话号码和电子邮件地址后，电话号码和电子邮件地址才会成为用户的活动别名。如果您将电子邮件地址和电话号码用作别名，建议您选择对其进行自动验证。

选择别名属性以防止用户注册时出现电子邮件地址和电话号码属性的 `UsernameExistsException` 错误。

激活 `preferred_username` 属性，以便您的用户可以更改他们用来登录的用户名，而他们的 `username` 属性值不会更改。如果您想设置这种用户体验，请提交新的 `username` 值作为 `preferred_username`，并选择 `preferred_username` 作为别名。这样，用户就可以使用输入的新值登录。如果选择 `preferred_username` 作为别名，您的用户只有在确认账户时才能提供该值。他们在注册期间无法提供该值。

当用户使用用户名注册时，您可以选择他们是否可以使用以下一个或多个别名登录。
+ 经过验证的电子邮件地址
+ 经过验证的电话号码
+ 首选用户名

用户注册后可以更改这些别名。

**重要**  
当您的用户池支持使用别名登录，并且您想要向用户授权或查找用户时，请不要通过用户的任何登录属性来识别您的用户。固定值的用户标识符 `sub` 是用户身份的唯一一致指标。

在创建用户池时包括以下步骤，以便用户可以使用别名登录。

------
#### [ Phone number or email address (console) ]

您必须在创建用户池时将电子邮件地址和电话号码设置为别名属性。

**在 Amazon Cognito 控制台中创建带有用户名别名的用户池**

1. 转到 AWS 管理控制台中的 [Amazon Cognito](https://console.aws.amazon.com/cognito/home)。如果控制台提示您，请输入您的 AWS 凭据。

1. 使用**开始使用**或**创建用户池**按钮创建新的用户池。

1. 在**定义您的应用程序**中选择应用程序设置。

1. 在**配置选项**中的**登录标识符的选项**下，选中**用户名**旁边的复选框以及至少一个其他选项，即**电子邮件**和**电话号码**。

1. 选择您的别名属性作为**注册的必要属性**。在托管登录的注册表单中，Amazon Cognito 会提示新用户为必要属性提供值。

1. 在**添加返回 URL** 下，设置应用程序回调 URL，以便在托管登录的登录后进行重定向。

1. 选择**创建**。

------
#### [ Phone number or email address (API/SDK) ]

使用 [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)API 操作创建新的用户池。如下所示配置 `AliasAttributes` 参数。如果您只需要电话号码别名，则可以删除 `email` 条目；如果您只需要电子邮件地址别名，则可以删除 `phone_number` 条目。

```
"AliasAttributes": [
   "email",
   "phone_number"
],
```

------
#### [ Preferred username (API/SDK) ]

Amazon Cognito 控制台创建不使用 `preferred_username` 作为别名的用户池。要使用`preferred_username`别名创建用户池，请在 AWS SDK 中设置包含 [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)API 请求的用户池。要支持在注册时创建首选用户名属性，请将 `preferred_username` 设置为必需属性。在托管登录的注册表单中，Amazon Cognito 会提示新用户为必要属性提供值。您*可以*在 Amazon Cognito 控制台中将 `preferred_username` 设置为必需属性，但这并不能将其用作别名。

**配置为别名**  
如下所示，在 `CreateUserPool` 请求的 `AliasAttributes` 参数中将 `preferred_username` 配置为别名。从列表中删除任何您不想作为别名属性的值。

```
"AliasAttributes": [
   "email",
   "phone_number",
   "preferred_username"
],
```

**根据需要进行配置**  
在托管登录的注册表单中，Amazon Cognito 会提示新用户为必要属性提供值。`preferred_username`根据需要在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)请求的`SchemaAttributes`参数中进行配置。

要将首选用户名设置为必需属性，请按如下所示进行配置。以下示例修改 `preferred_username` 的默认方案，以根据需要对其进行设置。诸如 `AttributeDataType`（默认为 `string`）和 `StringAttributeConstraints`（长度默认为 1-99 个字符）等其他方案参数采用默认值。

```
"Schema": [
   {
      "Name": "preferred_username",
      "Required": true
   }
]
```

------

#### 选项 2：将电子邮件地址或电话号码作为登录属性（用户名属性）
<a name="user-pool-settings-aliases-settings-option-2"></a>

当用户使用电子邮件地址或电话号码作为其用户名进行注册时，您可以选择他们是否可以仅使用电子邮件地址、仅使用电话号码或其中之一进行注册。

要选择用户名属性，请在创建用户池时不要选择**用户名**作为登录选项。

电子邮件地址或电话号码必须是唯一的，并且不能已被其他用户使用。它不必经过验证。用户使用电子邮件地址或电话号码注册之后，将无法使用相同的电子邮件地址或电话号码创建新账户。如果需要，用户只能重复使用现有账户并重置账户的密码。但是，用户可以将电子邮件地址或电话号码更改为新的电子邮件地址或电话号码。如果电子邮件地址或电话号码未被使用，它将成为新的用户名。

当您同时选择电子邮件地址和电话号码作为用户名属性时，用户可以使用其中一个属性登录，即使他们为这两个属性都提供了值。登录用户名基于您在`Username`参数中传递的[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html#CognitoUserPools-SignUp-request-Username)值。

**注意**  
如果用户使用电子邮件地址作为用户名进行注册，则可以将用户名更改为另一个电子邮件地址，但他们无法将用户名更改为电话号码。如果用户使用电话号码进行注册，他们可以将用户名更改为另一个电话号码，但他们无法将用户名更改为电子邮件地址。

在用户池创建过程中使用以下步骤设置使用电子邮件地址或电话号码注册和登录。

------
#### [ Username attributes (console) ]

以下过程创建带有电子邮件地址或电话号码用户名属性的用户池。在 Amazon Cognito 控制台中设置用户名属性的过程的不同之处在于，您不必同时将**用户名**设置为登录属性。

**在 Amazon Cognito 控制台中创建带有用户名属性的用户池**

1. 转到 AWS 管理控制台中的 [Amazon Cognito](https://console.aws.amazon.com/cognito/home)。如果控制台提示您，请输入您的 AWS 凭据。

1. 使用**开始使用**或**创建用户池**按钮创建新的用户池。

1. 在**定义您的应用程序**中选择应用程序设置。

1. 在**配置选项**中的**登录标识符的选项**下，选择您的用户名属性：**电子邮件**、**电话号码**或同时选择两者。取消选中**用户名**。

1. 作为最佳实践，请选择用户名属性作为**注册的必要属性**。在托管登录的注册表单中，Amazon Cognito 会提示新用户为必要属性提供值。如果您未按要求设置用户名属性，Amazon Cognito 不会提示新用户为其提供值。在这种情况下，您必须将应用程序配置为收集并提交每个用户的电子邮件地址或电话号码，然后他们才能登录。

1. 在**添加返回 URL** 下，设置应用程序回调 URL，以便在托管登录的登录后进行重定向。

1. 选择**创建**。

------
#### [ Username attributes (API/SDK) ]

在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)请求中，如图所示配置`UsernameAttributes`参数。要仅允许使用电子邮件地址用户名登录，请在此列表中单独指定 `email`。要仅允许使用电话号码用户名登录，请单独指定 `phone_number`。此参数将覆盖用户名作为登录选项。

```
"UsernameAttributes": [ 
   "email",
   "phone_number"
],
```

------

配置用户名属性时，可以发出 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)API 请求，在`username`参数中传递电子邮件地址或电话号码。以下是带有用户名属性的代码 `SignUp` API 操作的行为。
+ 如果 `username` 字符串采用有效的电子邮件地址格式，例如 `user@example.com`，用户池将使用 `username` 值自动填充用户的 `email` 属性。
+ 如果 `username` 字符串采用有效的电话号码格式，例如 `+12065551212`，用户池将使用 `username` 值自动填充用户的 `phone_number` 属性。
+ 如果 `username` 字符串格式不是电子邮件或电话号码格式，`SignUp` API 将返回异常。
+ 如果 `username` 字符串包含已被使用的电子邮件地址或电话号码，`SignUp` API 将返回异常。
+ `SignUp` API 使用您的用户的 [UUID](cognito-terms.md#terms-uuid) 填充 `username` 属性。此 UUID 与用户身份令牌中的 `sub` 声明具有相同的值。

 APIs除了操作之外，您还可以在所有[ListUsers](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html)操作中使用电子邮件地址或电话号码代替用户名。在 `ListUsers` API 请求中，您可以指定 `email` 或 `phone_number` 的 `Filter`。如果按 `username` 进行筛选，则必须提供 UUID 用户名，而不是电子邮件地址或电话号码。

## 自定义属性
<a name="user-pool-settings-custom-attributes"></a>

您可以将最多 50 个自定义属性添加到您的用户池。您可以为自定义属性指定一个最小和/或最大长度。但是，任何自定义属性的最大长度不能超过 2048 个字符。自定义属性的名称必须与`Name`参数中描述的正则表达式模式相匹配[SchemaAttributeType](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SchemaAttributeType.html)。

**每个自定义属性都具有以下特性：**
+ 可以将其定义为字符串、数字、布尔值或 `DateTime` 对象。Amazon Cognito 仅将自定义属性值作为字符串写入 ID 令牌。
**注意**  
在 Amazon Cognito 控制台中，您只能添加字符串和数字数据类型的自定义属性。布尔值和`DateTime`属性数据类型等其他选项仅在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)和 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求的`SchemaAttributes`属性中可用。
+ 您不能要求用户为属性提供值。
+ 将其添加到用户池后，您将无法删除或更改它。
+ 属性名称的字符长度在 Amazon Cognito 接受的限制范围内。有关更多信息，请参阅 [Amazon Cognito 中的限额](quotas.md)。
+ 它可能是*可以改变的*，也可能是*不可改变的*。在创建用户时，您只能将值写入不可改变属性。如果您的应用程序客户端具有该属性的写入权限，您可以更改可变属性的值。请参阅[属性权限和范围](#user-pool-settings-attribute-permissions-and-scopes)了解更多信息。

**注意**  
在您的代码和 [使用基于角色的访问控制](role-based-access-control.md) 的规则设置中，自定义属性需要使用 `custom:` 前缀，以便将它们与标准属性区分开来。

在创建用户池时，您还可以在的*属性中添加开发者属性[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)*。`SchemaAttributes`开发人员属性具有 `dev:` 前缀。您只能使用 AWS 凭证修改用户的开发者属性。开发人员属性是一项旧版特征，Amazon Cognito 已将其替换为应用程序客户端读写权限。

通过以下过程创建新的自定义属性。

**使用控制台添加自定义属性**

1. 前往 [Amazon Cognito](https://console.aws.amazon.com/cognito/home) AWS 管理控制台如果控制台提示您，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**注册**菜单，然后在**自定义属性**部分，选择**添加自定义属性**。

1. 在存储库的 **Add custom attributes**（添加自定义属性）页面上，提供有关新属性的以下详细信息：
   + 输入 **Name**（名称）。
   + 选择 **Type**（类型）（**字符串**或**数字**）。
   + 输入**最小**字符串长度或数字值。
   + 输入**最大**字符串长度或数字值。
   + 如果您想授予用户在设置初始值后更改自定义属性值的权限，请选择 **Mutable**（可变）。

1. 选择 **Save changes**（保存更改）。

## 属性权限和范围
<a name="user-pool-settings-attribute-permissions-and-scopes"></a>

对于每个应用程序客户端，您可以为每个用户属性设置读取和写入权限。这样，您可以控制为了读取和修改您为用户存储的每个属性，任何应用程序所具有的访问权限。例如，您可以设置一个自定义属性，用于指明用户是否为付费客户。您的应用程序可能能够看到此属性，但无法直接更改它。相反，您可以使用管理工具或后台进程更新此属性。您可以通过 Amazon Cognito 控制台、Amazon Cognito API 或 AWS CLI设置用户属性的权限。默认情况下，任何新的自定义属性都不可用，直到您为其设置读取和写入权限。默认情况下，创建新的应用程序客户端时，您将授予应用程序对所有标准和自定义属性的读取和写入权限。要将应用程序限制为仅使用它所需的信息量，请在应用程序客户端配置中为属性分配特定权限。

妥善做法是在创建应用程序客户端时指定属性的读取和写入权限。向您的应用程序客户端授予应用程序运行所需的最小用户属性集的访问权限。

**注意**  
[DescribeUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPoolClient.html)只有在配置默认权限之外的应用程序客户端权限`WriteAttributes`时，才会返回`ReadAttributes`和的值。

**更新属性权限（AWS 管理控制台）**

1. 前往 [Amazon Cognito](https://console.aws.amazon.com/cognito/home) AWS 管理控制台如果控制台提示您，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**应用程序客户端**菜单，然后从列表中选择应用程序客户端。

1. 在**属性权限**选项卡中，选择**编辑**。

1. 在 **Edit attribute read and write permissions**（编辑设置属性读取和写入权限）页面上，配置读取和写入权限，然后选择 **Save changes**（保存更改）。

使用自定义属性对每个应用程序客户端重复这些步骤。

对于每个应用程序客户端，您可以将属性标记为可读或可写。这对于标准属性和自定义属性均适用。您的应用程序可以检索您标记为可读的属性的值，也可以设置或修改您标记为可写的属性的值。如果您的应用程序尝试为其无权写入的属性设置值，Amazon Cognito 会返回。`NotAuthorizedException` [GetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html)请求包括带有应用程序客户端声明的访问令牌；Amazon Cognito 仅返回应用程序客户端可以读取的属性的值。来自应用程序的用户 ID 令牌仅包含与可读属性相对应的声明。所有应用程序客户端都可以写入用户池所需的属性。仅当您还为尚未具有值的必需属性提供值时，才能在 Amazon Cognito 用户池 API 请求中设置相应属性的值。

自定义属性具有不同的读写权限特征。您可以将它们创建为用户池的可变或不可变属性，并可以将它们设置为任何应用程序客户端的读或写属性。

在创建用户期间，不可变的自定义属性可以更新一次。您可以使用以下方法填充不可变的属性。
+ `SignUp`：用户注册了一个应用程序客户端，该客户端具有对不可变自定义属性的写访问权限。它们为该属性提供了一个值。
+ 使用第三方 IdP 登录：用户登录到一个应用程序客户端，该客户端具有对不可变自定义属性的写访问权限。IdP 的用户池配置有一条规则，可以将提供的声明映射到不可变的属性。这可以实现，但不太实际，因为用户只能登录一次。在首次登录后，如果用户尝试再次登录，Amazon Cognito 会因为映射规则指向一个现在不可写的属性而拒绝登录尝试。
+ `AdminCreateUser`：您为不可变属性提供一个值。

### 使用范围的属性权限
<a name="user-pool-settings-attribute-scope-based-permissions"></a>

在使用 AWS SDK 或 CDK、REST API 或配置的用户池中 AWS CLI，您可以使用 OIDC 范围配置应用程序客户端的读取或写入权限。`oidc:profile``oidc:profile` 授予对以下标准属性的读取或写入权限：
+ `name`
+ `family_name`
+ `given_name`
+ `middle_name`
+ `nickname`
+ `preferred_username`
+ `profile`
+ `picture`
+ `website`
+ `gender`
+ `birthdate`
+ `zoneinfo`
+ `locale`

此列表是 OIDC 标准属性减去 `email`、`phone_number`、`sub` 和 `address`，如 [OIDC 规范第 2.4 节](https://openid.net/specs/openid-connect-basic-1_0.html#Scopes)中所定义。有关您可以分配给应用程序客户端的范围的信息，请参阅[作用域、M2M 和资源服务器](cognito-user-pools-define-resource-servers.md)。

要将您的应用程序客户端配置为写入`oidc:profile`作用域下的属性，请在[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)或 [UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)API 请求中[WriteAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#CognitoUserPools-CreateUserPoolClient-request-WriteAttributes)将`oidc:profile`的值设置为，以及您希望允许应用程序修改的任何其他属性。同样，要授予对这些属性的读取权限，`oidc:profile`请添加的值[ReadAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#CognitoUserPools-CreateUserPoolClient-request-ReadAttributes)。

您可以在创建用户池后更改属性权限和范围。

# 了解用户池 JSON 网络令牌 (JWTs)
<a name="amazon-cognito-user-pools-using-tokens-with-identity-providers"></a>

令牌是身份验证的构件，您的应用程序可以将其用作 OIDC 身份验证的证明并请求访问资源。令牌中的*声明*是有关您的用户的信息。ID 令牌包含有关用户身份的声明，例如他们的用户名、姓氏和电子邮件地址。访问令牌包含诸如经过身份验证`scope`的用户可用于访问第三方 APIs、Amazon Cognito 用户自助服务 API 操作以及. [userInfo 端点](userinfo-endpoint.md) 访问令牌和 ID 令牌均包含 `cognito:groups` 声明，其中包含用户在用户池中的组成员资格。有关用户池组的更多信息，请参阅 [向用户池添加组](cognito-user-pools-user-groups.md)。

Amazon Cognito 还有刷新令牌，您可以使用它来获取新的令牌或撤销现有令牌。[刷新令牌](amazon-cognito-user-pools-using-the-refresh-token.md)来检索新的 ID 令牌和访问令牌。[撤销令牌](amazon-cognito-user-pools-using-the-refresh-token.md#amazon-cognito-identity-user-pools-revoking-all-tokens-for-user)来撤销刷新令牌允许的用户访问权限。

Amazon Cognito 以 [base64url](https://datatracker.ietf.org/doc/html/rfc4648#section-5) 编码字符串的形式发布令牌。您可以将任何 Amazon Cognito ID 或访问令牌从 `base64url` 解码为纯文本 JSON。Amazon Cognito 刷新令牌已加密，对用户池用户和管理员不透明，并且只能由您的用户池读取。

**使用令牌进行身份验证**  
当用户登录您的应用程序时，Amazon Cognito 会验证登录信息。如果登录成功，Amazon Cognito 会创建会话并为经过身份验证的用户返回 ID 令牌、访问令牌和刷新令牌。您可以使用这些令牌向您的用户授予对下游资源的访问权限， APIs 例如 Amazon API Gateway。或者，您可以用它们交换用于访问其他 AWS 服务的临时 AWS 凭证。

![\[身份验证概述\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/scenario-authentication-cup2.png)


**存储令牌**  
您的应用程序必须能够存储不同大小的令牌。令牌大小变化的原因可能包括但不限于其它声明、编码算法的更改以及加密算法的更改等。当您在用户池中启用令牌吊销时，Amazon Cognito 会向 JSON Web 令牌添加其他声明，从而增加令牌大小。新 `origin_jti` 和 `jti` 声明已添加到访问和 ID 令牌中。有关令牌撤销的更多信息，请参阅[撤销令牌](https://docs.aws.amazon.com/cognito/latest/developerguide/token-revocation.html)。

**重要**  
最佳实践是在应用程序环境中保护传输和存储中的所有令牌。令牌可以包含有关用户的个人识别信息，以及有关用于用户池的安全模型的信息。

**自定义令牌**  
您可以自定义 Amazon Cognito 传递给应用程序的访问令牌和 ID 令牌。在 [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md) 中，您可以添加、修改和隐藏令牌声明。令牌生成前触发器是一个 Lambda 函数，Amazon Cognito 会向其发送一组默认声明。声明包括 OAuth 2.0 范围、用户池群组成员资格、用户属性等。然后，该函数可以根据这些信息在运行时进行更改，并将更新的令牌声明返回给 Amazon Cognito。

使用版本 2 事件自定义访问令牌需要支付额外费用。有关更多信息，请参阅 [Amazon Cognito 定价](https://aws.amazon.com/cognito/pricing/)。

**Topics**
+ [了解身份（ID）令牌](amazon-cognito-user-pools-using-the-id-token.md)
+ [了解访问令牌](amazon-cognito-user-pools-using-the-access-token.md)
+ [刷新令牌](amazon-cognito-user-pools-using-the-refresh-token.md)
+ [通过令牌撤销来结束用户会话](token-revocation.md)
+ [验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)
+ [管理用户池令牌到期和缓存](amazon-cognito-user-pools-using-tokens-caching-tokens.md)

# 了解身份（ID）令牌
<a name="amazon-cognito-user-pools-using-the-id-token"></a>

ID 令牌是一个 [JSON Web 令牌（JWT）](https://tools.ietf.org/html/rfc7519)，其中包含有关经身份验证的用户的身份声明，如 `name`、`email` 和 `phone_number`。您可以在应用程序中使用此身份信息。此外，ID 令牌还可用于针对资源服务器或服务器应用程序对用户进行身份验证。您还可以将应用程序外部的 ID 令牌用于 Web API 操作。在这些情况下，您必须先验证 ID 令牌的签名，然后才能信任 ID 令牌内的任何声明。请参阅[验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。

您可以将 ID 令牌过期时间设置为 5 分钟到 1 天之间的任何值。您可以按应用程序客户端设置此值。

**重要**  
当您的用户使用托管登录信息登录时，Amazon Cognito 会设置有效期为 1 小时的会话 Cookie。如果您在应用程序中使用托管登录信息进行身份验证，并为访问和 ID 令牌指定不到 1 小时的最短持续时间，则您的用户在 Cookie 过期前仍将拥有有效的会话。如果用户的令牌在一小时的会话期间过期，则用户可以刷新他们的令牌，而无需重新身份验证。

## ID 令牌标头
<a name="user-pool-id-token-header"></a>

标头包含两部分信息：密钥 ID (`kid`) 和算法 (`alg`)。

```
{
"kid" : "1234example=",
"alg" : "RS256"
}
```

**`kid`**  
 密钥 ID。其值指示用于保护令牌的 JSON Web Signature (JWS) 的密钥。您可以在`jwks_uri`终端节点上查看您的用户池签 IDs 名密钥。  
有关 `kid` 参数的更多信息，请参阅[密钥标识符 (kid) 标头参数](https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4.5)。

**`alg`**  
Amazon Cognito 用于保护访问令牌的加密算法。用户池使用 RS256 加密算法，即带有 SHA-256 的 RSA 签名。  
有关 `alg` 参数的更多信息，请参阅[算法（alg）标头参数](https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4.4)。

## ID 令牌默认有效载荷
<a name="user-pool-id-token-payload"></a>

这是来自 ID 令牌的示例有效载荷。它包含有关经过身份验证的用户的声明。有关 OpenID Connect（OIDC）标准声明的更多信息，请参阅 [OIDC 标准声明](http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)列表。您可以使用 [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md) 添加自有设计的声明。

```
<header>.{
    "sub": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "cognito:groups": [
        "test-group-a",
        "test-group-b",
        "test-group-c"
    ],
    "email_verified": true,
    "cognito:preferred_role": "arn:aws:iam::111122223333:role/my-test-role",
    "iss": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_example",
    "cognito:username": "my-test-user",
    "middle_name": "Jane",
    "nonce": "abcdefg",
    "origin_jti": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "cognito:roles": [
        "arn:aws:iam::111122223333:role/my-test-role"
    ],
    "aud": "xxxxxxxxxxxxexample",
    "identities": [
        {
            "userId": "amzn1.account.EXAMPLE",
            "providerName": "LoginWithAmazon",
            "providerType": "LoginWithAmazon",
            "issuer": null,
            "primary": "true",
            "dateCreated": "1642699117273"
        }
    ],
    "event_id": "64f513be-32db-42b0-b78e-b02127b4f463",
    "token_use": "id",
    "auth_time": 1676312777,
    "exp": 1676316377,
    "iat": 1676312777,
    "jti": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "email": "my-test-user@example.com"
}
.<token signature>
```

**`sub`**  
经过身份验证的用户的唯一标识符（[UUID](cognito-terms.md#terms-uuid)）或主题。用户名在您的用户群体中可能不是唯一的。`sub` 声明是识别给定用户的最佳方法。

**`cognito:groups`**  
以您的用户为成员的用户群体组的名称数组。组可以是您提供给应用程序的标识符，也可以从身份池为首选 IAM 角色生成请求。

**`cognito:preferred_role`**  
与用户的最高优先级用户池组关联的 IAM 角色的 ARN。有关您的用户池如何选择此角色声明的更多信息，请参阅[将优先级值分配到组](cognito-user-pools-user-groups.md#assigning-precedence-values-to-groups)。

**`iss`**  
颁发令牌的身份提供者。声明采用以下格式。  
`https://cognito-idp.<Region>.amazonaws.com/<your user pool ID>`

**`cognito:username`**  
用户池中用户的用户名。

**`nonce`**  
`nonce`声明来自同名参数，您可以将其添加到对 OAuth 2.0 `authorize` 终端节点的请求中。添加参数时，`nonce` 声明包含在 Amazon Cognito 颁发的 ID 令牌中，您可以使用它来防范重播攻击。如果在您的请求中未提供 `nonce` 值，当您通过第三方身份提供商进行身份验证时，Amazon Cognito 会自动生成并验证随机数，然后将其作为 `nonce` 声明添加到 ID 令牌中。Amazon Cognito 中的 `nonce` 声明的实现基于 [OIDC 标准](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation)。

**`origin_jti`**  
与用户的刷新令牌关联的令牌撤消标识符。Amazon Cognito 在检查您是否通过[撤销端点](revocation-endpoint.md)或 API 操作撤销了用户的令牌时会引用该`origin_jti`声明。[RevokeToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html)当您撤销令牌时，Amazon Cognito 会使所有具有相同 `origin_jti` 值的访问令牌和 ID 令牌失效。

**`cognito:roles`**  
与您的用户组关联的 IAM 角色的名称的数组。每个用户池组可以有一个与之关联的 IAM 角色。此数组显示了您的用户组的所有 IAM 角色，不按优先级排列。有关更多信息，请参阅 [向用户池添加组](cognito-user-pools-user-groups.md)。

**`aud`**  
对用户进行身份验证的用户群体应用程序客户端。Amazon Cognito 在访问令牌 `client_id` 声明中呈现相同的值。

**`identities`**  
用户的 `identities` 属性的内容。该属性包含有关您通过联合登录或通过[将联合用户与本地配置文件关联](cognito-user-pools-identity-federation-consolidate-users.md)而与用户关联的每个第三方身份提供者配置文件的信息。此信息包含其提供商名称、提供商唯一 ID 和其它元数据。

**`token_use`**  
令牌的预期用途。在 ID 令牌中，其值为 `id`。

**`auth_time`**  
您的用户完成身份验证的身份验证时间，采用 Unix 时间格式。

**`exp`**  
您的用户令牌的过期时间，采用 Unix 时间格式。

**`iat`**  
Amazon Cognito 颁发您的用户令牌的时间，采用 Unix 时间格式。

**`jti`**  
JWT 的唯一标识符。

ID 令牌可包含 [OIDC 标准声明](https://openid.net/specs/openid-connect-core-1_0.html#Claims)中所定义的 OIDC 标准声明。ID 令牌还可包含您在用户池中定义的自定义属性。无论属性类型如何，Amazon Cognito 都会将自定义属性值作为字符串写入 ID 令牌。

**注意**  
用户池自定义属性始终以 `custom:` 为前缀。

## ID 令牌签名
<a name="user-pool-id-token-signature"></a>

ID 令牌的签名根据 JWT 令牌的标头和负载计算。在您接受应用程序收到的任何 ID 令牌中的声明之前，请验证该令牌的签名。有关更多信息，请参阅“验证 JSON Web 令牌”。[验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。

# 了解访问令牌
<a name="amazon-cognito-user-pools-using-the-access-token"></a>

用户池访问令牌包含有关经身份验证的用户声明、用户组列表以及作用域列表。访问令牌的目的是授权执行 API 操作。您的用户池接受访问令牌以授权用户执行自助操作。例如，您可以使用访问令牌授予用户访问权限以添加、更改或删除用户属性。

通过访问令牌中的 [OAuth 2.0 作用](https://www.rfc-editor.org/rfc/rfc6749#section-3.3)域（源自您添加到用户池中的自定义范围），您可以授权您的用户从 API 检索信息。例如，Amazon API Gateway 支持使用 Amazon Cognito 访问令牌进行授权。您可以使用用户池中的信息填充 REST API 授权方，也可以使用 Amazon Cognito 作为 HTTP API 的 JSON 网络令牌（JWT）授权方。要生成具有自定义作用域的访问令牌，您必须通过用户池[公有端点](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html)请求访问令牌。

借助基础版或增值版[功能计划](cognito-sign-in-feature-plans.md)，您还可以实施令牌生成前 Lambda 触发器，在运行时为您的访问令牌添加作用域。有关更多信息，请参阅 [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md)。

用户的 `openid` 作用域的访问令牌，是允许通过 [userInfo 端点](userinfo-endpoint.md)请求有关您的用户属性的更多信息的权限。来自 `userInfo` 端点的信息量源自访问令牌中的额外作用域：例如，`profile` 用于获取所有用户数据，`email` 用于获取用户的电子邮件地址。

用户的 `aws.cognito.signin.user.admin` 作用域的访问令牌，是读取和写入用户属性、列出身份验证因素、配置多重身份验证（MFA）首选项以及管理记住的设备的权限。您的访问令牌授予此范围的属性访问权限级别与您分配给应用程序客户端的属性 read/write 权限相匹配。

访问令牌是 [JSON Web 令牌 (JWT)](https://www.rfc-editor.org/rfc/rfc7519)。访问令牌的标头与 ID 令牌具有相同的结构。Amazon Cognito 使用与签署 ID 令牌的密钥所不同的密钥对访问令牌进行签名。访问密钥 ID (`kid`) 声明的值与来自同一用户会话的 ID 令牌中 `kid` 声明的值不匹配。在您的应用程序代码中，单独验证 ID 令牌和访问令牌。在验证签名之前，请勿信任访问令牌中的声明。有关更多信息，请参阅 [验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。您可以将访问令牌过期时间设置为 5 分钟到 1 天之间的任何值。您可以按应用程序客户端设置此值。

**重要**  
对于访问令牌和 ID 令牌，如果使用托管登录，请勿将最小值指定为少于一小时。托管登录会设置有效期为一小时的浏览器 Cookie。如果您将访问令牌的持续时间配置为小于一小时，这不会影响托管登录 Cookie 的有效性，也不会影响用户在初始登录后一小时内无需其他凭证即可重新进行身份验证的能力。

## 访问令牌标头
<a name="user-pool-access-token-header"></a>

标头包含两部分信息：密钥 ID (`kid`) 和算法 (`alg`)。

```
{
"kid" : "1234example="
"alg" : "RS256",
}
```

**`kid`**  
 密钥 ID。其值指示用于保护令牌的 JSON Web Signature (JWS) 的密钥。您可以在`jwks_uri`终端节点上查看您的用户池签 IDs 名密钥。  
有关 `kid` 参数的更多信息，请参阅[密钥标识符 (kid) 标头参数](https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4.5)。

**`alg`**  
Amazon Cognito 用于保护访问令牌的加密算法。用户池使用 RS256 加密算法，即带有 SHA-256 的 RSA 签名。  
有关 `alg` 参数的更多信息，请参阅[算法（alg）标头参数](https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4.4)。

## 访问令牌默认有效载荷
<a name="user-pool-access-token-payload"></a>

这是来自访问令牌的示例负载。有关更多信息，请参阅 [JWT 声明](https://tools.ietf.org/html/rfc7519#section-4)。您可以使用 [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md) 添加自有设计的声明。

```
<header>.
{
   "sub":"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "device_key": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "cognito:groups":[
      "testgroup"
   ],
   "iss":"https://cognito-idp.us-west-2.amazonaws.com/us-west-2_example",
   "version":2,
   "client_id":"xxxxxxxxxxxxexample",
   "aud": "https://api.example.com",
   "origin_jti":"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "event_id":"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "token_use":"access",
   "scope":"phone openid profile resourceserver.1/appclient2 email",
   "auth_time":1676313851,
   "exp":1676317451,
   "iat":1676313851,
   "jti":"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "username":"my-test-user"
}
.<token signature>
```

**`sub`**  
经过身份验证的用户的唯一标识符（[UUID](cognito-terms.md#terms-uuid)）或主题。用户名在您的用户群体中可能不是唯一的。`sub` 声明是识别给定用户的最佳方法。

**`cognito:groups`**  
以您的用户为成员的用户群体组的名称数组。

**`iss`**  
颁发令牌的身份提供者。声明采用以下格式。  
`https://cognito-idp.us-east-1.amazonaws.com/us-east-1_EXAMPLE`

**`client_id`**  
对用户进行身份验证的用户群体应用程序客户端。Amazon Cognito 在 ID 令牌 `aud` 声明中呈现相同的值。

**aud**  
访问令牌要授权的 API 的 URL。仅当您的应用程序向授权服务器请求[资源绑定](cognito-user-pools-define-resource-servers.md#cognito-user-pools-resource-binding)时才会显示。

**`origin_jti`**  
与用户的刷新令牌关联的令牌撤消标识符。Amazon Cognito 在检查您是否通过[撤销端点](revocation-endpoint.md)或 API 操作撤销了用户的令牌时会引用该`origin_jti`声明。[RevokeToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html)当您撤销令牌时，Amazon Cognito 将不再对访问权限以及具有相同 `origin_jti` 值的 ID 令牌进行验证。

**`token_use`**  
令牌的预期用途。在访问令牌中，其值为 `access`。

**`scope`**  
向登录用户发布的 OAuth 2.0 范围列表。作用域定义令牌为`userInfo`端点上的外部 APIs、用户自助服务操作和用户数据提供的访问权限。[令牌端点](token-endpoint.md) 中的令牌可以包含您的应用程序客户端支持的任何作用域。来自 Amazon Cognito API 登录的令牌仅包含作用域 `aws.cognito.signin.user.admin`。

**`auth_time`**  
您的用户完成身份验证的身份验证时间，采用 Unix 时间格式。

**`exp`**  
您的用户令牌的过期时间，采用 Unix 时间格式。

**`iat`**  
Amazon Cognito 颁发您的用户令牌的时间，采用 Unix 时间格式。

**`jti`**  
JWT 的唯一标识符。

**`username`**  
用户池中用户的用户名。

**更多资源**
+ [如何在 Amazon Cognito 用户池中自定义访问令牌](https://aws.amazon.com/blogs/security/how-to-customize-access-tokens-in-amazon-cognito-user-pools/)

## 访问令牌签名
<a name="user-pool-access-token-signature"></a>

访问令牌的签名使用在 `.well-known/jwks.json` 端点公布的密钥进行签名，可验证令牌标头和有效载荷的完整性。当您使用访问令牌授权外部访问时 APIs，请务必将您的 API 授权方配置为根据签名该签名的密钥来验证此签名。有关更多信息，请参阅 [验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。

# 刷新令牌
<a name="amazon-cognito-user-pools-using-the-refresh-token"></a>

您可以使用刷新令牌来检索新的 ID 令牌和访问令牌。默认情况下，刷新令牌会在您的应用程序用户登录用户池的 30 天后过期。当您为用户池创建应用程序时，您可以将应用程序的刷新令牌到期时间设置为介于 60 分钟和 10 年之间的任何值。

## 使用刷新令牌获取新的访问权限和身份令牌
<a name="amazon-cognito-user-pools-using-the-refresh-token_initiate-token"></a>

Amazon Cognito 会在通过托管登录的授权代码流程以及 API 操作或 SDK 方法成功完成身份验证后，颁发刷新令牌。刷新令牌会返回新的 ID 和访问令牌，以及可选的新刷新令牌。可以通过以下方式使用刷新令牌。

**GetTokensFromRefreshToken**  
[GetTokensFromRefreshToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetTokensFromRefreshToken.html)API 操作从有效的刷新令牌中发布新的 ID 和访问令牌。如果您启用了刷新令牌轮换，则还会获得新的刷新令牌。

**InitiateAuth 和 AdminitiateAuth**  
[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)API 操作包括`REFRESH_TOKEN_AUTH`身份验证流程。在此流程中，您可以传递刷新令牌，并获得新的 ID 令牌和访问令牌。在启用[刷新令牌轮换](#using-the-refresh-token-rotation)的应用程序客户端中，您无法使用 `REFRESH_TOKEN_AUTH` 进行身份验证。

**OAuth 令牌端点**  
在具有[域](cognito-user-pools-assign-domain.md)的用户池中，[令牌端点](token-endpoint.md)支持 `refresh_token` 授予类型，可通过一个有效的刷新令牌颁发新的 ID 令牌、访问令牌，并（通过[刷新令牌轮换](#using-the-refresh-token-rotation)）选择性地颁发刷新令牌。

## 刷新令牌轮换
<a name="using-the-refresh-token-rotation"></a>

您可以选择在应用程序客户端中配置刷新令牌轮换。通过刷新令牌轮换，您的客户端在每次刷新令牌时都会使原始刷新令牌失效，并颁发一个新的刷新令牌。启用此设置后，所有形式的令牌刷新请求成功后，都会返回一个新的 ID 令牌、访问令牌*和*刷新令牌。禁用此设置后，令牌刷新请求仅返回新的访问令牌和 ID 令牌，并且原始刷新令牌仍然有效。新的刷新令牌的有效期为原始刷新令牌的剩余有效时间。可以将[应用程序客户端](user-pool-settings-client-apps.md)配置为轮换刷新令牌或保留使用原始刷新令牌。为了支持短暂时间内的重试操作，还可以为原始刷新令牌配置最长 60 秒的宽限期。

**有关刷新令牌轮换的需知信息**
+ 启用刷新令牌轮换后，您的用户池的 JSON Web 令牌中会添加新的声明。`origin_jti` 和 `jti` 声明已添加到访问和 ID 令牌中。这些索赔增加了索赔的规模 JWTs。
+ 刷新令牌轮换与 `REFRESH_TOKEN_AUTH` 身份验证流程不兼容。要实现刷新令牌轮换，您必须在应用程序客户端中禁用此身份验证流程，并将您的应用程序设计为使用 [GetTokensFromRefreshToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetTokensFromRefreshToken.html)API 操作或等效的 SDK 方法提交令牌刷新请求。
+ 当刷新令牌轮换未启用时，您可以使用 `GetTokensFromRefreshToken` 或 `REFRESH_TOKEN_AUTH` 来完成令牌刷新请求。
+ 当您的用户池中启用了[设备记忆](amazon-cognito-user-pools-device-tracking.md)功能时，您必须在 `GetTokensFromRefreshToken` 请求中提供设备密钥。如果您的用户没有您的应用程序在初始身份验证请求中提交的已确认设备密钥，Amazon Cognito 会颁发一个新的密钥。在此置下进行令牌刷新时，无论您是在 `AuthParameters` 中指定了设备密钥，还是在身份验证响应中收到了新的设备密钥，都必须提供该设备密钥。
+ 可以在 `GetTokensFromRefreshToken` 请求中将 `ClientMetadata` 传递给令牌生成前 Lambda 触发器。这些数据将传递至触发器的输入事件，并提供额外上下文信息，可用于您的 Lambda 函数的自定义逻辑。

作为一项安全最佳实践，请在应用程序客户端启用刷新令牌轮换。

------
#### [ Enable refresh token rotation (console) ]

以下过程可用于为您的应用程序客户端打开或关闭刷新令牌轮换。此过程需要一个现有的应用程序客户端。要了解有关创建应用程序客户端的更多信息，请参阅[特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。

**启用刷新令牌轮换**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 导航到**应用程序客户端**菜单，然后选择一个现有的应用程序客户端。

1. 从页面的**应用程序客户端信息**部分选择**编辑**。

1. 在**高级安全配置**下，找到**启用刷新令牌轮换**选项。

1. 要启用轮换，请选中该复选框。要禁用轮换，请取消选中该复选框。

1. 在**刷新令牌轮换宽限期**下，输入要设置为撤销轮换刷新令牌之前的延迟时间（最多 60 秒）。

------
#### [ Enable refresh token rotation (API) ]

在[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)或 [UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)API 请求中配置刷新令牌轮换。以下部分请求正文用于开启刷新令牌轮换并将宽限期设置为十秒。

```
"RefreshTokenRotation" : {
   "Feature" : "ENABLED,
   "RetryGracePeriodSeconds" : 10
}
```

------

## API 和 SDK 令牌刷新
<a name="using-the-refresh-token-api"></a>

可通过两种方法使用刷新令牌通过用户池 API 获取新 ID 令牌和访问令牌，具体取决于刷新令牌轮换是否已启用。在启用刷新令牌轮换的应用程序客户端中，使用 [GetTokensFromRefreshToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetTokensFromRefreshToken.html)API 操作。在没有刷新令牌轮换的应用程序客户端中，使用[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)API 操作`REFRESH_TOKEN_AUTH`流程。

**注意**  
用户可以在[托管登录](cognito-user-pools-managed-login.md)或使用您构建的自定义应用程序 AWS SDKs 和 Amazon Cognito API 操作中使用用户池进行身份验证。`REFRESH_TOKEN_AUTH` 流程和 `GetTokensFromRefreshToken` 都可以为托管登录用户完成令牌刷新。自定义应用程序中的令牌刷新不会影响托管登录会话。这些会话是在浏览器 Cookie 中设置的，有效期为 1 小时。`GetTokensFromRefreshToken` 响应会发出新的 ID 令牌、访问令牌、可选刷新令牌，但不会续订托管登录会话 Cookie。  
`REFRESH_TOKEN_AUTH` 在启用刷新令牌轮换的应用程序客户端中不可用。

------
#### [ GetTokensFromRefreshToken ]

[GetTokensFromRefreshToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetTokensFromRefreshToken.html)返回您使用刷新令牌授权的请求中的新 ID、访问和刷新令牌。以下是 `GetTokensFromRefreshToken` 的一个请求正文示例。您可以通过此操作发起的请求，向 Lambda 触发器提交客户端元数据。

```
{
    "RefreshToken": "eyJjd123abcEXAMPLE",
    "ClientId": "1example23456789",
    "ClientSecret": "myappclientsecret123abc",
    "ClientMetadata": { 
      "MyMetadataKey" : "MyMetadataValue" 
   },
}
```

------
#### [ AdminInitiateAuth/InitiateAuth ]

要在刷新令牌轮换处于非活动状态时使用刷新令牌，请使用[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)API 操作。为 `AuthFlow` 参数传递 `REFRESH_TOKEN_AUTH`。在 `AuthFlow` 的 `AuthParameters` 属性中，将用户的刷新令牌作为 `"REFRESH_TOKEN"` 的值进行传递。在您的 API 请求通过所有质询后，Amazon Cognito 会返回新的 ID 和访问令牌。

以下是使用 `InitiateAuth` 或 `AdminInitiateAuth` API 刷新令牌的请求正文示例。

```
{
    "AuthFlow": "REFRESH_TOKEN_AUTH",
    "ClientId": "1example23456789",
    "UserPoolId": "us-west-2_EXAMPLE",
    "AuthParameters": {
        "REFRESH_TOKEN": "eyJjd123abcEXAMPLE",
        "SECRET_HASH": "kT5acwCVrbD6JexhW3EQwnRSe6fLuPTRkEQ50athqv8="
    }
}
```

------

## OAuth 令牌刷新
<a name="using-the-refresh-token-oauth"></a>

您也可以将刷新令牌提交给用户池中您在其中配置了域的[令牌端点](token-endpoint.md)。在请求正文中，加入 `refresh_token` 的 `grant_type` 值和用户刷新令牌的 `refresh_token` 值。

可在启用和未启用刷新令牌轮换的应用程序客户端向令牌端点发出请求。当刷新令牌轮换启用时，令牌端点会返回一个新的刷新令牌。

以下是刷新令牌的一个请求示例。

```
POST /oauth2/token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZGpjOTh1M2ppZWRtaTI4M2V1OTI4OmFiY2RlZjAxMjM0NTY3ODkw
Content-Length: **

client_id=1example23456789&grant_type=refresh_token&refresh_token=eyJjd123abcEXAMPLE
```

## 撤消刷新令牌
<a name="amazon-cognito-identity-user-pools-revoking-all-tokens-for-user"></a>

您可以撤销属于用户的刷新令牌。有关撤销令牌的更多信息，请参阅[通过令牌撤销来结束用户会话](token-revocation.md)。

**注意**  
撤销刷新令牌将撤销 Amazon Cognito 从具有该令牌的刷新请求中发出的所有 ID 和访问令牌。

要让用户退出当前所有登录会话，请使用或 API 请求撤消其所有令牌。[GlobalSignOut[AdminUserGlobalSignOut](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUserGlobalSignOut.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html)注销用户后，会发生以下影响。
+ 用户的刷新令牌无法获取该用户的新令牌。
+ 用户的访问令牌无法发出经过令牌授权的 API 请求。
+ 用户必须重新进行身份验证以获取新的令牌。由于托管登录会话 Cookie 不会自动过期，因此，用户可以使用会话 Cookie 重新进行身份验证，而无需额外提示输入凭证。注销托管登录用户后，会将这些用户重定向到[注销端点](logout-endpoint.md)，Amazon Cognito 将在其中清除用户的会话 Cookie。

使用刷新令牌，您可以将用户的会话长时间保留在您的应用程序中。随着时间推移，您的用户可能希望取消对他们使用刷新令牌保持登录状态的某些应用程序的授权。要将您的用户从单个会话注销，请撤销其刷新令牌。当您的用户想要退出所有经过身份验证的会话时，请生成 [GlobalSignOut](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html)API 请求。应用程序可以为用户提供一个选择，如**从所有设备注销**。`GlobalSignOut` 接受用户的有效（即未更改、未过期、未撤销的）访问令牌。由于此 API 经过令牌授权，因此一个用户无法使用它来发起另一个用户的注销。

但是，您可以生成一个 [AdminUserGlobalSignOut](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUserGlobalSignOut.html)API 请求，该请求由您使用您的 AWS 凭据进行授权，以便将任何用户从其所有设备上注销。管理员应用程序必须使用 AWS 开发者凭据调用此 API 操作，并将用户池 ID 和用户名作为参数传递。`AdminUserGlobalSignOut` API 可以在用户池中注销任何用户。

有关您可以使用 AWS 凭证或用户访问令牌授权的请求的更多信息，请参阅[按授权模型分组的 API 操作列表](authentication-flows-public-server-side.md#user-pool-apis-auth-unauth)。

# 通过令牌撤销来结束用户会话
<a name="token-revocation"></a>

您可以使用以下方法撤销刷新令牌和最终用户会话。撤销刷新令牌后，先前由该刷新令牌颁发的所有访问令牌都将失效。向用户颁发的其他刷新令牌不受影响。

**RevokeToken 操作**  
[RevokeToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html)撤消给定刷新令牌的所有访问令牌，包括来自交互式登录的初始访问令牌。此操作不会影响用户的任何其他刷新令牌，也不会影响由这些其他刷新令牌派生的 ID 令牌和访问令牌。

**撤销端点**  
[撤销端点](revocation-endpoint.md)会撤销给定的刷新令牌以及该刷新令牌生成的所有 ID 令牌和访问令牌。此端点还会撤销交互式登录的初始访问令牌。对此端点的请求不会影响用户的任何其他刷新令牌，也不会影响由这些其他刷新令牌派生的 ID 令牌和访问令牌。

**GlobalSignOut 操作**  
[GlobalSignOut](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html)是一种自助操作，用户使用其访问令牌对其进行授权。此操作会撤销请求用户的所有刷新、ID 和访问令牌。

**AdminUserGlobalSignOut 操作**  
[AdminUserGlobalSignOut](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUserGlobalSignOut.html)是管理员使用 IAM 凭证授权的服务器端操作。此操作会撤销目标用户的所有刷新、ID 和访问令牌。

**有关撤销令牌的需知信息**
+ 您撤销刷新令牌的请求必须包括用于获取该令牌的客户端 ID。
+ 用户池 JWTs 是独立的，其签名和到期时间是在创建令牌时分配的。已撤销令牌无法与任何需要令牌的 Amazon Cognito API 调用一起使用。但是，如果使用任何验证令牌签名和过期的 JWT 库进行验证，已撤销令牌仍然有效。
+ 当您创建新的用户池客户端时，默认会启用令牌撤销。
+ 您只能在启用令牌撤销的应用程序客户端中撤销刷新令牌。
+ 启用令牌吊销后，Amazon Cognito JSON Web 令牌中会添加新的声明。`origin_jti` 和 `jti` 声明已添加到访问和 ID 令牌中。这些声明增加应用程序客户端访问和 ID 令牌的大小。
+ 当您在之前已启用令牌撤销的应用程序客户端中禁用令牌撤销时，已撤销的令牌不会再次启用。
+ 当您[禁用用户账户](how-to-manage-user-accounts.md#manage-user-accounts-enable-disable)（会撤销刷新和访问令牌）后，如果您再次启用该用户账户，已撤销的令牌不会启用。
+ 使用 AWS 管理控制台、或 AWS API 创建新的用户池客户端时 AWS CLI，默认情况下会启用令牌撤销。

## 启用令牌撤销
<a name="enable-token-revocation"></a>

在您为现有的用户池客户端撤销令牌前，必须启用令牌撤销。您可以使用 AWS CLI 或 AWS API 为现有用户池客户端启用令牌撤销。为此，请调用 `aws cognito-idp describe-user-pool-client` CLI 命令或 `DescribeUserPoolClient` API 操作以从应用程序客户端检索当前设置。然后调用 `aws cognito-idp update-user-pool-client` CLI 命令或 `UpdateUserPoolClient` API 操作。包括来自您的应用程序客户端的当前设置并将 `EnableTokenRevocation` 参数设置为 `true`。

要使用 Amazon Cognito API 或软件开发工具包创建或修改启用令牌撤销功能的 AWS 应用程序客户端，请在[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)您的[UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)或 API 请求中包含以下参数。

```
"EnableTokenRevocation": true
```

要在 Amazon Cognito 控制台中配置令牌撤销，请从用户池的**应用程序客户端**菜单中选择一个应用程序客户端。在**应用程序客户端信息**中选择**编辑**按钮，然后在**高级配置**下启用或禁用令牌撤销。

## 撤销令牌
<a name="revoke-tokens-api"></a>

您可以使用 [RevokeToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html)API 请求撤消刷新令牌，例如使用 `[aws cognito-idp revoke-token](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/revoke-token.html)` CLI 命令。您也可以使用[撤销端点](revocation-endpoint.md)撤销令牌。此端点在您将域添加到用户池后可用。您可以在 Amazon Cognito 托管域或您的自定义域上使用撤销端点。

以下是示例 `RevokeToken` API 请求的正文。

```
{
   "ClientId": "1example23456789",
   "ClientSecret": "abcdef123456789ghijklexample",
   "Token": "eyJjdHkiOiJKV1QiEXAMPLE"
}
```

以下是对使用自定义域的用户池的 `/oauth2/revoke` 端点发出的 cURL 请求示例。

```
curl --location 'auth.mydomain.com/oauth2/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic Base64Encode(client_id:client_secret)' \
--data-urlencode 'token=abcdef123456789ghijklexample' \
--data-urlencode 'client_id=1example23456789'
```

除非您的应用程序客户端具有客户端密钥，否则 `RevokeToken` 操作和 `/oauth2/revoke` 端点不需要额外授权。

# 验证 JSON Web 令牌
<a name="amazon-cognito-user-pools-using-tokens-verifying-a-jwt"></a>

JSON 网络令牌 (JWTs) 可以轻松解码、读取和修改。修改过的访问令牌会带来权限提升的风险。修改过的 ID 令牌会带来冒充身份的风险。您的应用程序信任您的用户池作为令牌颁发者，但如果用户拦截了传输中的令牌，该怎么办？ 您必须确保应用程序收到的令牌与 Amazon Cognito 颁发的令牌一致。

Amazon Cognito 颁发令牌，这些令牌使用 OpenID Connect（OIDC）规范的某些完整性和保密性特征。用户池令牌通过到期时间、颁发者和数字签名等对象来指示令牌的有效性。签名（`.` 分隔的 JWT 的第三个也是最后一个分段）是令牌验证的关键组件。恶意用户会修改令牌，但如果您的应用程序检索公钥并比较签名，则该令牌将不匹配。任何通过 OIDC 身份验证进行处理 JWTs 的应用程序都必须在每次登录时执行此验证操作。

在本页上，我们提出了一些一般和具体的验证建议 JWTs。在应用程序开发过程中，开发人员需要使用各种编程语言和平台。由于 Amazon Cognito 实施的 OIDC 足够接近公共规范，因此选择开发人员环境中任何声誉良好的 JWT 库都可以满足您的验证要求。

这些步骤描述了验证用户池 JSON Web 令牌（JWT）的过程。

**Topics**
+ [先决条件](#amazon-cognito-user-pools-using-tokens-prerequisites)
+ [使用验证令牌 aws-jwt-verify](#amazon-cognito-user-pools-using-tokens-aws-jwt-verify)
+ [了解和检查令牌](#amazon-cognito-user-pools-using-tokens-manually-inspect)

## 先决条件
<a name="amazon-cognito-user-pools-using-tokens-prerequisites"></a>

您的库、SDK 或软件框架可能已经处理了本节中的任务。 AWS SDKs 为应用程序中的 Amazon Cognito 用户池令牌处理和管理提供工具。 AWS Amplify 包括检索和刷新 Amazon Cognito 令牌的功能。

有关更多信息，请参阅以下页面。
+ [将 Amazon Cognito 身份验证和授权与 Web 和移动应用程序集成](cognito-integrate-apps.md)
+ [使用 Amazon Cognito 身份提供商的代码示例 AWS SDKs](https://docs.aws.amazon.com/cognito/latest/developerguide/service_code_examples.html)
+ *Amplify Dev Center*（Amplify 开发中心）中的 [Advanced workflows](https://docs.amplify.aws/lib/auth/advanced/q/platform/js/#retrieve-jwt-tokens)（高级工作流）

许多库可用于解码和验证 JSON Web 令牌 (JWT)。如果您要手动处理用于服务器端 API 处理的令牌，或者您使用的是其他编程语言，则这些库可以为您提供帮助。请参阅[用于处理 JWT 令牌库的 OpenID Foundation 列表](http://openid.net/developers/jwt/)。

## 使用验证令牌 aws-jwt-verify
<a name="amazon-cognito-user-pools-using-tokens-aws-jwt-verify"></a>

在 Node.js 应用程序中， AWS 建议使用该[aws-jwt-verify库](https://github.com/awslabs/aws-jwt-verify)来验证用户传递给您的应用程序的令牌中的参数。使用 `aws-jwt-verify`，您可以使用要为一个或多个用户池验证的声明值填充 `CognitoJwtVerifier`。它可以检查的一些值包括以下内容。
+ 该访问令牌或 ID 令牌的格式不正确或已过期，但具有有效的签名。
+ 这些访问令牌来自[正确的用户池和应用程序客户端](https://github.com/awslabs/aws-jwt-verify#verifying-jwts-from-amazon-cognito)。
+ 该访问令牌声明包含[正确的 OAuth 2.0 范围](https://github.com/awslabs/aws-jwt-verify#checking-scope)。
+ 对访问令牌和 ID 令牌进行签名的密钥[与用户池的 *JWKS URI* 中的签名密钥 `kid` 匹配](https://github.com/awslabs/aws-jwt-verify#the-jwks-cache)。

  JWKS URI 包含有关对用户令牌进行签名的私有密钥的公有信息。您可以在以下位置找到用户池的 JWKS URI：`https://cognito-idp.<Region>.amazonaws.com/<userPoolId>/.well-known/jwks.json`。

有关您可以在 Node.js 应用程序或 AWS Lambda 授权方中使用的更多信息和示例代码，请参阅[https://github.com/awslabs/aws-jwt-verify](https://github.com/awslabs/aws-jwt-verify)上 GitHub的。

## 了解和检查令牌
<a name="amazon-cognito-user-pools-using-tokens-manually-inspect"></a>

在将令牌检查与应用程序集成之前，请考虑一下 Amazon Cognito 是如何组装的。 JWTs从用户池中检索示例令牌。解码并详细检查它们，以了解它们的特征，并确定要验证的内容和时间。例如，您可能希望检查一个场景中的组成员资格，而在另一个场景中，您可能想要检查作用域。

以下各节描述了在准备应用程序时手动检查 Amazon Cognito JWTs 的过程。

### 确认 JWT 的结构
<a name="amazon-cognito-user-pools-using-tokens-step-1"></a>

JSON Web 令牌 (JWT) 包括三个部分，各部分之间有一个 `.`（圆点）分隔符。

**标题**  
Amazon Cognito 用来对令牌进行签名的密钥 ID `kid` 和 RSA 算法 `alg`。Amazon Cognito 使用 `alg` (`RS256`) 对令牌进行签名。`kid` 是对您的用户池持有的 2048 位 RSA 私有签名密钥的截断引用。

**有效载荷**  
令牌声明。在 ID 令牌中，声明包括用户属性和有关用户池 `iss` 和应用程序客户端 `aud` 的信息。在访问令牌中，有效载荷包括作用域、组成员资格、用户池身份 (`iss`) 和应用程序客户端 (`client_id`)。

**签名**  
签名不是像标头和有效载荷那样的可解码 base64url。它是从签名密钥和参数派生的 RSA256 标识符，您可以在 JWKS URI 中观察到这些标识符。

标头和有效载荷是以 base64url 编码的 JSON。您可以通过解码为起始字符 `eyJ` 的开头字符 `{` 来识别它们。如果用户向您的应用程序提供了以 base64url 编码的 JWT，但其格式不是 `[JSON Header].[JSON Payload].[Signature]`，则它不是有效的 Amazon Cognito 令牌，您可以将其丢弃。

以下示例应用程序使用 `aws-jwt-verify` 验证用户池令牌。

```
// cognito-verify.js
// Usage example: node cognito-verify.js eyJra789ghiEXAMPLE

const { CognitoJwtVerifier } = require('aws-jwt-verify');

// Replace with your Amazon Cognito user pool ID
const userPoolId = 'us-west-2_EXAMPLE';

async function verifyJWT(token) {
  try {
    const verifier = CognitoJwtVerifier.create({
      userPoolId,
      tokenUse: 'access', // or 'id' for ID tokens
      clientId: '1example23456789', // Optional, only if you need to verify the token audience
    });

    const payload = await verifier.verify(token);
    console.log('Decoded JWT:', payload);
  } catch (err) {
    console.error('Error verifying JWT:', err);
  }
}

// Example usage
if (process.argv.length < 3) {
  console.error('Please provide a JWT token as an argument.');
  process.exit(1);
}

const MyToken = process.argv[2];
verifyJWT(MyToken);
```

### 验证 JWT
<a name="amazon-cognito-user-pools-using-tokens-step-2"></a>

JWT 签名是标头和负载的哈希组合。Amazon Cognito 为每个用户池生成两对 RSA 加密密钥。一个私有密钥对访问令牌进行签名，另一个私有密钥对 ID 令牌进行签名。

**验证 JWT 令牌的签名**

1. 解码 ID 令牌。

   OpenID Foundation 还[维护用于处理 JWT 令牌的库列表](http://openid.net/developers/jwt/)。

   您也可以使用 AWS Lambda 解码用户池 JWTs。有关更多信息，请参阅使用[解码和验证 Amazon Cognito J](https://github.com/awslabs/aws-support-tools/tree/master/Cognito/decode-verify-jwt) WT 令牌。 AWS Lambda

1. 将本地密钥 ID (`kid`) 与公有 `kid` 进行比较。

   1. 下载并存储适用于用户池的对应的公有 JSON Web Key（JWK）。它可作为 JSON Web Key Set (JWKS) 的一部分提供。您可以通过为您的环境构建以下 `jwks_uri` URL 来找到它：

      ```
      https://cognito-idp.<Region>.amazonaws.com/<userPoolId>/.well-known/jwks.json
      ```

      有关更多 JWK 和 JWK 集的更多信息，请参阅 [JSON Web Key (JWK)](https://tools.ietf.org/html/rfc7517)。
**注意**  
Amazon Cognito 可能会轮换用户池中的签名密钥。最佳做法是使用 `kid` 作为缓存密钥在应用程序中缓存公有密钥，并定期刷新缓存。将您的应用程序收到的令牌中的 `kid` 与缓存进行比较。  
如果您收到的令牌的颁发者是正确的，但 `kid` 不同，则 Amazon Cognito 可能已经轮换了签名密钥。从您的用户池 `jwks_uri` 端点刷新缓存。

      这是个 `jwks.json` 文件示例：

      ```
      {
      	"keys": [{
      		"kid": "1234example=",
      		"alg": "RS256",
      		"kty": "RSA",
      		"e": "AQAB",
      		"n": "1234567890",
      		"use": "sig"
      	}, {
      		"kid": "5678example=",
      		"alg": "RS256",
      		"kty": "RSA",
      		"e": "AQAB",
      		"n": "987654321",
      		"use": "sig"
      	}]
      }
      ```  
**密钥 ID（`kid`）**  
`kid` 是一个提示，指示哪个密钥用于保护令牌的 JSON Web 签名（JWS）。  
**算法（`alg`）**  
`alg` 标头参数表示用于保护 ID 令牌的加密算法。用户池使用 RS256加密算法，即带有 SHA-256 的 RSA 签名。有关 RSA 的更多信息，请参阅 [RSA 加密](https://tools.ietf.org/html/rfc3447)。  
**密钥类型（`kty`）**  
`kty` 参数标识与密钥结合使用的加密算法系列，例如，在本示例中为“RSA”。  
**RSA 指数（`e`）**  
`e` 参数包含 RSA 公有密钥的指数值。它以 base64URL UInt 编码的值表示。  
**RSA 模数（`n`）**  
`n` 参数包含 RSA 公有密钥的模数值。它以 base64URL UInt 编码的值表示。  
**使用（`use`）**  
`use` 参数描述了公有密钥的预期用途。在本示例中，`use` 值 `sig` 表示签名。

   1. 搜索与您 JWT 的 `kid` 相匹配的 `kid` 的公有 JSON Web 密钥。

### 验证声明
<a name="amazon-cognito-user-pools-using-tokens-step-3"></a>

**验证 JWT 声明**

1. 通过以下方法之一，验证令牌是否未过期。

   1. 对令牌解码并将 `exp` 声明与当前时间进行比较。

   1. 如果您的访问令牌包含`aws.cognito.signin.user.admin`索赔，请向类似的 API 发送请求[GetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html)。如果令牌已过期，您[使用访问令牌进行授权](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pools-API-operations.html#user-pool-apis-auth-unauth)的 API 请求会返回错误。

   1. 在针对[userInfo 端点](userinfo-endpoint.md)的请求中提供您的访问令牌。如果您的令牌已过期，则请求会返回错误。

1. ID 令牌中的 `aud` 声明和访问令牌中的 `client_id` 声明应与在 Amazon Cognito 用户池中创建的应用程序客户端 ID 匹配。

1. 发布者 (`iss`) 声明应与您的用户池匹配。例如，在 `us-east-1` 区域中创建的用户池将有下列 `iss` 值：

   `https://cognito-idp.us-east-1.amazonaws.com/<userpoolID>`.

1. 检查 `token_use` 声明。
   + 如果您在 Web API 操作中只接受访问令牌，则其值必须为 `access`。
   + 如果您只使用 ID 令牌，则其值必须为 `id`。
   + 如果您同时使用 ID 令牌和访问令牌，则 `token_use` 声明必须为 `id` 或 `access`。

您现在可以信任该令牌内的声明。

# 管理用户池令牌到期和缓存
<a name="amazon-cognito-user-pools-using-tokens-caching-tokens"></a>

每次您想要获取新的 JSON Web 令牌（JWT）时，应用程序都必须成功完成以下请求之一。
+ 从[令牌端点](token-endpoint.md)请求客户端凭证或授权码[授予](https://www.rfc-editor.org/rfc/rfc6749#section-1.3)。
+ 从您的托管登录页面请求隐式授权。
+ 在 Amazon Cognito API 请求中对本地用户进行身份验证，例如。[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)

您可以将用户池配置为将令牌设置为在数分钟、数小时或数天后过期。要确保应用程序的性能和可用性，请使用 Amazon Cognito 令牌至大约 75% 的令牌生命周期，并且仅在那时获取新令牌。您为应用程序构建的缓存解决方案可保持令牌可用，并可防止 Amazon Cognito 在您的请求速率过高时拒绝请求。客户端应用程序必须将令牌存储在内存缓存中。服务器端应用程序可以添加加密的缓存机制来存储令牌。

当您的用户池生成大量用户或 machine-to-machine活动时，您可能会遇到 Amazon Cognito 对您可以发出的令牌请求数量设定的限制。要减少您向 Amazon Cognito 端点发出的请求数量，可以安全地存储和重复使用身份验证数据，也可以实施指数回退和重试。

身份验证数据来自两类端点。Amazon Cognito [OAuth2.0 终端](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html)节点包括令牌终端节点，该终端节点为客户端凭证和托管登录授权码请求提供服务。[服务端点](https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html#cognito_identity_your_user_pools_region)应答用户池 API 请求，例如 `InitiateAuth` 和 `RespondToAuthChallenge`。每种类型的请求都有自己的限制。有关限制的更多信息，请参阅[Amazon Cognito 中的限额](quotas.md)。

## 使用 Amazon API Gateway 缓存 machine-to-machine访问令牌
<a name="amazon-cognito-user-pools-using-tokens-caching-tokens-API-gateway"></a>

借助 API Gateway 令牌缓存，您的应用程序可以扩展以响应大于 Amazon Cognito OAuth 终端节点默认请求速率配额的事件。

![\[API Gateway 为 M2M 维护访问令牌缓存的示意图。API 代理处理令牌请求，如果已经有一个缓存的令牌有效，则返回缓存的令牌。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/user-pools-m2m-caching.png)


您可以缓存访问令牌，以便您的应用程序仅在缓存的令牌过期时才请求新的访问令牌。否则，您的缓存端点会从缓存中返回一个令牌。这会阻止对 Amazon Cognito API 端点的其他调用。当您使用 Amazon API Gateway 作为 [令牌端点](token-endpoint.md)的代理时，您的 API 会响应大多数原本会计入您的请求配额的请求，从而避免由于速率限制而导致的请求失败。

以下基于 API Gateway 的解决方案提供了低延迟、低代码/无代码的令牌缓存实施。API Gateway APIs 在传输过程中进行加密，也可以选择静态加密。API Gateway 缓存非常适合 OAuth 2.0 [客户端凭证授予](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4)，这是一种通常是大批量的授予类型，用于生成用于授权 machine-to-machine和微服务会话的访问令牌。在诸如流量激增导致您的微服务水平扩展的情况下，您最终可能会有许多系统使用相同的客户端凭据，但其数量超过用户池或应用程序客户端的 AWS 请求速率限制。要保持应用程序可用性和低延迟，缓存解决方案是此类情况下的最佳实践。

在此解决方案中，您可以在 API 中定义一个缓存，以便为要在应用中请求的 OAuth 范围和应用程序客户端的每种组合存储单独的访问令牌。当您的应用程序发出与缓存键匹配的请求时，您的 API 会使用 Amazon Cognito 向与缓存键匹配的第一个请求颁发的访问令牌进行响应。当您的缓存键持续时间到期时，API 会将请求转发到令牌端点并缓存新的访问令牌。

**注意**  
您的缓存键持续时间必须短于应用程序客户端的访问令牌持续时间。

缓存密钥是您在请求正文`scope`参数中请求的 OAuth 作用域和请求`Authorization`标头的组合。`Authorization` 标头包含您的应用程序客户端 ID 和客户端密钥。您无需在应用程序中实施其他逻辑即可实施此解决方案。您只必须更新配置以更改用户池令牌端点的路径。

您也可以使用 [ElastiCache (Redis OSS)](https://docs.aws.amazon.com/elasticache/index.html) 实现令牌缓存。要使用 AWS Identity and Access Management (IAM) 策略进行精细控制，请考虑 [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/authentication-and-access-control.html#authentication) 缓存。

**注意**  
在 API Gateway 中缓存需要支付额外费用。[有关更多详细信息，请参阅定价。](https://aws.amazon.com/api-gateway/pricing)<a name="amazon-cognito-user-pools-using-tokens-caching-tokens-API-gateway-how-to"></a>

**使用 API Gateway 设置缓存代理**

1. 打开 [API Gateway 控制台](https://console.aws.amazon.com/apigateway/main/apis)，然后创建一个 REST API。

1. 在 **Resources**（资源）中，创建一个 POST 方法。

   1. 选择 HTTP **Integration type**（集成类型）。

   1. 选择 **Use HTTP proxy integration**（使用 HTTP 代理集成）。

   1. 输入 **Endpoint URL**（端点 URL）`https://<your user pool domain>/oauth2/token`。

1. 在 **Resources**（资源）中，配置缓存键。

   1. 编辑 POST 方法的 **Method request**（方法请求）。
**注意**  
此方法请求验证用于令牌请求中的 `client_secret_basic` 授权，其中客户端密钥被编码在 `Authorization` 请求标头中。对于使用 `client_secret_post` 授权方式对 JSON 请求正文的验证，应创建一个[数据模型](https://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings-models.html)，明确要求请求正文中必须包含 [client\$1secret](token-endpoint.md#post-token-request-parameters-in-body)。在此模型中，您的**请求验证程序**应**验证正文、查询字符串参数和标头**。

   1. 配置**请求验证程序**方法以**验证查询字符串参数和标头**。有关请求验证的更多信息，请参阅 *Amazon API Gateway 开发者指南*中的[请求验证](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-method-request-validation.html)。

   1. 将您的 `scope` 参数和 `Authorization` 标头设置为缓存键。

      1. 将一个查询字符串添加到 **URL 查询字符串参数**。输入 `scope` 作为查询字符串的**名称**，然后选择**必填项**和**缓存**。

      1. 将一个标头添加到 **HTTP 请求标头**。输入 `Authorization` 作为请求标头的**名称**，然后选择**必填项**和**缓存**。

1. 在 **Stages**（阶段）中，配置缓存。

   1. 选择要修改的阶段，然后从**阶段详细信息**中选择**编辑**。

   1. 在**其他设置**下，对于**缓存设置**，开启**配置 API 缓存**选项。

   1. 选择 **Cache capacity**（缓存容量）。较高的缓存容量可以提高性能，但需要额外付费。

   1. 清除**需要授权**复选框。选择**继续**。

   1. API Gateway 仅将缓存策略应用于阶段级别的 GET 方法。您必须对 POST 方法应用缓存策略覆盖。

      展开您配置的阶段并选择 `POST` 方法。要为该方法创建缓存设置，请选择**创建覆盖**。

   1. 激活**启用方法缓存**选项。

   1. 输入 3600 秒的****缓存 time-to-live (TTL)****。选择**保存**。

1. 在 **Stages**（阶段）中，注意 **Invoke URL**（调用 URL）。

1. 更新您的应用程序，以将令牌请求发布到 API 的 **Invoke URL**（调用 URL）而不是用户池的 `/oauth2/token` 端点。

# 在成功登录后访问资源
<a name="accessing-resources"></a>

您的应用程序用户可以通过用户池直接登录，也可以通过第三方身份提供者（IdP）进行联合身份验证。用户池管理处理通过Facebook、谷歌、亚马逊和苹果进行社交登录以及从OpenID Connect（OIDC）和SAML返回的代币的开销。 IdPs有关更多信息，请参阅 [了解用户池 JSON 网络令牌 (JWTs)](amazon-cognito-user-pools-using-tokens-with-identity-providers.md)。

成功进行身份验证后，您的应用程序将收到来自 Amazon Cognito 的用户池令牌。您可以使用用户池令牌来完成以下操作：
+ 在 Amazon DynamoDB 和 Amazon S3 AWS 服务 等中检索授权应用程序资源请求的 AWS 证书。
+ 提供临时、可撤销的身份验证证明。
+ 将身份数据填入到应用程序中的用户配置文件中。
+ 授权对已登录用户在用户池目录中的配置文件进行更改。
+ 使用访问令牌授权对用户信息的请求。
+ 使用访问令牌授权对位于受访问保护的外部 APIs 数据之后的请求。
+ 使用 Amazon Verified Permissions 授权对存储在客户端或服务器上的应用程序资产的访问。

有关更多信息，请参阅[身份验证会话示例](authentication.md#amazon-cognito-user-pools-authentication-flow)和[了解用户池 JSON 网络令牌 (JWTs)](amazon-cognito-user-pools-using-tokens-with-identity-providers.md)。

![\[身份验证概述。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/scenario-authentication-cup.png)


**Topics**
+ [使用 Amazon Verified Permissions 授权对客户端或服务器资源的访问。](scenario-backend.md)
+ [在登录后使用 API Gateway 访问资源](user-pool-accessing-resources-api-gateway-and-lambda.md)
+ [登录后 AWS 服务 使用身份池进行访问](amazon-cognito-integrating-user-pools-with-identity-pools.md)

# 使用 Amazon Verified Permissions 授权对客户端或服务器资源的访问。
<a name="scenario-backend"></a>

您的应用程序可以将已登录用户的令牌传递给 [Amazon Verified Permissions](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/what-is-avp.html)。Verified Permissions 是一项可扩展、精细的权限管理和授权服务，适用于您构建的应用程序。Amazon Cognito 用户池可以作为 Verified Permissions 策略存储的身份源。Verified Permissions 会根据用户池令牌中的主体及其属性对请求的操作和资源（例如 `premium_badge.png` 的 `GetPhoto`）作出授权决策。

下图显示了您的应用程序如何在授权请求中将用户的令牌传递给 Verified Permissions。

![\[一个应用程序的流程图，该应用程序使用 Amazon Cognito 用户池进行身份验证，并使用 Amazon Verified Permissions 授权访问本地资源。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/access-services-local-resources.png)


**Amazon Verified Permissions 入门**  
将用户池与 Verified Permissions 集成后，您可以集中管理所有 Amazon Cognito 应用程序的精细授权。这样就不需要在所有应用程序中重复编写和复制精细安全逻辑。有关使用 Verified Permissions 进行授权的更多信息，请参阅[使用 Amazon Verified Permissions 进行授权](amazon-cognito-authorization-with-avp.md)。

已验证的权限授权请求需要 AWS 凭证。您可以实施以下一些技术来安全地将凭证应用于授权请求。
+ 操作可以在服务器后端存储密钥的 Web 应用程序。
+ 获取经过身份验证的身份池凭证。
+ 通过 access-token-authorized API 代理用户请求，并将 AWS 凭据附加到请求中。

# 在登录后使用 API Gateway 访问资源
<a name="user-pool-accessing-resources-api-gateway-and-lambda"></a>

Amazon Cognito 用户池令牌的常见用途是授权向 [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html) 发出的请求。访问令牌中的 OAuth 2.0 作用域可以对方法和路径进行授权，比`HTTP GET`如`/app_assets`。ID 令牌可以用作 API 的通用身份验证，也可以将用户属性传递给后端服务。API Gateway 还有其他自定义授权选项，例如[适用于 HTTP 的 JWT 授权](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html)方和 APIs Lambda [授权者，它们可以应用更精细](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html)的逻辑。

下图说明了访问令牌中具有 OAuth 2.0 范围的 REST API 的应用程序。

![\[一个应用程序的流程图，该应用程序使用 Amazon Cognito 用户池进行身份验证，并使用 Amazon API Gateway 授权访问 API 资源。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/access-services-api-gateway.png)


您的应用程序必须从经过身份验证的会话中收集令牌，并将其作为持有者令牌添加到请求中的 `Authorization` 标头。配置您为用于评估令牌内容的 API、路径和方法配置的授权方。仅当请求符合您为授权方设置的条件时，API Gateway 才会返回数据。

API Gateway API 可以通过以下一些方法来批准来自应用程序的访问：
+ 访问令牌有效，未过期，并且包含正确的 OAuth 2.0 范围。[适用于 REST API 的 Amazon Cognito 用户池授权方](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html)是一种常见的实现，进入门槛很低。您还可以评估向此类授权方发出的请求的正文、查询字符串和标头。
+ ID 令牌有效且未过期。当您将 ID 令牌传递给 Amazon Cognito 授权方时，您可以在应用程序服务器上对 ID 令牌内容进行额外验证。
+ 访问令牌或 ID 令牌中的组、声明、属性或角色符合您在 Lambda 函数中定义的要求。[Lambda 授权方](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html)解析请求标头中的令牌，并对其进行评估以作出授权决策。您可以在函数中构造自定义逻辑，也可以向 [Amazon Verified Permissions](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/what-is-avp.html) 发出 API 请求。

您还可以使用来自用户池的令牌来授权向 [AWS AppSync GraphQL API](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#amazon-cognito-user-pools-authorization) 发出的请求。

# 登录后 AWS 服务 使用身份池进行访问
<a name="amazon-cognito-integrating-user-pools-with-identity-pools"></a>

用户使用用户池登录后，他们可以使用身份池颁发的临时 API 凭证进行访问 AWS 服务 。

您的 Web 应用程序或移动应用程序接收来自用户池的令牌。当您将用户池配置为身份池的身份提供者时，身份池会用令牌交换临时 AWS 证书。这些证书的范围可以限于 IAM 角色及其策略，这些策略允许用户访问有限的 AWS 资源。有关更多信息，请参阅 [身份池身份验证流程](authentication-flow.md)。

下图显示了应用程序如何使用用户池登录、检索身份池凭证以及如何从 AWS 服务请求资产。

![\[使用 Amazon Cognito 用户池进行身份验证并使用身份池授权 AWS 访问资源的应用程序流程图。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/access-services-identity-pool.png)


您可以使用身份池凭证来完成以下操作：
+ 使用用户自己的凭证向 Amazon Verified Permissions 提出精细的授权请求。
+ 连接到 Amazon API Gateway REST API 或授权与 IAM 连接的 AWS AppSync GraphQL API。
+ 连接到使用 IAM 授权连接的数据库后端，例如 Amazon DynamoDB 或 Amazon RDS。
+ 从 Amazon S3 存储桶检索应用程序资产。
+ 使用 Amazon WorkSpaces 虚拟桌面启动会话。

身份池不仅在经过用户池认证的会话中运行。它们还直接接受来自第三方身份提供者的身份验证，并且可为未经身份验证的访客用户生成凭证。

有关使用身份池和用户池组来控制对 AWS 资源的访问的更多信息，请参阅[向用户池添加组](cognito-user-pools-user-groups.md)和[使用基于角色的访问控制](role-based-access-control.md)。另外，有关身份池和的更多信息 AWS Identity and Access Management，请参阅[身份池身份验证流程](authentication-flow.md)。

## 使用设置用户池 AWS 管理控制台
<a name="amazon-cognito-integrating-user-pools-with-identity-pools-setting-up"></a>

创建 Amazon Cognito 用户池并记下每个客户端应用程序的**用户池 ID** 和**应用程序客户端 ID**。有关创建用户池的更多信息，请参阅[用户池入门](getting-started-user-pools.md)。

## 使用设置身份池 AWS 管理控制台
<a name="amazon-cognito-integrating-user-pools-with-identity-pools-configuring"></a>

以下过程介绍如何使用将 AWS 管理控制台 身份池与一个或多个用户池和客户端应用程序集成。

**添加 Amazon Cognito 用户池身份提供者 (IdP)**

1. 从 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)中选择**身份池**。选择身份池。

1. 选择**用户访问**选项卡。

1. 选择**添加身份提供者**。

1. 选择 **Amazon Cognito 用户池**。

1. 输入**用户池 ID** 和**应用程序客户端 ID**。

1. 要设置 Amazon Cognito 在向通过该提供者进行身份验证的用户颁发凭证时请求的角色，请配置**角色设置**。

   1. 您可以为该 IdP 中的用户分配您在配置**经过身份验证的角色**时设置的**原定设置角色**，也可以**使用规则选择角色**。使用 Amazon Cognito 用户池 IdP，还可以**选择令牌中包含 preferred\$1role 声明的角色**。有关 `cognito:preferred_role` 声明的更多信息，请参阅[将优先级值分配到组](cognito-user-pools-user-groups.md#assigning-precedence-values-to-groups)。

      1. 如果您选择**使用规则选择角色**，请输入用户身份验证中的来源**声明**、您要用来将声明与规则进行比较的**运算符**、导致与该角色选择匹配的**值**，以及当**角色分配**匹配时要分配的**角色**。选择**添加其他**，以根据不同的条件创建其他规则。

      1. 如果您选择**选择令牌中有 preferred\$1role 声明的角色**，Amazon Cognito 会在您的用户的 `cognito:preferred_role` 声明中为该角色发放凭证。如果不存在首选角色声明，Amazon Cognito 将根据您的**角色解析**发放凭证。

   1. 选择**角色解析**。当用户的声明与您的规则不匹配时，您可以拒绝凭证或为**经过身份验证的角色**颁发凭证。

1. 要更改 Amazon Cognito 在向通过该提供者进行身份验证的用户颁发凭证时分配的主体标签，请配置**访问控制属性**。
   + 如果不应用主体标签，请选择**非活动**。
   + 要基于 `sub` 和 `aud` 声明应用主体标签，请选择**使用原定设置映射**。
   + 要为主体标签创建自己的自定义属性模式，请选择**使用自定义映射**。然后，对于您要在标签中表示的每个**声明**，输入要从该声明中获取的**标签键**。

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

## 将用户池与身份池集成
<a name="amazon-cognito-integrating-user-pools-with-identity-pools-using"></a>

对您的应用程序用户进行身份验证后，将用户的身份令牌添加到凭证提供程序中的登录映射中。提供商名称取决于 Amazon Cognito 用户池 ID。结构如下所示：

```
cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>
```

您可以*<region>*从**用户池 ID** 中推导出值。例如，如果用户池 ID 为`us-east-1_EXAMPLE1`，则*<region>*为`us-east-1`。如果用户池 ID 为`us-west-2_EXAMPLE2`，则*<region>*为`us-west-2`。

------
#### [ JavaScript ]

```
var cognitoUser = userPool.getCurrentUser();

if (cognitoUser != null) {
	cognitoUser.getSession(function(err, result) {
		if (result) {
			console.log('You are now logged in.');

			// Add the User's Id Token to the Cognito credentials login map.
			AWS.config.credentials = new AWS.CognitoIdentityCredentials({
				IdentityPoolId: 'YOUR_IDENTITY_POOL_ID',
				Logins: {
					'cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>': result.getIdToken().getJwtToken()
				}
			});
		}
	});
}
```

------
#### [ Android ]

```
cognitoUser.getSessionInBackground(new AuthenticationHandler() {
	@Override
	public void onSuccess(CognitoUserSession session) {
		String idToken = session.getIdToken().getJWTToken();

		Map<String, String> logins = new HashMap<String, String>();
		logins.put("cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>", session.getIdToken().getJWTToken());
		credentialsProvider.setLogins(logins);
	}

});
```

------
#### [ iOS - objective-C ]

```
AWSServiceConfiguration *serviceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil];
AWSCognitoIdentityUserPoolConfiguration *userPoolConfiguration = [[AWSCognitoIdentityUserPoolConfiguration alloc] initWithClientId:@"YOUR_CLIENT_ID"  clientSecret:@"YOUR_CLIENT_SECRET" poolId:@"YOUR_USER_POOL_ID"];
[AWSCognitoIdentityUserPool registerCognitoIdentityUserPoolWithConfiguration:serviceConfiguration userPoolConfiguration:userPoolConfiguration forKey:@"UserPool"];
AWSCognitoIdentityUserPool *pool = [AWSCognitoIdentityUserPool CognitoIdentityUserPoolForKey:@"UserPool"];
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:@"YOUR_IDENTITY_POOL_ID" identityProviderManager:pool];
```

------
#### [ iOS - swift ]

```
let serviceConfiguration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: nil)
let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: "YOUR_CLIENT_ID", clientSecret: "YOUR_CLIENT_SECRET", poolId: "YOUR_USER_POOL_ID")
AWSCognitoIdentityUserPool.registerCognitoIdentityUserPoolWithConfiguration(serviceConfiguration, userPoolConfiguration: userPoolConfiguration, forKey: "UserPool")
let pool = AWSCognitoIdentityUserPool(forKey: "UserPool")
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YOUR_IDENTITY_POOL_ID", identityProviderManager:pool)
```

------

# 作用域、M2M 和资源服务器
<a name="cognito-user-pools-define-resource-servers"></a>

为用户池配置域后，Amazon Cognito 会自动配置 OAuth 2.0 授权服务器和托管 Web UI，其中包含您的应用程序可以向用户展示的注册和登录页面。有关更多信息，请参阅 [用户池托管登录](cognito-user-pools-managed-login.md)。您可以选择希望授权服务器添加到访问令牌中的范围。范围授权访问资源服务器和用户数据。

*资源服务器*是一个 OAuth 2.0 的 API 服务器。为了保护受访问权限保护的资源，它会验证用户池中的访问令牌所包含的范围是否授权所请求的方法和它所保护的 API 中的路径。它根据令牌签名验证发放者，根据令牌到期时间验证有效性，并根据令牌声明中的范围验证访问级别。用户池范围位于访问令牌 `scope` 声明中。有关 Amazon Cognito 访问令牌中的声明的更多信息，请参阅[了解访问令牌](amazon-cognito-user-pools-using-the-access-token.md)。

借助 Amazon Cognito，访问令牌中的范围可以授权访问外部属性 APIs 或用户属性。您可以向本地用户、联合用户或计算机身份发放访问令牌。

**Topics**
+ [API 授权](#cognito-user-pools-define-resource-servers-about-api-authz)
+ [Machine-to-machine (M2M) 授权](#cognito-user-pools-define-resource-servers-about-m2m)
+ [关于范围](#cognito-user-pools-define-resource-servers-about-scopes)
+ [关于资源服务器](#cognito-user-pools-define-resource-servers-about-resource-servers)
+ [资源绑定](#cognito-user-pools-resource-binding)

## API 授权
<a name="cognito-user-pools-define-resource-servers-about-api-authz"></a>

以下是您可以使用亚马逊 Cognito 令牌 APIs 授权请求的一些方法：

**访问令牌**  
将 Amazon Cognito 授权方添加到 REST API 方法请求配置时，将**授权范围**添加到授权方配置中。使用此配置，您的 API 会接受 `Authorization` 标头中的访问令牌，并检查访问令牌中的可接受范围。

**ID 令牌**  
当您在 REST API 中将有效的 ID 令牌传递给 Amazon Cognito 授权方时，API Gateway 会接受请求并将 ID 令牌内容传递给 API 后端。

**Amazon Verified Permissions**  
在 Verified Permissions 中，您可以选择创建 [API 关联策略存储](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/policy-stores_api-userpool.html)。Verified Permissions 创建并分配一个 Lambda 授权方，该授权方处理请求 `Authorization` 标头中的 ID 令牌或访问令牌。此 Lambda 授权方将您的令牌传递到策略存储，然后 Verified Permissions 将其与策略进行比较，并将向授权方返回允许或拒绝决定。

**更多资源**
+ [在 API Gateway 中控制和管理对 REST API 的访问](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-to-api.html)
+ [使用 Amazon Verified Permissions 进行授权](amazon-cognito-authorization-with-avp.md)

## Machine-to-machine (M2M) 授权
<a name="cognito-user-pools-define-resource-servers-about-m2m"></a>

Amazon Cognito 支持使用*计算机身份*访问 API 数据的应用程序。用户池中的计算机身份是在应用程序服务器上运行并连接到远程的[机密客户端](user-pool-settings-client-apps.md#user-pool-settings-client-app-client-types) APIs。其操作无需用户交互：计划任务、数据流或资产更新。当这些客户端使用访问令牌授权其请求时，它们会执行*机器对机器*（M2M）授权。在 M2M 授权中，共享密钥取代访问控制中的用户凭证。

通过 M2M 授权访问 API 的应用程序必须具有客户端 ID 和客户端密钥。在您的用户池中，必须构建支持客户端凭证授予的应用程序客户端。要支持客户端凭证，您的应用程序客户端必须具有客户端密钥，且您必须有用户池域。在此流程中，您的计算机身份直接从 [令牌端点](token-endpoint.md) 请求访问令牌。对于客户端凭证授予，您只能在访问令牌中授权来自[资源服务器](#cognito-user-pools-define-resource-servers-about-resource-servers)的自定义范围。有关设置应用程序客户端的更多信息，请参阅[特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。

来自客户端凭证授予的访问令牌实际上是一个可验证的声明，表明您希望计算机身份向 API 请求哪些操作。要详细了解访问令牌如何授权 API 请求，请继续阅读。有关示例应用程序，请参阅[使用 AWS CDK 进行基于 Amazon Cognito 和 API Gateway 的机器到机器授权](https://github.com/aws-samples/amazon-cognito-and-api-gateway-based-machine-to-machine-authorization-using-aws-cdk)。

M2M 授权的计费模式不同于每月活跃用户 (MAUs) 的计费方式。用户身份验证会根据每个活跃用户的数量收取费用，而 M2M 计费则反映了活跃的客户端凭证应用程序客户端和令牌请求总量。有关更多信息，请参阅 [Amazon Cognito 定价](https://aws.amazon.com/cognito/pricing)。要控制 M2M 授权的成本，请优化访问令牌的持续时间和应用程序发出的令牌请求数量。有关使用 API Gateway 缓存来减少 M2M 授权中的新令牌请求的方法，请参阅[管理用户池令牌到期和缓存](amazon-cognito-user-pools-using-tokens-caching-tokens.md)。

有关优化会增加 AWS 账单成本的 Amazon Cognito 操作的信息，请参阅。[管理 成本](tracking-cost.md#tracking-cost-managing)

**machine-to-machine(M2M) 客户端凭证的客户端元数据**  
您可以在 M2M 请求中传递[客户端元数据](cognito-user-pools-working-with-lambda-triggers.md#working-with-lambda-trigger-client-metadata)。客户端元数据是来自用户或应用程序环境的附加信息，可影响[令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md)的结果。在使用用户委托人的身份验证操作中，您可以将客户端元数据传递给 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)API 请求正文中的令牌生成前触发器。[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)由于应用程序通过直接向 [令牌端点](token-endpoint.md) 发出请求来执行为 M2M 生成访问令牌的流程，因此它们的模型不同。在客户端凭证令牌请求的 POST 正文中，传递一个 `aws_client_metadata` 参数，其值为客户端元数据对象经 URL 编码（`x-www-form-urlencoded`）后的字符串。有关示例请求，请参阅[基本授权的客户端凭证POST 正文授权的客户端凭证](token-endpoint.md#exchanging-client-credentials-for-an-access-token-in-request-body)。以下是传递键值对 `{"environment": "dev", "language": "en-US"}` 的参数的示例。

```
aws_client_metadata=%7B%22environment%22%3A%20%22dev%22,%20%22language%22%3A%20%22en-US%22%7D
```

## 关于范围
<a name="cognito-user-pools-define-resource-servers-about-scopes"></a>

*范围*是应用程序可请求的对资源的访问权限的级别。在 Amazon Cognito 访问令牌中，范围由您与用户池建立的信任提供支持：一个具有已知数字签名的可信访问令牌发放者。用户池可以生成访问令牌，其范围可以证明您的客户可以管理自己的部分或全部用户个人资料，或者可以从后端 API 检索数据。Amazon Cognito 用户池使用*用户池预留 API 范围*、*自定义范围*和 *OpenID Connect（OIDC）范围*来发放访问令牌。

**用户池预留 API 范围**  
Amazon Cognito 用户池 API 中的 `aws.cognito.signin.user.admin` 范围授权当前用户执行自助操作。它授权访问令牌的持有者通过和 API 操作查询和更新有关该持有者的所有信息。[GetUser[UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html)当您使用 Amazon Cognito 用户池 API 对用户进行身份验证时，这是您在访问令牌中收到的唯一范围。这也是您读写已授权应用程序客户端读写的用户属性所需的唯一范围。您也可以在发往 [对端点授权](authorization-endpoint.md) 的请求中请求此范围。仅此范围不足以向 [userInfo 端点](userinfo-endpoint.md) 请求用户属性。对于同时授权用户池 API *和* 用户 `userInfo` 请求的访问令牌，您必须在一个 `/oauth2/authorize` 请求中同时请求 `openid` 和 `aws.cognito.signin.user.admin` 这两个范围。

**自定义作用域**  
自定义作用域授权向资源服务器保护的外部服务器发 APIs 出的请求。您可以使用其他类型的范围请求自定义范围。您可以在此页面中找到有关自定义范围的更多信息。

**OpenID Connect（OIDC）范围**  
使用用户池授权服务器（包括托管登录）验证用户身份时，必须请求范围。您可以在 Amazon Cognito 授权服务器中对用户池本地用户和第三方联合用户进行身份验证。OIDC 范围授权您的应用从您的用户池的 [userInfo 端点](userinfo-endpoint.md) 中读取用户信息。通过该 OAuth 模型，您可以从`userInfo`端点查询用户属性，它可以针对大量用户属性请求优化您的应用程序。`userInfo` 端点返回权限级别的属性，该级别由访问令牌中的范围决定。您可以授权您的应用程序客户端颁发具有以下 OIDC 范围的访问令牌。

openid  
OpenID Connect (OIDC) 查询的最小范围。授权 ID 令牌、唯一标识符声明 `sub` 以及请求其他范围的能力。  
当您请求 `openid` 范围而不请求其他范围时，您的用户池 ID 令牌和 `userInfo` 响应将包括您的应用程序客户端可以读取的所有用户属性的声明。当您同时请求 `openid` 和其他 OIDC 范围（例如 `profile`、`email` 和 `phone`）时，ID 令牌和 [userInfo](userinfo-endpoint.md#userinfo-endpoint.title) 响应的内容将受到其他范围的限制。  
例如，如果发送到 [对端点授权](authorization-endpoint.md) 的请求带有参数 `scope=openid+email`，则将返回带有 `sub`、`email` 和 `email_verified` 的 ID 令牌。来自此请求的访问令牌也将从 [userInfo 端点](userinfo-endpoint.md) 返回这些属性。带有参数 `scope=openid` 的请求将在 ID 令牌中返回所有客户端可以读取的属性，`userInfo` 响应也是如此。

配置文件  
授权应用程序客户端可以读取的所有用户属性。

电子邮件  
授权用户属性 `email` 和 `email_verified`。如果有已明确设置的值，Amazon Cognito 将返回 `email_verified`。

phone  
授权用户属性 `phone_number` 和 `phone_number_verified`。

## 关于资源服务器
<a name="cognito-user-pools-define-resource-servers-about-resource-servers"></a>

资源服务器 API 可能会授予对数据库中信息的访问权限，或者控制您的 IT 资源。亚马逊 Cognito 访问令牌可以授权访问 APIs 该支持 OAuth 2.0。亚马逊 API Gateway REST [内置 APIs 了对使用亚马逊 Cognito 访问令牌进行授权的支持](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html)。应用程序会将 API 调用中的访问令牌传递到资源服务器。资源服务器将检查访问令牌以确定是否应授予访问权限。

Amazon Cognito 将来可能会更新用户池访问令牌的架构。如果您的应用程序在将访问令牌传递给 API 之前分析其内容，则您必须对代码进行设计以接受架构的更新。

自定义范围由您定义，它会扩展用户池的授权功能，以包括与查询和修改用户及其属性无关的目的。例如，如果你有一个照片资源服务器，它可能会定义两个范围：`photos.read`用于照片的读取权限和`photos.write` write/delete 访问权限。您可以配置 API 以接受用于授权的访问令牌，并授予 `HTTP GET` 请求使用 `scope` 声明中的 `photos.read` 访问令牌，以及授予 `HTTP POST` 请求使用 `photos.write` 访问令牌。这些是*自定义范围*。

**注意**  
您的资源服务器在处理访问令牌内的任何声明之前必须验证访问令牌的签名和到期日期。有关验证令牌的更多信息，请参阅[验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。有关在 Amazon API Gateway 中验证和使用用户池令牌的更多信息，请参阅博客[将 Amazon Cognito 用户池与 API Gateway 集成](https://aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/)。API Gateway 是用于检查访问令牌和保护您的资源的一个很好的选择。有关 API Gateway Lambda 授权方的更多信息，请参阅[使用 API Gateway Lambda 授权方](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html)。

**概述**  
使用 Amazon Cognito，您可以创建 OAuth 2.0 **资源服务器**并将**自定义范围与它们**关联起来。访问令牌中的自定义范围可向 API 中的特定操作授权。您可以授权用户池中的任何应用程序客户端从您的任何资源服务器发布自定义范围。将您的自定义范围与应用程序客户端关联，并从 OAuth 2.0 授权码授权、隐式授权和客户端凭证授予中请求这些范围[令牌端点](token-endpoint.md)。Amazon Cognito 在访问令牌中将自定义范围添加到 `scope` 声明中。客户端可对其资源服务器使用访问令牌，然后服务器基于令牌中给出的范围做出授权决定。有关访问令牌范围的更多信息，请参阅[将令牌与用户池结合使用](amazon-cognito-user-pools-using-tokens-with-identity-providers.md)。

![\[资源服务器流程概述。客户端请求具有自定义范围的授予，用户池返回具有自定义范围的访问令牌，然后客户端向 API 提供访问令牌。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/resource-servers.png)


要获得具有自定义范围的访问令牌，您的应用程序必须向 [令牌端点](token-endpoint.md) 发出请求以兑换授权代码或请求客户端凭证授予。在托管登录中，您还可以通过隐式授予在访问令牌中请求自定义范围。

**注意**  
因为它们是为以用户池作为 IdP 的人机交互身份验证而设计的 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)，[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)并且请求仅在访问令牌中生成具有单`scope`一值的声明。`aws.cognito.signin.user.admin`

**管理资源服务器和自定义范围**

在创建资源服务器时，您必须提供资源服务器名称和资源服务器标识符。对于您在资源服务器中创建的每个范围，您都必须提供范围名称和描述。
+ **资源服务器名称**：资源服务器的易记名称，如 `Solar system object tracker` 或 `Photo API`。
+ **资源服务器标识符**：资源服务器的唯一标识符。标识符是您希望与 API 关联的任何名称，例如 `solar-system-data`。您可以配置更长的标识符，例如 `https://solar-system-data-api.example.com`，作为对 API URI 路径的更直接引用，但较长的字符串会增加访问令牌的大小。
+ **范围名称**：`scope` 声明中需要的值。例如 `sunproximity.read`。
+ **描述**：范围的友好描述。例如 `Check current proximity to sun`。

Amazon Cognito 可以在任何用户的访问令牌中包含自定义范围，无论这些用户是用户池的本地用户还是与第三方身份提供者的联合身份验证用户。在身份验证流程中，您可以使用包含托管登录的 OAuth 2.0 授权服务器为用户的访问令牌选择范围。您的用户的身份验证必须从以 `scope` 作为请求参数之一的[对端点授权](authorization-endpoint.md)开始。以下是推荐的资源服务器格式。对于标识符，请使用 API 友好名称。对于自定义范围，请使用它们授权的操作。

```
resourceServerIdentifier/scopeName
```

例如，您在柯伊伯带发现了一颗新的小行星，您想通过 `solar-system-data` API 对其进行注册。授权对小行星数据库进行写操作的范围是 `asteroids.add`。当您请求授权您注册发现的小行星的访问令牌时，请将 `scope` HTTPS 请求参数格式设置为 `scope=solar-system-data/asteroids.add`。

从资源服务器中删除一个范围不会删除其与所有客户端的关联。而是范围标记为*非活动*。Amazon Cognito 不会为访问令牌添加非活动的范围，但如果您的应用程序请求访问令牌，则会正常进行。如果您稍后再次将范围添加到资源服务器，则 Amazon Cognito 会再次将其写入访问令牌。如果您请求的范围尚未与应用程序客户端关联，则无论您是否将其从用户池资源服务器中删除，身份验证都会失败。

您可以使用 AWS 管理控制台、API 或 CLI 为用户池定义资源服务器和范围。

### 为您的用户池定义资源服务器（AWS 管理控制台）
<a name="cognito-user-pools-define-resource-servers-console"></a>

您可以使用为您的用户池定义资源服务器。 AWS 管理控制台 

**定义资源服务器**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。

1. 在导航窗格中，选择 **User Pools**（用户池），然后选择要编辑的用户池。

1. 选择**品牌**下的**域**菜单，然后找到**资源服务器**。

1. 选择 **Create a resource server**（创建资源服务器）。

1. 输入 **Resource server name**（资源服务器名称）。例如 `Photo Server`。

1. 输入 **Resource server identifier**（资源服务器识符）。例如 `com.example.photos`。

1. 输入您的资源的 **Custom scopes**（自定义范围），例如 `read` 和 `write`。

1. 对于每个 **Scope name**（范围名称），输入一个 **Description**（描述），如 `view your photos` 和 `update your photos`。

1. 选择**创建**。

您的自定义范围可以在**域**菜单**资源服务器**下的**自定义范围**列中查看。可以从**应用程序**下的**应用程序客户端**菜单为应用程序客户端启用自定义范围。选择应用程序客户端，找到**登录页面**，然后选择**编辑**。添加 **Custom scopes**（自定义范围），然后选择 **Save changes**（保存更改）。

### 为您的用户池（AWS CLI 和 AWS API）定义资源服务器
<a name="cognito-user-pools-define-resource-servers-cli-api"></a>

使用以下命令可为您的用户池指定资源服务器设置。

**创建资源服务器**
+ AWS CLI: `aws cognito-idp create-resource-server`
+ AWS API: [CreateResourceServer](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateResourceServer.html)

**获取有关您的资源服务器设置的信息**
+ AWS CLI: `aws cognito-idp describe-resource-server`
+ AWS API: [DescribeResourceServer](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeResourceServer.html)

**列出用户池的所有资源服务器的相关信息**
+ AWS CLI: `aws cognito-idp list-resource-servers`
+ AWS API: [ListResourceServers](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListResourceServers.html)

**删除资源服务器**
+ AWS CLI: `aws cognito-idp delete-resource-server`
+ AWS API: [DeleteResourceServer](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteResourceServer.html)

**更新资源服务器的设置**
+ AWS CLI: `aws cognito-idp update-resource-server`
+ AWS API: [UpdateResourceServer](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateResourceServer.html)

## 资源绑定
<a name="cognito-user-pools-resource-binding"></a>

通过资源绑定（也称为资源指示器），您可以向用户池授权服务器请求特定于 API 的授权授予。资源绑定是 [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html) 中定义的 OAuth 2.0 扩展，它允许客户端在授权请求期间明确指定他们打算访问哪个资源服务器。通过资源绑定，您的 API 配置可以拒绝访问不是专门为其设计的令牌。

**注意**  
您只能为用户将访问令牌绑定到资源。您不能对客户端凭证 M2M 授予请求资源绑定。

当您对 Amazon Cognito 用户池使用资源绑定时，客户端可以在向您的用户池授权服务器发送的身份验证请求中包含一个 `resource` 参数。您的用户池会验证所请求资源的值是否为 URL，遵循`http://`与[应用程序客户端](user-pool-settings-client-apps.md#cognito-user-pools-app-idp-settings-about)回调相同的方案规则 URLs：`https://`、`localhost`仅限使用或类似`myapp://`的自定义方案。Amazon Cognito 在[访问令牌](amazon-cognito-user-pools-using-the-access-token.md)的 `aud` 声明中将请求的 URI 设置为受众。如果请求的资源是用户池资源服务器，则资源服务器标识符必须采用 URL 格式。您可以为每个身份验证请求请求一个资源。

此功能是使用用户池 OAuth 2.0 授权服务器进行[托管登录身份验证](authentication-flows-selection-managedlogin.md)所独有的。您可以从[对端点授权](authorization-endpoint.md)中，在隐式和授权码授予中请求资源绑定。来自[令牌端点](token-endpoint.md)的令牌刷新授予会延续来自原始请求的 `aud` 声明。它当前在 [SDK 身份验证模型](authentication-flows-selection-sdk.md)中不可用。

**对 Amazon Cognito 用户池实施资源绑定**

1. 在用户池中使用唯一标识符配置一个或多个资源服务器。

1. 在向 `/oauth2/authorize` 的授权请求中，请求授权码或隐式授予，并包含 `resource` 参数。`resource` 的值必须是 URL 格式的资源服务器标识符或 URL。例如 `&resource=https://solar-system-data-api.example.com`。

1. 授权服务器验证资源请求，完成身份验证，并将访问令牌 `aud` 声明设置为请求的资源 URL。

1. 为了验证令牌是专门为其发布，使用用户访问令牌的资源会检查 `aud` 声明。

# 配置用户池功能
<a name="user-pools-configure-features"></a>

在前面的章节中，您可能已经在 Amazon Cognito 控制台的引导下配置了一些功能。本节中的页面将更深入地探讨用户池一些核心功能的详细配置要求。这里有关于应用程序客户端、电子邮件和短信配置、记住用户设备等方面的选项的重要参考信息。

**Topics**
+ [更新用户池和应用程序客户端配置](cognito-user-pool-updating.md)
+ [特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)
+ [使用用户池中的用户设备](amazon-cognito-user-pools-device-tracking.md)
+ [使用 Amazon Pinpoint 进行用户池分析](cognito-user-pools-pinpoint-integration.md)
+ [Amazon Cognito 用户池的电子邮件设置](user-pool-email.md)
+ [Amazon Cognito 用户池的短信设置](user-pool-sms-settings.md)

# 更新用户池和应用程序客户端配置
<a name="cognito-user-pool-updating"></a>

当您想要更改用户池或应用程序客户端中的设置时，只需点击几下即可在 Amazon Cognito 控制台中应用更新。浏览用户池设置中基于特征的选项卡，并按照本指南其他部分的说明更新字段。

许多组织通过编程方式管理其资源 AWS CloudFormation、基于 AWS SDKs 或 CDK 构建的应用程序以及其他自动化软件。如果这是您的资源管理模型，则在资源中逐步实施变更时必须格外小心。

API 操作[ UpdateUserPool[ UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)并更新现有用户池或应用程序客户端。每个操作在 API 参考中都有一个警告：*如果您没有为属性提供值，Amazon Cognito 会将其设置为默认值。*当您提交仅包含一个参数的更新请求时，Amazon Cognito 会将该参数设置为您选择的值，并将所有其他参数设置为默认值。这样可以重置配置，包括您的属性架构、Lambda 触发器以及电子邮件和短信消息配置。

此外，在创建用户池或应用程序客户端后，有些设置会锁定，除非创建新资源，否则无法更改这些设置。

**Topics**
+ [无法更改的设置](#cognito-user-pool-updating-fixed-settings)
+ [短信配置](#cognito-user-pool-updating-sms)
+ [使用 AWS SDK 或 REST API 更新用户池 AWS CDK](#cognito-user-pool-updating-api-cli)

## 无法更改的设置
<a name="cognito-user-pool-updating-fixed-settings"></a>

创建用户池后，您无法更改一些设置。如果您想要更改以下设置，您必须创建新的用户池或应用程序客户端。

**注意**  
以前，您无法更改用户池的名称。这一点已经改变。现在，您可以为用户池分配新的友好名称。

**用户池 ID**  
API 参数名称：[ID/ UserPoolId](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UserPoolType.html#CognitoUserPools-Type-UserPoolType-ID)  
用户池 ID（例如 `us-east-1_EXAMPLE`）由 Amazon Cognito 自动生成，无法更改。

**Amazon Cognito 用户池登录选项**  
API 参数名称：[AliasAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-AliasAttributes)和 [UsernameAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-UsernameAttributes)  
用户登录时可以作为用户名传递的属性。创建用户池时，您可以选择允许使用用户名、电子邮件地址、电话号码或首选用户名进行登录。要更改用户池登录选项，请创建新的用户池。

**Make user name case sensitive（使用户名区分大小写）**  
API 参数名称：[UsernameConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-UsernameConfiguration)  
当您创建的用户名与其他用户名（字母大小写除外）匹配时，Amazon Cognito 可以将其视为同一用户或唯一用户。有关更多信息，请参阅 [用户池区分大小写](user-pool-case-sensitivity.md)。要更改区分大小写，请创建新的用户池。

**客户端密钥**  
API 参数名称：[GenerateSecret](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#CognitoUserPools-CreateUserPoolClient-request-GenerateSecret)  
创建应用程序客户端时，可以生成客户端密钥，以便只有受信任的来源才能向用户池发出请求。有关更多信息，请参阅 [特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。要更改客户端密钥，请在同一用户池中创建新的应用程序客户端。

**必需的属性**  
API 参数名称：[Schema](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-Schema)  
当用户注册时或当您创建属性时，用户必须为这些属性提供值。有关更多信息，请参阅 [使用用户属性](user-pool-settings-attributes.md)。要更改必需的属性，请创建新的用户池。

**自定义属性（删除）**  
API 参数名称：[Schema](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-Schema)  
具有自定义名称的属性。您可以更改用户自定义属性的值，但不能从用户池中删除自定义属性。有关更多信息，请参阅 [使用用户属性](user-pool-settings-attributes.md)。如果达到自定义属性的最大数量并且您想要修改列表，请创建新的用户池。

## 短信配置
<a name="cognito-user-pool-updating-sms"></a>

激活用户池中的短信后，您就无法停用它们。
+ 如果您选择在创建用户池时配置短信，则在完成设置后无法停用短信。
+ 您可以在自己创建的用户池中激活短信，但之后就无法停用短信。
+ Amazon Cognito 可以使用短信进行用户账户邀请和恢复、属性验证和多重身份验证（MFA）。激活短信后，您可以随时为这些功能开启或关闭短信。
+ 短信配置包括您委托给 Amazon Cognito 的 IAM 角色，以便使用 Amazon SNS 发送消息。您可以随时更改分配的角色。

## 使用 AWS SDK 或 REST API 更新用户池 AWS CDK
<a name="cognito-user-pool-updating-api-cli"></a>

在 Amazon Cognito 控制台中，您可以更改用户池设置，一次更改一个参数。例如，要添加 Lambda 触发器，您可以选择**添加 Lambda 触发器**，然后选择函数和触发器类型。Amazon Cognito 用户池 API 按以下方式进行构造，用户池和应用程序客户端的更新操作需要用户池的完整参数集。但是，控制台会使用您的其他用户池设置透明地自动执行此更新操作。

有时你可能会发现，当更新与你要更改的设置无关时，你 AWS 账户 可能会发现其他地方的更改可能会导致更新生成错误。例如，已删除的 Amazon SES 身份或 IAM 权限的 AWS WAF更改。如果其中一个当前参数不再有效，则在修复该参数之前，您无法更新设置。遇到此类错误时，请检查错误响应并验证响应中提及的设置。

[Amazon Cognito 用户池 REST API [AWS SDKs](https://aws.amazon.com/developer/tools/)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html)是用于自动化和编程配置 Amazon Cognito 资源的工具。[AWS Cloud Development Kit (AWS CDK)](https://aws.amazon.com/cdk)使用这些工具的请求也必须像 Amazon Cognito 控制台一样，在请求正文中使用完整的资源配置来更新设置。概括来说，您必须执行以下步骤。

1. 从描述现有资源配置的操作中捕获输出。

1. 设置更改后修改输出。

1. 在更新资源的操作中发送修改后的配置。

以下过程使用 [ UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 操作更新您的配置。同样的方法适用于不同的输入字段[ UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)。

**重要**  
如果您未为现有参数提供值，Amazon Cognito 将它们设置为默认值。例如，如果您有现有的 `LambdaConfig`，然后提交具有空 `LambdaConfig` 的 `UpdateUserPool`，则会删除为用户池触发器分配的所有 Lambda 函数。当您想自动更改用户池配置时，请相应地进行规划。

1. 使用捕获用户池的现有状态[ DescribeUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPool.html)。

1. 设置 `DescribeUserPool` 的输出的格式以与 `UpdateUserPool` 的[请求参数](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#API_UpdateUserPool_RequestSyntax)匹配。从输出 JSON 中删除以下顶级字段及其子对象。
   + `Arn`
   + `CreationDate`
   + `CustomDomain`
     + 使用 [UpdateUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolDomain.html)API 操作更新此字段。
   + `Domain`
     + 使用 [UpdateUserPoolDomain](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolDomain.html)API 操作更新此字段。
   + `EmailConfigurationFailure`
   + `EstimatedNumberOfUsers`
   + `Id`
   + `LastModifiedDate`
   + `Name`
   + `SchemaAttributes`
   + `SmsConfigurationFailure`
   + `Status`

1. 确认生成的 JSON 与 `UpdateUserPool` 的[请求参数](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#API_UpdateUserPool_RequestSyntax)匹配。

1. 修改任何您想要在生成的 JSON 中更改的参数。

1. 提交 `UpdateUserPool` API 请求，同时将您修改后的 JSON 作为请求输入。

您还可以在 AWS CLI中，在 `update-user-pool` 的 `--cli-input-json` 参数中使用这一修改后的 `DescribeUserPool` 输出。

或者，运行以下 AWS CLI 命令为接受的输入字段生成空值的 JSON。`update-user-pool`然后，您可以使用用户池中的现有值填充这些字段。

```
aws cognito-idp update-user-pool --generate-cli-skeleton --output json
```

运行以下命令以为应用程序客户端生成相同的 JSON 对象。

```
aws cognito-idp update-user-pool-client --generate-cli-skeleton --output json
```

# 特定于应用程序的应用程序客户端设置
<a name="user-pool-settings-client-apps"></a>

用户池应用程序客户端是用户池中的一项配置，它与一个通过 Amazon Cognito 进行身份验证的移动或 Web 应用程序进行交互。应用程序客户端可以调用经过授权和未经身份验证的 API 操作，并读取或修改用户的部分或全部属性。您的应用程序必须在操作中向应用程序客户端表明自己的身份，才能注册、登录和处理忘记的密码。这些 API 请求必须包括使用应用程序客户端 ID 进行自我识别以及使用可选客户端密钥进行授权的机制。您必须保护所有应用程序客户端 IDs 或密钥，以便只有经过授权的客户端应用程序才能调用这些未经身份验证的操作。此外，如果您将应用程序配置为使用 AWS 凭证签署经过身份验证的 API 请求，则必须保护您的凭据免受用户检查。

您可以为一个用户池创建多个应用程序。应用程序客户端可能链接到应用程序的代码平台，也可能链接到用户池中的单独租户。例如，您可以为服务器端应用程序和其他 Android 应用程序创建一个应用程序。每个应用程序都有各自的应用程序客户端 ID。

您可以在应用程序客户端级别应用以下用户池特征的设置：

1. [分析](cognito-user-pools-pinpoint-integration.md)

1. [托管登录](cognito-user-pools-managed-login.md) IdPs、授权类型 URLs、回调和自定义

1. [资源服务器和自定义范围](cognito-user-pools-define-resource-servers.md)

1. [威胁防护](cognito-user-pool-settings-threat-protection.md)

1. [属性读取和写入权限](user-pool-settings-attributes.md#user-pool-settings-attribute-permissions-and-scopes)

1. [令牌到期和撤销](amazon-cognito-user-pools-using-tokens-with-identity-providers.md)

1. [身份验证流程](authentication.md#amazon-cognito-user-pools-authentication-flow)

## 应用程序客户端类型
<a name="user-pool-settings-client-app-client-types"></a>

**在 Amazon Cognito 中创建应用程序客户端时，您可以根据标准 OAuth 客户端类型（**公共客户端**和机密客户端）预先填充选项。**使用**客户端密钥**配置**机密客户端** 有关客户端类型的更多信息，请参阅 [IETF RFC 6749 \$12.1](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1)。

**公有客户端**  
公有客户端在浏览器或移动设备上运行。由于它没有可信的服务器端资源，所以它没有客户端密钥。

**机密客户端**  
机密客户端拥有可以信任的服务器端资源，使用**客户端密钥**进行未经身份验证的 API 操作。该应用程序可在后端服务器上作为守护进程或 Shell 脚本运行。

**客户端密钥**  
客户端机密或客户端密码是一个固定字符串，您的应用程序必须在发送到应用程序客户端的所有 API 请求中使用该字符串。您的应用程序客户端必须有客户端密钥才能执行 `client_credentials` 授权。有关更多信息，请参阅 [IETF RFC 6749 \$12.3.1](https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.1)。  
每个应用程序客户端一次最多可以拥有两个密钥，从而无需停机即可进行密钥轮换。在创建应用程序客户端时，您可以让 Amazon Cognito 生成密钥值，也可以提供自己的自定义密钥值。您在创建应用程序后无法更改密钥。您可以通过 [AddUserPoolClientSecret](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AddUserPoolClientSecret.html)API 操作添加第二个密钥来轮换密钥。添加密钥时，您可以让 Amazon Cognito 生成密钥值，也可以提供自己的自定义密钥值。要删除密钥，请使用 [DeleteUserPoolClientSecret](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUserPoolClientSecret.html)API 操作。您无法删除与应用程序客户端关联的唯一密钥。您也可以删除应用程序，以便阻止使用该应用程序客户端 ID 的应用程序的访问。  
当您为应用程序类型选择**传统 Web** 应用程序和 **M 应用程序选项时，Amazon Cognito 控制台会创建带有客户端密钥的achine-to-machine应用程序**客户端。选择以下选项之一来生成客户端密钥，或者使用编程方式创建客户端，[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)并将其设置`GenerateSecret`为`true`。

您可以将机密客户端和客户端密钥用于公有应用程序。使用 Amazon CloudFront 代理添加`SECRET_HASH`在途中。有关更多信息，请参阅博客上的[使用亚马逊 CloudFront 代理保护公共客户端 Amazon Cognito](https://aws.amazon.com/blogs/security/protect-public-clients-for-amazon-cognito-by-using-an-amazon-cloudfront-proxy/)。 AWS 

## JSON Web 令牌
<a name="user-pool-settings-client-app-token-types"></a>

亚马逊 Cognito 应用程序客户端可以发行以下类型的 JSON 网络令牌 (JWTs)。

**身份（ID）令牌**  
一份可验证的声明，表明您的用户是从用户池进行的身份验证。OpenID Connect (OIDC) 在 2.0 定义的访问和刷新[令牌标准中添加了 ID 令牌规范](https://openid.net/specs/openid-connect-core-1_0.html#IDToken)。 OAuth ID 令牌包含身份信息，例如用户属性，您的应用程序可以使用这些信息来创建用户个人资料和配置资源。请参阅[了解身份（ID）令牌](amazon-cognito-user-pools-using-the-id-token.md)了解更多信息。

**访问令牌**  
您的用户访问权限的可验证声明。访问令牌包含[作用域](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3)、OIDC 和 OAuth 2.0 的功能。您的应用程序可以为后端资源提供范围，并证明您的用户池已授权用户或计算机访问来自 API 的数据或它们自己的用户数据。具有*自定义范围*的访问令牌（通常来自 M2M 客户端凭证授权）用于授权访问资源服务器。请参阅[了解访问令牌](amazon-cognito-user-pools-using-the-access-token.md)了解更多信息。

**刷新令牌**  
一种加密的初始身份验证声明，当您的用户令牌到期时，您的应用程序可以将其提供给您的用户池。刷新令牌请求会返回新的未到期访问令牌和 ID 令牌。请参阅[刷新令牌](amazon-cognito-user-pools-using-the-refresh-token.md)了解更多信息。

您可以在 [Amazon Cognito](https://console.aws.amazon.com/cognito/v2/idp/user-pools) 控制台中，从用户池的**应用程序客户端**菜单为每个应用程序客户端设置这些令牌的到期时间。

## 应用程序客户端术语
<a name="cognito-user-pools-app-idp-settings-about"></a>

以下术语是 Amazon Cognito 控制台中应用程序客户端的可用属性。

**允许的回调 URLs**  
回调 URL 指示在用户成功登录之后将被重新导向到哪里。选择至少一个回调 URL。回调 URL 必须：  
+ 是绝对 URI。
+ 已预先向客户端注册。
+ 不包含片段组件。
请参阅 [OAuth 2.0-重定向端点](https://tools.ietf.org/html/rfc6749#section-3.1.2)。  
Amazon Cognito 要求使用 `HTTPS` 而不是 `HTTP`，但 `http://localhost`（仅用于测试目的）除外。  
还支持 URLs 诸如之`myapp://example`类的应用程序回调。

**允许注销 URLs**  
注销 URL 指示在您的用户注销后会被重定向到哪里。

**属性读取和写入权限**  
您的用户群可能有很多客户，每个客户都有自己的应用程序客户端，并且 IdPs。您可以将应用程序客户端配置为仅对与应用程序相关的用户属性具有读写权限。在 machine-to-machine（M2M）授权之类的情况下，您可以不授予对任何用户属性的访问权限。  

**属性读取和写入权限配置的注意事项**
+ 如果您创建应用程序客户端但不自定义属性读取和写入权限，Amazon Cognito 会向所有用户池属性授予读写权限。
+ 您可以授予对不可变[自定义属性](user-pool-settings-attributes.md#user-pool-settings-custom-attributes.title)的写入权限。创建或注册用户时，您的应用程序客户端可以将值写入不可变属性。此后，您将无法为用户的任何不可变自定义属性写入值。
+ 应用程序客户端必须拥有对用户池中必要属性的写入权限。Amazon Cognito 控制台会自动将必要属性设置为可写属性。
+ 您不能允许应用程序客户端对 `email_verified` 或 `phone_number_verified` 拥有写入权限。用户池管理员可以修改这些值。用户只能通过[属性验证](signing-up-users-in-your-app.md#allowing-users-to-sign-up-and-confirm-themselves.title)来更改这些属性的值。

**身份验证流程**  
您的应用程序客户端允许的登录方法。您的应用程序可以支持使用用户名和密码进行身份验证、电子邮件和短信、密钥身份验证器 OTPs、使用 Lambda 触发器的自定义身份验证以及令牌刷新。作为最佳安全实践，请在自定义构建的应用程序中使用 SRP 身份验证进行用户名和密码身份验证。

**自定义作用域**  
自定义范围是您在**资源服务器**中为自己的资源服务器定义的范围。格式为*resource-server-identifier*/*scope*。请参阅[作用域、M2M 和资源服务器](cognito-user-pools-define-resource-servers.md)。

**默认的重定向 URI**  
将用户身份验证请求中的`redirect_uri`参数替换为第三方 IdPs。使用[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)或 [UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)API 请求的`DefaultRedirectURI`参数配置此应用程序客户端设置。此 URL 还必须是应用程序客户端的 `CallbackURLs` 的成员。在以下情况下，Amazon Cognito 会将经过身份验证的会话重定向到此 URL：  

1. 您的应用程序客户端分配了一个[身份提供商](#app-client-terms-identity-provider)并 URLs定义了多个[回调](#app-client-terms-callback-urls)。如果身份验证请求不包括 `redirect_uri` 参数，则用户池会将对[授权服务器](authorization-endpoint.md)的身份验证请求重定向到默认的重定向 URI。

1. 您的应用程序客户端分配了一个[身份提供商](#app-client-terms-identity-provider)并 URLs定义了一个[回调](#app-client-terms-callback-urls)。在这种情况下，无需定义默认的回调 URL。不包括 `redirect_uri` 参数的请求会重定向到一个可用的回调 URL。

**身份提供者**  
您可以选择部分或全部用户池外部身份提供商 (IdPs) 来对用户进行身份验证。您的应用程序客户端还可以仅对用户池中的本地用户进行身份验证。当您将 IdP 添加到应用程序客户端时，可以生成指向 IdP 的授权链接，并将其显示在您的托管登录的登录页面上。您可以分配多个 IdPs，但必须至少分配一个。有关使用外部的更多信息 IdPs，请参阅[使用第三方身份提供者进行用户池登录](cognito-user-pools-identity-federation.md)。

**OpenID Connect 范围**  
选择以下一个或多个 `OAuth` 范围来指定可以为访问令牌请求的访问权限。  
+ `openid` 范围声明您要检索 ID 令牌和用户的唯一 ID。它还会请求全部或部分用户属性，具体取决于请求中的其他范围。除非您请求 `openid` 范围，否则 Amazon Cognito 不会返回 ID 令牌。`openid` 范围授权结构化 ID 令牌声明，例如过期时间和密钥 ID，并确定您在 [userInfo 端点](userinfo-endpoint.md) 的响应中收到的用户属性。
  + 当 `openid` 是您请求的唯一范围时，Amazon Cognito 会使用当前应用程序客户端可以读取的所有用户属性填充 ID 令牌。对仅具有此范围的访问令牌的 `userInfo` 响应将返回所有用户属性。
  + 当您使用其他范围（例如 `phone`、`email` 或 `profile`）请求 `openid` 时，ID 令牌和 `userInfo` 返回用户的唯一 ID 以及由其他范围定义的属性。
+ `phone` 范围授予对 `phone_number` 和 `phone_number_verified` 声明的访问权限。此范围只能通过 `openid` 范围来请求。
+ `email` 范围授予对 `email` 和 `email_verified` 声明的访问权限。此范围只能通过 `openid` 范围来请求。
+ 该`aws.cognito.signin.user.admin`范围允许访问需要访问令牌的 [Amazon Cognito 用户池 API 操作](authentication-flows-public-server-side.md#user-pools-API-operations)，例如[UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html)和。[VerifyUserAttribute](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifyUserAttribute.html)
+ `profile` 范围授予对客户端可读取的所有用户属性的访问权限。此范围只能通过 `openid` 范围来请求。
有关范围的更多信息，请参阅[标准 OIDC 范围](http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims)列表。

**OAuth 拨款类型**  
 OAuth 授权是一种检索用户池令牌的身份验证方法。Amazon Cognito 支持以下类型的授权。要将这些 OAuth 授权集成到您的应用程序中，您必须向用户池中添加域名。  
**授予授权代码**  
授权码授权会生成一个代码，您的应用程序可以用它与[令牌端点](token-endpoint.md)交换用户池令牌。当您交换授权码时，您的应用程序会收到 ID、访问权限和刷新令牌。与隐式授权一样，这种 OAuth 流程发生在用户的浏览器中。授权码授权是 Amazon Cognito 提供的最安全的授权，因为令牌在用户的会话中不可见。相反，您的应用程序会生成返回令牌的请求，并可以将其缓存在受保护存储空间中。有关更多信息，请参阅 [IETF RFC 6749 \$11.3.1](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1) 中的*授权码*。
作为公共客户端应用程序的最佳安全实践，仅激活授权码授予 OAuth 流程，并实施代码交换证明密钥 (PKCE) 以限制令牌交换。通过 PKCE，客户端只有在向令牌端点提供与原始身份验证请求中相同的机密时，才能交换授权码。有关 PKCE 的更多信息，请参阅 [IETF RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636)。
**隐式授予**  
隐式授权直接从[对端点授权](authorization-endpoint.md)向用户的浏览器会话提供访问权限和 ID 令牌，但不返回刷新令牌。隐式授权消除了向令牌端点提出单独请求的要求，但与 PKCE 不兼容，也不会返回刷新令牌。该授权适用于无法完成授权码授权的测试场景和应用程序架构。有关更多信息，请参阅 [IETF RFC 6749 \$11.3.2](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.2) 中的*隐式授权*。您可以在应用程序客户端中同时激活授权码授权和隐式授权，然后按需使用每个授权。
**客户端凭证授权**  
客户端凭证授予用于 machine-to-machine (M2M) 通信。授权码和隐式授权向经过身份验证的人类用户发放令牌。客户端凭证授权非交互式系统对 API 的基于范围的授权。您的应用程序可以直接从令牌端点请求客户端凭证并接收访问令牌。有关更多信息，请参阅 [IETF RFC 6749 \$11.3.4](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.4) 中的*客户端凭证*。您只能在具有客户端机密且不支持授权码或隐式授权的应用程序客户端中激活客户端凭证授权。
由于您没有以用户身份调用客户端凭证流程，因此该授权只能向访问令牌添加*自定义*范围。自定义范围就是您为自己的资源服务器定义的范围。默认范围（例如 `openid` 和 `profile`）不适用于非人类用户。  
由于 ID 令牌是对用户属性的验证，因此它们与 M2M 通信无关，客户凭证授权也不会发放 ID 令牌。请参阅[作用域、M2M 和资源服务器](cognito-user-pools-define-resource-servers.md)。
客户凭证授予会增加您的 AWS 账单费用。有关更多信息，请参阅 [Amazon Cognito 定价](https://aws.amazon.com/cognito/pricing)。

## 创建应用程序客户端
<a name="cognito-user-pools-app-idp-settings-console-create"></a>

------
#### [ AWS 管理控制台 ]

**创建应用程序客户端（控制台）**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或创建一个用户池。这两个选项都会提示您使用特定于应用程序的设置配置应用程序客户端。

1. 选择一种能反映您的应用程序架构的**应用程序类型**。

1. 使用友好的标识符**命名您的应用程序**。

1. 输入**返回 URL**。

1. 选择**创建应用程序客户端**。创建应用程序客户端后，您可以更改高级选项。

1. Amazon Cognito 将您返回到应用程序客户端详细信息。要访问应用程序的示例代码，请从**快速设置指南**选项卡中选择一个平台。

------
#### [ AWS CLI ]

```
aws cognito-idp create-user-pool-client --user-pool-id MyUserPoolID --client-name myApp
```

**注意**  
使用 JSON 格式进行回调和注销 URLs ，以防止 CLI 将其视为远程参数文件：  

```
--callback-urls "["https://example.com"]"
--logout-urls "["https://example.com"]"
```

有关更多信息，请参阅 AWS CLI 命令参考：[create-user-pool-client](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/create-user-pool-client.html)

------
#### [ Amazon Cognito user pools API ]

生成 [CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)API 请求。必须为所有您不想设置为默认值的参数指定一个值。

------

## 更新用户池应用程序客户端（AWS CLI 和 AWS API）
<a name="cognito-user-pools-app-idp-settings-cli-api-update-user-pool-client"></a>

在 AWS CLI，输入以下命令：

```
aws cognito-idp update-user-pool-client --user-pool-id  "MyUserPoolID" --client-id "MyAppClientID" --allowed-o-auth-flows-user-pool-client --allowed-o-auth-flows "code" "implicit" --allowed-o-auth-scopes "openid" --callback-urls "["https://example.com"]" --supported-identity-providers "["MySAMLIdP", "LoginWithAmazon"]"
```

如果命令成功，则 AWS CLI 返回确认信息：

```
{
    "UserPoolClient": {
        "ClientId": "MyClientID",
        "SupportedIdentityProviders": [
            "LoginWithAmazon",
            "MySAMLIdP"
        ],
        "CallbackURLs": [
            "https://example.com"
        ],
        "AllowedOAuthScopes": [
            "openid"
        ],
        "ClientName": "Example",
        "AllowedOAuthFlows": [
            "implicit",
            "code"
        ],
        "RefreshTokenValidity": 30,
        "AuthSessionValidity": 3,
        "CreationDate": 1524628110.29,
        "AllowedOAuthFlowsUserPoolClient": true,
        "UserPoolId": "MyUserPoolID",
        "LastModifiedDate": 1530055177.553
    }
}
```

有关更多信息，请参阅 AWS CLI 命令参考:[update-user-pool-client](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/update-user-pool-client.html).

AWS API: [UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)

## 获取有关用户池应用程序客户端（AWS CLI 和 AWS API）的信息
<a name="cognito-user-pools-app-idp-settings-cli-api-describe-user-pool-client"></a>

```
aws cognito-idp describe-user-pool-client --user-pool-id MyUserPoolID --client-id MyClientID
```

有关更多信息，请参阅 AWS CLI 命令参考:[describe-user-pool-client](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/describe-user-pool-client.html).

AWS API: [DescribeUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPoolClient.html)

## 列出用户池（AWS CLI 和 AWS API）中的所有应用程序客户端信息
<a name="cognito-user-pools-app-idp-settings-cli-api-list-user-pool-clients"></a>

```
aws cognito-idp list-user-pool-clients --user-pool-id "MyUserPoolID" --max-results 3
```

有关更多信息，请参阅 AWS CLI 命令参考:[list-user-pool-clients](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/list-user-pool-clients.html).

AWS API: [ListUserPoolClients](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUserPoolClients.html)

## 删除用户池应用程序客户端（AWS CLI 和 AWS API）
<a name="cognito-user-pools-app-idp-settings-cli-api-delete-user-pool-client"></a>

```
aws cognito-idp delete-user-pool-client --user-pool-id "MyUserPoolID" --client-id "MyAppClientID"
```

有关更多信息，请参阅 AWS CLI 命令参考：[delete-user-pool-client](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/delete-user-pool-client.html)

AWS API: [DeleteUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUserPoolClient.html)

# 使用用户池中的用户设备
<a name="amazon-cognito-user-pools-device-tracking"></a>

当您使用 Amazon Cognito 用户池 API 登录本地用户池用户时，可以将来自[威胁防护](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-settings-threat-protection.html)的用户活动日志与用户的每台设备相关联，并且如果用户使用的是可信设备，还可以选择让用户跳过多重身份验证（MFA）。对于任何尚未包含设备信息的登录，Amazon Cognito 都会在响应中包含设备密钥。设备密钥的格式为 `Region_UUID`。借助设备密钥、安全远程密码（SRP）库和允许设备身份验证的用户池，您可以提示应用程序中的用户信任当前设备，而不再在登录时提示输入 MFA 代码。

**Topics**
+ [设置记忆设备](#amazon-cognito-user-pools-setting-up-remembered-devices)
+ [获取设备密钥](#user-pools-remembered-devices-getting-a-device-key)
+ [使用设备登录](#user-pools-remembered-devices-signing-in-with-a-device)
+ [查看、更新和忘记设备](#user-pools-remembered-devices-viewing-updating-forgetting)

## 设置记忆设备
<a name="amazon-cognito-user-pools-setting-up-remembered-devices"></a>

借助 Amazon Cognito 用户池，您可以将每个用户的设备与唯一的设备标识符（设备密钥）关联起来。当您在登录时提供设备密钥和执行设备身份验证时，可以使用*可信设备*身份验证流程配置应用程序。在此流程中，您的应用程序可以为用户提供一种选择，使其无需使用 MFA 即可登录，直至由应用程序安全要求或用户首选项确定的某个时间之后。在该段时间后，您的应用程序必须将设备状态更改为*未记住*，并且用户必须通过 MFA 登录，直至他们确认他们希望记住设备。例如，应用程序可能会提示用户信任某台设备 30 天、60 天或 90 天。您可以将此日期存储在自定义属性中，并在该日期更改其设备的记住状态。然后，必须重新提示用户提交 MFA 代码并将设备设置为在成功进行身份验证后再次记住设备。

1. 记住的设备只能在 MFA 处于活动状态的用户池中覆盖 MFA。

当用户使用记住的设备登录时，您必须在其身份验证流程中执行额外的设备身份验证。有关更多信息，请参阅 [使用设备登录](#user-pools-remembered-devices-signing-in-with-a-device)。

在用户池的**登录**菜单的**设备跟踪**下，将用户池配置为记住设备。通过 Amazon Cognito 控制台设置记忆设备功能时，有三种选项供您选择：**Always (始终)**、**User Opt-In (用户选择加入)** 和 **No (否)**。

**请勿记住**  
用户池不会提示用户在登录时记住设备。

**始终记住**  
当应用程序确认用户的设备时，用户池将始终记住该设备，并且不会在将来成功登录设备时返回 MFA 质询。

**用户选择加入**  
当应用程序确认用户的设备后，用户池不会自动抑制 MFA 质询。您必须提示用户选择是否要记住设备。

当您选择**始终记住**或**用户选择加入**时，每次用户从身份不明的设备登录时，Amazon Cognito 都会生成设备标识符密钥和机密。设备密钥是应用程序在用户执行设备身份验证时发送到用户池的初始标识符。

对于每个已确认的用户设备，无论是自动记住还是选择加入，您都可以在每次用户登录时使用设备标识符密钥和机密对设备进行身份验证。

您还可以在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求中为用户池配置记忆设备设置。欲了解更多信息，请参阅该[DeviceConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#CognitoUserPools-UpdateUserPool-request-DeviceConfiguration)属性。

Amazon Cognito 用户池 API 为记住的设备提供了额外的操作。

1. [ListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListDevices.html)并[AdminListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminListDevices.html)返回用户的设备密钥及其元数据的列表。

1. [GetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetDevice.html)并[AdminGetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminGetDevice.html)返回单个设备的设备密钥和元数据。

1. [UpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateDeviceStatus.html)并将用户的设备[AdminUpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateDeviceStatus.html)设置为已记住或未记住。

1. [ForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgetDevice.html)并从用户的个人资料中[AdminForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminForgetDevice.html)移除已确认的设备。

名称以 `Admin` 开头的 API 操作用于服务器端应用程序，必须使用 IAM 凭证进行授权。有关更多信息，请参阅 [了解 API、OIDC 和托管登录页面身份验证](authentication-flows-public-server-side.md#user-pools-API-operations)。

## 获取设备密钥
<a name="user-pools-remembered-devices-getting-a-device-key"></a>

每当用户使用用户池 API 登录并且身份验证参数中未包含设备密钥作为 `DEVICE_KEY` 时，Amazon Cognito 都会在响应中返回新的设备密钥。在公共客户端应用程序中，将设备密钥放在应用程序存储中，以便您可以将其包含在将来的请求中。在机密服务器端应用程序中，使用用户的设备密钥设置浏览器 Cookie 或其它客户端令牌。

应用程序必须确认设备密钥并提供其它信息，然后用户才能使用其可信设备登录。向 Amazon Cognito 生成[ConfirmDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmDevice.html)请求，使用设备密钥、友好名称、密码验证器和盐来确认用户的设备。如果您将用户池配置为选择加入设备身份验证，Amazon Cognito 会在响应您的 `ConfirmDevice` 请求时，提示用户必须选择是否记住当前设备。在[UpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateDeviceStatus.html)请求中使用用户选择的内容进行回应。

当您确认用户的设备但未将其设置为记住的设备时，Amazon Cognito 会存储关联，但在您提供设备密钥时继续进行非设备登录。设备可以生成对用户安全和故障排除非常有用的日志。已确认但未记住的设备不会利用登录特征，但会利用安全监控日志特征。当您为应用程序客户端激活威胁防护功能并将设备指纹编码到请求中时，Amazon Cognito 会将用户事件与已确认的设备关联起来。

**获取新的设备密钥**

1. 使用 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 请求开始用户的登录会话。

1. 在收到标记用户登录会话完成的 JSON Web 令牌 (JWTs) [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)之前，使用回复所有身份验证挑战。

1. 在应用程序中，记录 Amazon Cognito 在其 `RespondToAuthChallenge` 或 `InitiateAuth` 响应的 `NewDeviceMetadata` 中返回的值：`DeviceGroupKey` 和 `DeviceKey`。

1. 为用户生成新的 SRP 密钥：盐和密码验证程序。此功能在提供 SRP 库 SDKs 的中可用。

1. 提示用户输入设备名称，或根据用户的设备特征生成一个名称。

1. 在 [ConfirmDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmDevice.html)API 请求中提供用户的访问令牌、设备密钥、设备名称和 SRP 密钥。如果用户池设置为**始终记住**设备，则用户的注册已完成。

1. 如果 Amazon Cognito 对于 `ConfirmDevice` 响应了 `"UserConfirmationNecessary": true`，请提示您的用户选择是否要记住该设备。如果他们确认要记住设备，请使用用户的访问令牌、设备密钥和生成 [UpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateDeviceStatus.html)API 请求`"DeviceRememberedStatus": "remembered"`。

1. 如果您已指示 Amazon Cognito 记住该设备，那么当用户下次登录时，看到的不是 MFA 质询，而是 `DEVICE_SRP_AUTH` 质询。

## 使用设备登录
<a name="user-pools-remembered-devices-signing-in-with-a-device"></a>

将用户的设备配置为记住后，当用户使用相同的设备密钥登录时，Amazon Cognito 不再要求用户提交 MFA 代码。设备身份验证仅用设备身份验证质询取代 MFA 身份验证质询。您不能仅使用设备身份验证登录用户。用户必须首先使用其密码或自定义质询完成身份验证。以下是在记住的设备上对用户进行身份验证的过程。

要在使用[自定义身份验证质询 Lambda 触发器的流程中执行设备身份验证](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-challenge.html)，请在您的 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API `DEVICE_KEY` 请求中传递参数。在用户成功完成所有质询并且 `CUSTOM_CHALLENGE` 质询返回的 `issueTokens` 值为 `true` 之后，Amazon Cognito 将返回一个最终 `DEVICE_SRP_AUTH` 质询。

**使用设备登录**

1. 从客户端存储中检索用户的设备密钥。

1. 使用 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 请求开始用户的登录会话。选择一个 `AuthFlow`：`USER_SRP_AUTH`、`REFRESH_TOKEN_AUTH`、`USER_PASSWORD_AUTH` 或 `CUSTOM_AUTH`。在 `AuthParameters` 中，将用户的设备密钥添加到 `DEVICE_KEY` 参数中，并包括所选登录流程所需的其它参数。

   1. 您还可以在对身份验证质询的 `PASSWORD_VERIFIER` 响应的参数中传递 `DEVICE_KEY`。

1. 完成质询响应，直到您在响应中收到 `DEVICE_SRP_AUTH` 质询。

1. 在 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)API 请求中，发送`USERNAME``DEVICE_KEY`、`DEVICE_SRP_AUTH`和`ChallengeName`的和参数`SRP_A`。

1. Amazon Cognito 以 `DEVICE_PASSWORD_VERIFIER` 质询进行响应。此质询响应包括 `SECRET_BLOCK` 和 `SRP_B` 的值。

1. 使用您的 SRP 库，生成并提交 `PASSWORD_CLAIM_SIGNATURE`、`PASSWORD_CLAIM_SECRET_BLOCK`、`TIMESTAMP`、`USERNAME` 和 `DEVICE_KEY` 参数。在其它 `RespondToAuthChallenge` 请求中提交这些内容。

1. 完成其他挑战，直到收到用户的挑战 JWTs。

以下伪代码演示如何计算 `DEVICE_PASSWORD_VERIFIER` 质询响应的值。要对设备进行 SRP 身份验证，请为用户生成一个*新*的 SRP 密钥：新的高熵密码 `DeviceSecret`、加密盐及关联的密码验证程序。这些值不同于用于用户 SRP 身份验证的密码、加密盐和验证程序。它们仅用于设备身份验证，并且仅存储在设备上。用于为用户设备生成 SRP 密钥的功能可在不同版本的 [SRP 库](https://github.com/secure-remote-password/implementations)中找到。 SDKs

```
PASSWORD_CLAIM_SECRET_BLOCK = SECRET_BLOCK
TIMESTAMP = "Tue May 7 00:09:40 UTC 2025"
k = SHA256(N || g) as a non-negative integer in big-endian
u = SHA256(SRP_A || SRP_B) as a non-negative integer in big-endian
x = SHA256(salt || SHA256(DeviceGroupKey || DeviceKey || ":" || DeviceSecret)) as a non-negative integer in big-endian
S_USER = (SRP_B - k * g^x)^(a + u * x) % N
K_USER = HKDF_HMAC_SHA256(salt=u, ikm=S_USER, info="Caldera Derived Key", length=16 bytes)
PASSWORD_CLAIM_SIGNATURE = Base64(HMAC_SHA256(key=K_USER, message=(DeviceGroupKey || DeviceKey || PASSWORD_CLAIM_SECRET_BLOCK || TIMESTAMP)))
```

## 查看、更新和忘记设备
<a name="user-pools-remembered-devices-viewing-updating-forgetting"></a>

您可以使用 Amazon Cognito API 在应用程序中实现以下特征。

1. 显示有关用户的当前设备的信息。

1. 显示用户的所有设备的列表。

1. 忘记设备。

1. 更新设备记住的状态。

授权以下描述中的 API 请求的访问令牌必须包含 `aws.cognito.signin.user.admin` 范围。Amazon Cognito 会将此范围的声明添加到您使用 Amazon Cognito 用户池 API 生成的所有访问令牌中。第三方 IdPs 必须为其向 Amazon Cognito 进行身份验证的用户单独管理设备和 MFA。在托管登录中，您可以请求 `aws.cognito.signin.user.admin` 范围，但是托管登录会自动将设备信息添加到高级安全用户日志中，而不提供记住设备的功能。

**显示有关设备的信息**  
您可以查询有关用户设备的信息，以确定设备当前是否仍在使用中。例如，您可能希望在记住的设备已有 90 天未登录后将其停用。
+ 要在公共客户端应用程序中显示用户的设备信息，请在 [GetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetDevice.html)API 请求中提交用户的访问密钥和设备密钥。
+ 要在机密客户端应用程序中显示用户的设备信息，请使用 AWS 凭据签署 [AdminGetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminGetDevice.html)API 请求并提交用户的用户名、设备密钥和用户池。

**显示用户的所有设备的列表**  
您可以显示用户的所有设备及其属性的列表。例如，您可能要验证当前设备是否与记住的设备相匹配。
+ 在公共客户端应用程序中，在 [ListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListDevices.html)API 请求中提交用户的访问令牌。
+ 在机密客户端应用程序中，使用 AWS 凭据签署 [AdminListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminListDevices.html)API 请求并提交用户的用户名和用户池。

**忘记设备**  
您可以删除用户的设备密钥。当您确定您的用户不再使用设备时，或者当您检测到异常活动并希望提示用户再次完成 MFA 时，您可能需要这样做。要稍后再次注册设备，必须生成并存储新的设备密钥。
+ 在公共客户端应用程序中，在 [ForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgetDevice.html)API 请求中提交用户的设备密钥和访问令牌。
+ 在机密客户端应用程序中，在 [AdminForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminForgetDevice.html)API 请求中提交用户的设备密钥和访问令牌。

# 使用 Amazon Pinpoint 进行用户池分析
<a name="cognito-user-pools-pinpoint-integration"></a>

**注意**  
**终止支持通知：** AWS 将于 2026 年 10 月 30 日终止对亚马逊 Pinpoint 的支持。2026 年 10 月 30 日之后，您将不再能够访问 Amazon Pinpoint 控制台或 Amazon Pinpoint 资源（端点、分段、活动、旅程和分析）。有关更多信息，请参阅 [Amazon Pinpoint 终止支持](https://docs.aws.amazon.com/console/pinpoint/migration-guide)。**注意：** APIs 与短信相关、语音、移动推送、OTP 和电话号码验证不受此更改的影响，并受 AWS 最终用户消息的支持。

Amazon Pinpoint 用户池与 Amazon Pinpoint 集成，为 Amazon Cognito 用户池提供分析并丰富 Amazon Pinpoint 活动的用户数据。Amazon Pinpoint 提供分析和有针对性的市场活动，以使用推送通知推动用户与移动应用程序的交互。借助 Amazon Cognito 用户池中的 Amazon Pinpoint 分析支持，您可以在 Amazon Pinpoint 控制台中跟踪用户池注册、登录、身份验证失败、每日活跃用户 DAUs () 和每月活跃用户 () MAUs。您可以深入查看不同日期范围或属性的数据，例如设备平台、设备区域设置和应用程序版本。

您还可以为应用程序设置自定义属性。然后可以使用这些属性在 Amazon Pinpoint 上对用户进行细分，并向他们发送有针对性的推送通知。如果您在 Amazon Cognito 控制台的**应用程序客户端**菜单中为应用程序客户端的**分析**配置选择**与 Amazon Pinpoint 共享用户属性数据**，Amazon Pinpoint 将会为用户电子邮件地址和电话号码创建其他端点。

当您使用 Amazon Cognito 控制台在用户池中激活 Amazon Pinpoint 分析时，您还会创建一个[服务相关角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html#service-linked-role-permissions)，Amazon Cognito 在向 Amazon Pinpoint 发出针对用户池的 API 请求时代入该角色。添加您的分析配置的 IAM 委托人必须拥有[CreateServiceLinkedRole](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateServiceLinkedRole.html)权限。服务相关角色是。[AWSServiceRoleForAmazonCognitoIdp](https://console.aws.amazon.com/iamv2/home?region=us-east-1#/roles/details/AWSServiceRoleForAmazonCognitoIdp)有关更多信息，请参阅 [对 Amazon Cognito 使用服务相关角色](using-service-linked-roles.md)。

当您在 Amazon Cognito API 中向应用程序客户端应用 `AnalyticsConfiguration` 时，您可以为 Amazon Pinpoint 分配自定义 IAM 角色和外部 ID 来代入该角色。此角色必须信任 `cognito-idp` 服务主体，如果角色信任策略需要外部 ID，则它必须与您的 `AnalyticsConfiguration` 相匹配。您必须针对 **Amazon Pinpoint 项目**向该角色授予 `cognito-idp:Describe*` 权限和以下权限。
+ `mobiletargeting:UpdateEndpoint`
+ `mobiletargeting:PutEvents`

## Amazon Cognito 和 Amazon Pinpoint 区域可用性
<a name="cognito-user-pools-find-region-mappings"></a>

下表显示了满足以下条件之一的 Amazon Cognito 和 Amazon Pinpoint 之间的 AWS 区域 映射。
+ 您只能在美国东部（弗吉尼亚州北部）（us-east-1）区域使用 Amazon Pinpoint 项目。
+ 您可以在相同的区域*或者*在美国东部（弗吉尼亚州北部）（us-east-1）区域使用 Amazon Pinpoint 项目

默认情况下，Amazon Cognito 只能向位于相同 AWS 区域中的 Amazon Pinpoint 项目发送分析。此规则的例外情况是下表中的区域，以及 Amazon Pinpoint 不可用的区域。

Amazon Pinpoint 未在以下区域推出。这些地区的 Amazon Cognito 用户池不支持分析。
+ Europe (Milan)
+ 中东（巴林）
+ 亚太地区（大阪）
+ 以色列（特拉维夫）
+ 非洲（开普敦）
+ 亚太地区（雅加达）
+ 亚太地区（马来西亚）

表中显示了您构建 Amazon Cognito 用户池的区域与 Amazon Pinpoint 中对应区域的关系。您必须在可用区域中配置 Amazon Pinpoint 项目，才能将其与 Amazon Cognito 集成。


| Amazon Cognito 用户池区域 | Amazon Pinpoint 项目所在区域 | 
| --- | --- | 
|  ap-northeast-1  |  us-east-1  | 
|  ap-northeast-2  |  us-east-1  | 
|  ap-south-1  |  us-east-1、ap-sou1  | 
|  ap-southeast-1  |  us-east-1  | 
|  ap-southeast-2  |  us-east-1、ap-southeast-2  | 
|  ca-central-1  |  us-east-1  | 
|  eu-central-1  |  us-east-1、eu-central-1  | 
|  eu-west-1  |  us-east-1、eu-west-1  | 
|  eu-west-2  |  us-east-1  | 
|  us-east-1  |  us-east-1  | 
|  us-east-2  |  us-east-1  | 
|  us-west-2  |  us-east-1、us-west-2  | 

**区域映射示例**
+ 如果您在 ap-northest-1 中创建用户池，则可以在 us-east-1 中创建您的 Amazon Pinpoint 项目。
+ 如果您在 ap-south-1 中创建用户池，则可以在 us-east-1 或 ap-south-1 中创建您的 Amazon Pinpoint 项目。

**注意**  
除了上表中的项目 AWS 区域 外，Amazon Cognito 只能使用与您的用户池位于同一区域的 Amazon Pinpoint 项目。如果 Amazon Pinpoint 在您构建用户池的区域中不可用且未在表中列出，那么 Amazon Cognito 在该区域不支持 Amazon Pinpoint 分析。有关详细的 AWS 区域 信息，请参阅 [Amazon Pinpoint 端点和配额](https://docs.aws.amazon.com/general/latest/gr/pinpoint.html)。

### 指定 Amazon Pinpoint 分析设置（AWS 管理控制台）
<a name="cognito-user-pools-pinpoint-integration-console"></a>

您可以配置 Amazon Cognito 用户池以向 Amazon Pinpoint 发送分析数据。Amazon Cognito 仅为本地用户将分析数据发送到 Amazon Pinpoint。将您的用户池配置为与 Amazon Pinpoint 项目关联后，您必须在 API 请求中包含 `AnalyticsMetadata`。有关更多信息，请参阅 [将您的应用程序与 Amazon Pinpoint 集成](#cognito-user-pools-pinpoint-integration-client)。

**指定分析设置**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。系统可能会提示您输入 AWS 凭证。

1. 选择 **User Pools**（用户池）并从列表中选择一个现有的用户池。

1. 选择**应用程序客户端**菜单，然后选择要更新的应用程序客户端。

1. 在**分析**选项卡的**精确定位分析**下，选择**启用**。

1. 选择 **Pinpoint Region**（Pinpoint 区域）。

1. 选择 **Amazon Pinpoint project**（Amazon Pinpoint 项目）或者选择 **Create Amazon Pinpoint project**（创建 Amazon Pinpoint 项目）。
**注意**  
Amazon Pinpoint 项目 ID 是 Amazon Pinpoint 项目特有的由 32 个字符组成的字符串。它在 Amazon Pinpoint 控制台中列出。  
您可以将多个 Amazon Cognito 应用程序映射到单个 Amazon Pinpoint 项目。但是，每个 Amazon Cognito 应用程序只能映射到一个 Amazon Pinpoint 项目。  
在 Amazon Pinpoint 中，每个项目都应该是单个应用程序。例如，如果游戏开发员有两款游戏，每款游戏应该是单独的 Amazon Pinpoint 项目，即使这两款游戏使用同一 Amazon Cognito 用户池。有关 Amazon Pinpoint 项目的更多信息，请参阅[在 Amazon Pinpoint 中创建项目](https://docs.aws.amazon.com/push-notifications/latest/userguide/mobile-push.html#mobile-push-create-project)。

1. 在 **User data sharing**（用户数据共享）下，如果您希望 Amazon Cognito 发送电子邮件地址和电话号码到 Amazon Pinpoint 并为用户创建额外的端点，则选择 **Share user data with Amazon Pinpoint**（与 Amazon Pinpoint 共享用户数据）。用户验证其电子邮件地址和电话号码后，Amazon Cognito 只在它们可用于用户账户时才会与 Amazon Pinpoint 共享。
**注意**  
*端点*唯一地标识可以使用 Amazon Pinpoint 向其发送推送通知的用户设备。有关端点的更多信息，请参阅《Amazon Pinpoint 开发人员指南》**中的[添加端点](https://docs.aws.amazon.com/pinpoint/latest/developerguide/endpoints.html)。

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

### 指定亚马逊 Pinpoint 分析设置（AWS CLI 和 AWS API）
<a name="cognito-user-pools-pinpoint-integration-cli-api"></a>

使用以下命令为您的用户池指定 Amazon Pinpoint 分析设置。

**在创建应用程序时为用户池的现有客户端应用程序指定分析设置**
+ AWS CLI: `aws cognito-idp create-user-pool-client`
+ AWS API: [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)

**为用户池的现有客户端应用程序更新分析设置**
+ AWS CLI: `aws cognito-idp update-user-pool-client`
+ AWS API: [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)

**注意**  
在您使用`ApplicationArn`时，Amazon Cognito 支持区域内集成

## 将您的应用程序与 Amazon Pinpoint 集成
<a name="cognito-user-pools-pinpoint-integration-client"></a>

您可以在*用户池 API* 中针对 Amazon Cognito *本地用户*将分析元数据发布到 Amazon Pinpoint。

**本地用户**  
注册了账户或在您的用户池中创建的用户，而不是通过第三方身份提供者 (IdP) 登录的用户。

**用户池 API**  
您可以使用带有自定义用户界面 (UI) 的应用程序与 S AWS DK 集成的操作。您无法为通过托管登录进行登录的联合身份用户或本地用户传递分析元数据。有关用户池 API 操作的列表，请参阅 [Amazon Cognito API 参考](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html)。

在您将用户池配置为发布到活动后，Amazon Cognito 会将以下 API 操作的元数据传递给 Amazon Pinpoint。
+ `AdminInitiateAuth`
+ `AdminRespondToAuthChallenge`
+ `ConfirmForgotPassword`
+ `ConfirmSignUp`
+ `ForgotPassword`
+ `InitiateAuth`
+ `ResendConfirmationCode`
+ `RespondToAuthChallenge`
+ `SignUp`

要将有关用户会话的元数据传递到 Amazon Pinpoint 活动，请在 API 请求的 `AnalyticsMetadata` 参数中包含 `AnalyticsEndpointId` 值。 JavaScript 例如，请参阅[为什么我的 Amazon Cognito 用户池分析没有显示在我的 Amazon Pinpoint 控制面板上？](https://aws.amazon.com/premiumsupport/knowledge-center/pinpoint-cognito-user-pool-analytics/) 在*AWS 知识中心*中。

# Amazon Cognito 用户池的电子邮件设置
<a name="user-pool-email"></a>

应用程序中的某些事件可能导致 Amazon Cognito 向用户发送电子邮件。例如，如果您将用户池配置为需要电子邮件验证，则当用户在应用程序中注册新账户或重置其密码时，Amazon Cognito 会发送电子邮件。根据发起电子邮件递送的操作，电子邮件将包含验证码或临时密码。

为处理电子邮件递送，您可以使用以下任一选项：
+ 内置于 Amazon Cognito 服务中的[默认电子邮件配置](#user-pool-email-default)。
+ [您的 Amazon Simple Email Service (Amazon SES) 配置](#user-pool-email-developer)。

创建用户池后，您可以更改传递选项。

Amazon Cognito 会向您的用户发送电子邮件，其中包含用户可以输入的代码或用户可以选择的 URL 链接。下表显示了可以生成电子邮件的事件。

**消息选项**


| Activity | API 操作 | 传递选项 | 格式选项 | 可自定义 | [消息模板](cognito-user-pool-settings-message-customizations.md) | 
| --- |--- |--- |--- |--- |--- |
| 忘记密码 | [ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html), [AdminResetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminResetUserPassword.html) | 电子邮件、短信 | 代码 | 是 | 验证消息 | 
| 邀请 | [AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html) | 电子邮件、短信 | 代码 | 是 | 邀请消息 | 
| 自行注册 | [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html), [ResendConfirmationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html) | 电子邮件、短信 | 代码，链接 | 是 | 验证消息 | 
| 电子邮件地址或电话号码验证 | [UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html), [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html), [GetUserAttributeVerificationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAttributeVerificationCode.html) | 电子邮件、短信 | 代码 | 是 | 验证消息 | 
| 多重身份验证 (MFA) | [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) | 电子邮件¹、短信、身份验证器应用程序 | 代码 | 是² | MFA 消息 | 
| 一次性密码认证 (OTP) | [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) | 电子邮件¹、短信 | 代码 | 是 | MFA 消息 ³ | 

¹ 需要基础版[功能计划](cognito-sign-in-feature-plans.md)或更高版本以及 [Amazon SES 电子邮件配置](#user-pool-email-developer)。

² 用于短信和电子邮件消息。

³ 只有在用户池中必须或可以选择使用 MFA 时，才能自定义 MFA 消息模板。当 MFA 处于非活动状态时，Amazon Cognito 会使用默认模板发送一次性密码。

Amazon SES 会对电子邮件收费。有关详情，请参阅 [Amazon SES 定价](https://aws.amazon.com/ses/pricing/)。

要了解有关电子邮件 MFA 的更多信息，请参阅 [短信和电子邮件消息 MFA](user-pool-settings-mfa-sms-email-message.md)。

Amazon Cognito 可能会在短时间内阻止向单个目的地传送额外的电子邮件或短信。如果您认为自己的用户池受到了影响，请配置并查看[日志中是否存在消息传送错误](exporting-quotas-and-usage.md#exporting-quotas-and-usage-messages)，然后联系您的账户团队。

## 默认电子邮件配置
<a name="user-pool-email-default"></a>

Amazon Cognito 可以使用其默认电子邮件配置为您处理电子邮件递送。当您使用默认选项时，Amazon Cognito 会限制您的用户池每天可以发送的电子邮件数量。有关服务限制的更多信息，请参阅 [Amazon Cognito 中的限额](quotas.md)。对于典型的生产环境，默认的电子邮件限制低于所需的递送量。要启用更高的送达量，您可使用您的 Amazon SES 电子邮件配置。

当您使用默认配置时，您将使用 AWS 管理的 Amazon SES 资源来发送电子邮件消息。Amazon SES 将返回[查无此人的邮件](https://docs.aws.amazon.com/ses/latest/dg/send-email-concepts-deliverability.html#send-email-concepts-deliverability-bounce)的电子邮件地址添加到[账户级禁止列表](https://docs.aws.amazon.com/ses/latest/dg/sending-email-suppression-list.html)或[全局禁止列表](https://docs.aws.amazon.com/ses/latest/dg/send-email-concepts-deliverability.html#send-email-concepts-deliverability-suppression-list)。如果无法送达的电子邮件地址稍后变为可送达，则当您的用户池配置为使用默认配置时，您无法控制将其从禁止列表中删除的行为。电子邮件地址可以无限期地保留在 AWS管理的禁止列表中。要管理无法送达的电子邮件地址，请将 Amazon SES 电子邮件配置与账户级别的禁止列表一起使用，如下一节中所述。

使用默认电子邮件配置时，您可以使用以下任一电子邮件地址作为 FROM 地址：
+ 默认电子邮件地址 *no-reply@verificationemail.com*。
+ 自定义电子邮件地址。在可以使用您自己的电子邮件地址之前，您必须向 Amazon SES 验证此地址，并且向 Amazon Cognito 授予使用此地址的权限。

## Amazon SES 电子邮件配置
<a name="user-pool-email-developer"></a>

您的应用程序需要的递送量可能高于默认选项所提供的递送量。要增加可能的递送量，请将您的 Amazon SES 资源与用户池一起使用来向用户发送电子邮件。当您使用自己的 Amazon SES 配置发送电子邮件消息时，您还可以[监控您的电子邮件发送活动](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/monitor-sending-activity.html)。

在可以使用您的 Amazon SES 配置之前，您必须向 Amazon SES 验证一个或多个电子邮件地址或域。将经验证的电子邮件地址或已验证域的地址，用作分配给用户池的 FROM 电子邮件地址。当 Amazon Cognito 向您的用户发送电子邮件时，它会以您的名义调用 Amazon SES 并使用您的电子邮件地址。

当您使用 Amazon SES 配置时，以下条件适用：
+ 您的用户池的电子邮件传送限制与适用于您的 AWS 账户中的 Amazon SES 验证电子邮件地址的限制相同。
+ 您可以使用 Amazon SES 中覆盖[全局禁止列表](https://docs.aws.amazon.com/ses/latest/dg/send-email-concepts-deliverability.html#send-email-concepts-deliverability-suppression-list)的账户级禁止列表来管理发送到无法送达的电子邮件地址的邮件。当您使用账户级禁止列表时，退回的电子邮件消息会影响您的账户作为发件人的声誉。有关更多信息，请参阅《Amazon Simple Email Service 开发人员指南》中的[使用 Amazon SES 账户级禁止列表](https://docs.aws.amazon.com/ses/latest/dg/sending-email-suppression-list.html)。

### Amazon SES 电子邮件配置区域
<a name="user-pool-email-developer-region-mapping"></a>

 AWS 区域 在 Amazon SES 中配置电子邮件时，创建用户池的位置有三个要求之一。您可以从与您的用户池相同的区域、多个区域（包括相同区域），或者一个或多个远程区域通过 Amazon SES 发送电子邮件消息。为了获得出色性能，在您可以选择的情况下，在与您的用户池相同的区域中，通过经 Amazon SES 验证的身份发送电子邮件。经过 Amazon SES 验证的身份的区域要求类别

**仅限区域内**  
您的用户池可以像用户池 AWS 区域 一样发送身份经过验证的电子邮件。在没有自定义 `FROM` 电子邮件地址的默认电子邮件配置中，Amazon Cognito 使用同一区域中的 `no-reply@verificationemail.com` 已验证身份。

**向后兼容**  
您的用户池可以在相同 AWS 区域 或以下备用区域之一发送身份经过验证的电子邮件：  
+ 美国东部（弗吉尼亚州北部）
+ 美国西部（俄勒冈州）
+ 欧洲地区（爱尔兰）
此特征支持您可能在 Amazon Cognito 服务启动时为了满足当时的要求而创建的用户池资源的连续性。该时期的用户池只能在有限的数量内发送身份经过验证的电子邮件 AWS 区域。在没有自定义 `FROM` 电子邮件地址的默认电子邮件配置中，Amazon Cognito 使用同一区域中的 `no-reply@verificationemail.com` 已验证身份。

**备用区域**  
您的用户池可以在用户池区域之外的备用 AWS 区域 地址发送身份经过验证的电子邮件。当 Amazon SES 在提供 Amazon Cognito 的区域不可用时，就会出现这种配置。  
Amazon SES 在备用区域发送经过验证的身份的授权策略时，必须信任来源区域的 Amazon Cognito 服务主体。有关更多信息，请参阅 [授予权限以使用默认的电子邮件配置](#user-pool-email-permissions-default)。  
在其中一些区域，对于默认的 `COGNITO_DEFAULT` 电子邮件配置，Amazon Cognito 在两个备用区域之间拆分电子邮件消息。在这些情况下，要使用自定义 `FROM` 电子邮件地址，Amazon SES 在每个备用区域发送经过验证的身份的授权策略时，必须信任来源区域的 Amazon Cognito 服务主体。有关更多信息，请参阅 [授予权限以使用默认的电子邮件配置](#user-pool-email-permissions-default)。借助这些区域中的 `DEVELOPER` Amazon SES 电子邮件配置，您必须在*第一个*列出的区域中使用经过验证的身份，并将其配置为信任用户池区域中的 Amazon Cognito 服务主体。例如，在中东（阿联酋）的用户池中，将欧洲地区（法兰克福）经过验证的身份配置为信任 `cognito-idp.me-central-1.amazonaws.com`。在没有自定义 `FROM` 电子邮件地址的默认电子邮件配置中，Amazon Cognito 使用每个区域中的 `no-reply@verificationemail.com` 已验证身份。

**注意**  
在以下条件组合下，必须在 Region 元素中[EmailConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-EmailConfiguration)使用通配符指定`SourceArn`参数，格式为`arn:${Partition}:ses:*:${Account}:identity/${IdentityName}`。这允许您的用户池发送两者中都具有相同已验证身份 AWS 账户 的电子邮件 AWS 区域。  
你的 EmailSendingAccount 是`COGNITO_DEFAULT`。
您想使用自定义 `FROM` 地址。
您的用户池在**备用区域**发送电子邮件。
您的用户池在后面的 **Amazon SES 支持区域**表中指定了*第二个*[1](#cognito-email-alternate-regions-note) **备用区域**。

如果您使用软件开发工具包、Amazon Cognito API 或 CLI、或以编程方式创建用户池，则您的用户池将 AWS CDK使用参数 AWS CloudFormation为您的用户池指定的 Amazon SES 身份发送电子邮件。 AWS `SourceArn` [EmailConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-EmailConfiguration)Amazon SES 身份必须占据支持 AWS 区域的。如果您的 `EmailSendingAccount` 是 `COGNITO_DEFAULT` 而且您没有指定 `SourceArn` 参数，则 Amazon Cognito 使用您创建用户池所在区域中的资源，从 `no-reply@verificationemail.com` 发送电子邮件。

下表显示了您可以在 Amazon Cognito 上使用 Amazon SES 身份 AWS 区域 的地方。


| 用户池区域 | 区域选项 | Amazon SES 支持的区域 | 
| --- | --- | --- | 
|  美国东部（弗吉尼亚州北部）  |  向后兼容  |  美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  美国东部（俄亥俄州）  |  向后兼容  |  美国东部（俄亥俄）、美国东部（弗吉尼亚北部）、欧洲（爱尔兰）  | 
|  美国西部（北加利福尼亚）  |  仅限区域内  |  美国西部（北加利福尼亚）  | 
|  美国西部（俄勒冈州）  |  向后兼容  |  美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  加拿大（中部）  |  向后兼容  |  加拿大（中部）、美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  加拿大西部（卡尔加里）  |  备用区域  |  加拿大（中部）、美国西部（北加利福尼亚）[1](#cognito-email-alternate-regions-note)  | 
|  墨西哥（中部）  |  备用区域  |  美国东部（弗吉尼亚州北部）、美国西部（俄勒冈州）[1](#cognito-email-alternate-regions-note)  | 
|  亚太地区（东京）  |  向后兼容  |  亚太地区（东京）、美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  亚太地区（香港）  |  备用区域  |  亚太地区（新加坡）、亚太地区（东京）[1](#cognito-email-alternate-regions-note)  | 
|  亚太地区（首尔）  |  向后兼容  |  亚太地区（首尔）、美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
| 亚太地区（马来西亚） | 备用区域 | 亚太地区（悉尼）、亚太地区（新加坡）[1](#cognito-email-alternate-regions-note) | 
| 亚太地区（泰国） | 备用区域 | 亚太地区（新加坡）、亚太地区（孟买）[1](#cognito-email-alternate-regions-note) | 
|  亚太地区（孟买）  |  向后兼容  |  亚太地区（孟买）、美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  亚太地区（海得拉巴）  |  备用区域  |  亚太地区（孟买）、亚太地区（新加坡）[1](#cognito-email-alternate-regions-note)  | 
|  亚太地区（新加坡）  |  向后兼容  |  亚太地区（新加坡）、美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  亚太地区（悉尼）  |  向后兼容  |  亚太地区（悉尼）、美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  亚太地区（大阪）  |  仅限区域内  |  亚太地区（大阪）  | 
|  亚太地区（雅加达）  |  仅限区域内  |  亚太地区（雅加达）  | 
|  亚太地区（墨尔本）  |  备用区域  |  亚太地区（悉尼）、亚太地区（新加坡）[1](#cognito-email-alternate-regions-note)  | 
|  欧洲地区（爱尔兰）  |  向后兼容  |  美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  欧洲地区（伦敦）  |  向后兼容  |  欧洲（伦敦）、美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  欧洲地区（巴黎）  |  仅限区域内  |  欧洲地区（巴黎）  | 
|  欧洲地区（法兰克福）  |  向后兼容  |  欧洲（法兰克福）、美国东部（弗吉尼亚北部）、美国西部（俄勒冈）、欧洲（爱尔兰）  | 
|  欧洲（苏黎世）  |  备用区域  |  欧洲地区（法兰克福）、欧洲地区（伦敦）[1](#cognito-email-alternate-regions-note)  | 
|  欧洲地区（斯德哥尔摩）  |  仅限区域内  |  欧洲地区（斯德哥尔摩）  | 
| 欧洲地区（米兰） |  仅限区域内  | 欧洲地区（米兰） | 
| 欧洲（西班牙） |  备用区域  | 欧洲地区（巴黎）、欧洲地区（斯德哥尔摩）[1](#cognito-email-alternate-regions-note) | 
|  中东（巴林）  |  仅限区域内  |  中东（巴林）  | 
|  中东（阿联酋）：  |  备用区域  |  欧洲地区（法兰克福）、欧洲地区（伦敦）[1](#cognito-email-alternate-regions-note)  | 
|  南美洲（圣保罗）  |  仅限区域内  |  南美洲（圣保罗）  | 
|  以色列（特拉维夫）  |  仅限区域内  |  以色列（特拉维夫）  | 
|  非洲（开普敦）  |  仅限区域内  |  非洲（开普敦）  | 

 1在具有默认电子邮件配置的用户池中使用。Amazon Cognito 在每个区域中通过具有相同电子邮件地址的经验证身份来分发电子邮件。要使用自定义 `FROM` 地址，请使用格式为 `arn:${Partition}:ses:*:${Account}:identity/${IdentityName}` 的 `SourceArn` 参数来配置 `EmailConfiguration`。

## 为您的用户池配置电子邮件
<a name="user-pool-email-configure"></a>

完成以下步骤为用户池配置电子邮件设置。根据您要使用的设置，您可能需要 Amazon SES、 AWS Identity and Access Management （IAM）和 Amazon Cognito 中的 IAM 权限。

**注意**  
您在这些步骤中创建的资源无法跨 AWS 账户进行共享。例如，您不能为一个账户中的用户池配置用户池，然后将其用于另一个账户中的 Amazon SES 电子邮件地址。如果您在多个账户中使用 Amazon Cognito，请为每个账户中重复这些步骤。

### 步骤 1：使用 Amazon SES 验证电子邮件地址或域
<a name="user-pool-email-configure-verify-ses"></a>

在配置您的用户池之前，如果您要执行以下任一操作，则必须使用 Amazon SES 验证一个或多个电子邮件地址或域：
+ 使用您自己的电子邮件地址作为 FROM 地址
+ 使用您的 Amazon SES 配置处理电子邮件送达

通过验证您的电子邮件地址或域，您确认您拥有该电子邮件地址，这有助于防止未经授权的使用。

有关使用 Amazon SES 验证电子邮件地址的更多信息，请参阅 *Amazon Simple Email Service 开发人员指南*中的[验证电子邮件地址](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-email-addresses-procedure.html)。有关使用 Amazon SES 验证域的信息，请参阅[验证域](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domains.html)。

### 步骤 2：将您的账户移出 Amazon SES 沙盒
<a name="user-pool-email-configure-sandbox"></a>

如果您使用的是默认 Amazon Cognito 电子邮件配置，则跳过此步骤。

当你第一次在任何地方使用 Amazon SES 时 AWS 区域，它会将你置 AWS 账户 于该地区的 Amazon SES 沙箱中。Amazon SES 使用沙盒防止欺诈和滥用。如果您使用您的 Amazon SES 配置来处理电子邮件送达，则必须将您的 AWS 账户 移出沙盒，然后 Amazon Cognito 才能向用户发送电子邮件。

在沙盒中，Amazon SES 会对您可以发送的电子邮件数量和可以发送电子邮件的位置施加限制。您可以仅向已通过 Amazon SES 验证的地址和域发送电子邮件，也可以将其发送到 Amazon SES 邮箱模拟器地址。在您 AWS 账户 仍处于沙箱状态时，请不要将您的 Amazon SES 配置用于生产中的应用程序。在这种情况下，Amazon Cognito 无法将邮件发送到您用户的电子邮件地址。

要将您 AWS 账户 从沙箱中移除，请参阅[《亚马逊*简单电子邮件服务开发者指南》中的移出 Amazon* SES 沙箱](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html)。

### 步骤 3：授予 Amazon Cognito 电子邮件权限
<a name="user-pool-email-permissions"></a>

您可能需要向 Amazon Cognito 授予特定权限，然后它才能向您的用户发送电子邮件。您授予的权限以及用于授予权限的过程取决于您使用的是默认电子邮件配置还是您的 Amazon SES 配置。

#### 授予权限以使用默认的电子邮件配置
<a name="user-pool-email-permissions-default"></a>

仅当您将用户池配置为**使用 Cognito 发送电子邮件**或将 `EmailSendingAccount` 设置为 `COGNITO_DEFAULT` 时，才能完成此步骤。

使用默认的电子邮件配置，您的用户池可以使用以下任一地址发送电子邮件。
+ 默认地址 `no-reply@verificationemail.com`。
+ 来自您在 Amazon SES 中的已验证电子邮件地址或域的自定义 FROM 地址。

如果您使用自定义地址，Amazon Cognito 需要额外权限，以便使用此地址向您的用户发送电子邮件。通过 Amazon SES 中地址或域的[发送授权策略](https://docs.aws.amazon.com/ses/latest/dg/sending-authorization.html)来授予这些权限。如果您使用 Amazon Cognito 控制台向您的用户池添加自定义地址，此策略会自动附加到 Amazon SES 验证的电子邮件地址。但是，如果您在控制台之外配置用户池，例如使用 AWS CLI 或 Amazon Cognito API，则必须使用 A [mazon SES 控制台](https://console.aws.amazon.com/ses/)或 API 附加策略。[PutIdentityPolicy](https://docs.aws.amazon.com/ses/latest/APIReference/API_PutIdentityPolicy.html)

**注意**  
您只能使用 AWS CLI 或 Amazon Cognito API 在已验证的域中配置 FORM 地址。

发送授权策略根据使用 Amazon Cognito 调用 Amazon SES 的账户资源，来允许或拒绝访问。有关基于资源的策略的更多信息，请参阅 [IAM 用户指南](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_resource-based)。在 [Amazon SES 开发人员指南](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-policy-examples.html)中可以找到基于资源的策略示例。

**Example 发送授权策略**  
以下示例发送授权策略授予 Amazon Cognito 使用经 Amazon SES 验证的身份的有限能力。Amazon Cognito 在代表 `aws:SourceArn` 中的用户池和 `aws:SourceAccount` 条件中的账户时才能发送电子邮件。  
用户池区域或备用区域中的发送授权策略必须允许 Amazon Cognito 服务主体发送电子邮件消息。有关更多信息，请参阅[区域表](#ses-regions-table)。如果您的**用户池区域**与 **Amazon SES 区域**中的至少一个值匹配，请在以下示例中使用全局服务主体配置您的发送授权策略。    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "stmnt1234567891234",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "email.cognito-idp.amazonaws.com"
                ]
            },
            "Action": [
                "SES:SendEmail",
                "SES:SendRawEmail"
            ],
            "Resource": "arn:aws:ses:us-east-1:111122223333:identity/support@example.com",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "111122223333"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:cognito-idp:us-east-1:111122223333:userpool/us-east-1_EXAMPLE"
                }
            }
        }
    ]
}
```
在可用 Amazon Cognito AWS 区域 的地方，Amazon SES 并非在所有可选模式中都可用。中东（阿联酋）是一个例子，只能在欧洲地区（法兰克福）（`eu-central-1`）使用经过验证的身份发送电子邮件。在使用默认电子邮件配置的用户池中，Amazon Cognito 也会在这两个区域中的每一个使用经过验证的身份发送电子邮件消息。就中东（阿联酋）而言，新增区域是欧洲地区（伦敦）。您必须更新两个区域中的发送授权策略。  
每个备用区域中的发送授权策略必须允许用户池选择加入区域中的 Amazon Cognito 服务主体发送电子邮件消息。有关更多信息，请参阅[区域表](#ses-regions-table)。如果您的区域标记为**备用区域**，请使用区域服务主体配置您的发送授权策略，如下例所示。根据需要将示例区域标识*me-central-1*符替换为所需的区域 ID。    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "cognito-idp.me-central-1.amazonaws.com"
                ]
            },
            "Action": [
                "SES:SendEmail",
                "SES:SendRawEmail"
            ],
            "Resource": "arn:aws:ses:us-east-1:111122223333:identity/support@example.com",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "111122223333"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:cognito-idp:us-east-1:111122223333:userpool/us-east-1_EXAMPLE"
                }
            }
        }
    ]
}
```
有关策略语法的更多信息，请参阅《Amazon Simple Email Service 开发人员指南》**中的 [Amazon SES 发送授权策略](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-policies.html)。  
有关更多示例，请参阅《Amazon Simple Email Service 开发人员指南》**中的 [Amazon SES 发送授权策略示例](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-policy-examples.html)。

#### 授予权限以使用您的 Amazon SES 配置
<a name="user-pool-email-permissions-developer"></a>

如果您将用户池配置为使用您的 Amazon SES 配置，Amazon Cognito 在向用户发送电子邮件时，需要额外的权限代表您调用 Amazon SES。此授权将通过 IAM 服务授予。

当您使用此选项配置用户池时，Amazon Cognito 将创建一个*服务相关角色*，这是您 AWS 账户中的一种 IAM 角色类型。此角色包含允许 Amazon Cognito 访问 Amazon SES 并使用您的地址发送电子邮件的权限。

Amazon Cognito 使用设置配置的用户会话的 AWS 凭证创建您的服务相关角色。此会话的 IAM 权限必须包括 `iam:CreateServiceLinkedRole` 操作。有关 IAM 中权限的更多信息，请参阅 I *AM 用户指南*中的[AWS 资源访问管理](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html)。

有关 Amazon Cognito 创建的服务相关角色的更多信息，请参阅[对 Amazon Cognito 使用服务相关角色](using-service-linked-roles.md)。

### 步骤 4：配置用户池
<a name="user-pool-email-configure-user-pool"></a>

如果您要将您的用户池配置为使用以下内容，请完成以下步骤：
+ 自定义 FROM 地址（显示为电子邮件发件人）。
+ 自定义 REPLY-TO 地址，用于接收您的用户发送到您的 FROM 地址的邮件
+ Amazon SES 配置

**注意**  
如果您的已验证身份是一个电子邮件地址，Amazon Cognito 会默认将该电子邮件地址设置为 FROM 和 REPLY-TO 电子邮件地址。但如果您的已验证身份是一个域，则必须为 FROM 电子邮件地址提供一个值。

如果您要使用默认 Amazon Cognito 电子邮件配置和地址，则跳过此过程。

**配置用户池以使用自定义电子邮件地址**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**身份验证方法**菜单，找到**电子邮件配置**，选择**编辑**。

1. 在 **Edit email configuration**（编辑电子邮件配置）页面中，选择 **Send email from Amazon SES**（使用 Amazon SES 发送电子邮件）或 **Send email with Amazon Cognito**（使用 Amazon Cognito 发送电子邮件）。仅当您选择 **Send email from Amazon SES**（使用 Amazon SES 发送电子邮件）时，您才可以自定义 **SES Region**（SES 区域）、**Configuration Set**（配置集） 和 **FROM sender name**（FROM 发件人姓名）。

1. 要使用自定义 FROM 地址，请完成以下步骤：

   1. 在 **SES region**（SES 区域）下，选择包含验证的电子邮件地址的区域。

   1. 在 **FROM email address**（FROM 电子邮件地址）下，选择您的电子邮件地址。使用您已通过 Amazon SES 验证的电子邮件地址。

   1. （可选）在 **Configuration set**（配置集）下，选择 Amazon SES 使用的配置集。进行此更改并保存可创建服务相关角色。

   1. （可选）在 **FROM sender address**（FROM 发件人地址）下，输入电子邮件地址。您可以仅提供电子邮件地址，也可以同时提供电子邮件地址和格式为 `Jane Doe <janedoe@example.com>` 的易记名称。

   1. （可选）在 **REPLY-TO email address**（REPLY-TO 电子邮箱地址）下，输入要用来接收用户发送到您的 FROM 地址的邮件的电子邮件地址。

1. 选择 **Save changes**（保存更改）。

**相关主题**
+ [自定义电子邮件验证消息](cognito-user-pool-settings-message-customizations.md#cognito-user-pool-settings-email-verification-message-customization)
+ [自定义用户邀请消息](cognito-user-pool-settings-message-customizations.md#cognito-user-pool-settings-user-invitation-message-customization)

# Amazon Cognito 用户池的短信设置
<a name="user-pool-sms-settings"></a>

您的用户池的某些 Amazon Cognito 事件可能会导致 Amazon Cognito 向您的用户发送短信。例如，如果您将用户池配置为需要电话验证，则当用户在应用程序中注册新账户或重置其密码时，Amazon Cognito 会发送短信。根据发起短信的操作，短信中将包含验证码、临时密码或欢迎消息。

Amazon Cognito 使用 Amazon Simple Notification Service (Amazon SNS) 传送短信。反过来，Amazon SNS 会将短信交给。 AWS End User Messaging SMS如果您是首次通过 Amazon Cognito 发送短信，则会将您 AWS End User Messaging SMS 置于[沙盒](https://docs.aws.amazon.com/sms-voice/latest/userguide/sandbox.html)环境中。在沙盒环境中，您可以对应用程序的 SMS 文本消息进行测试。在沙盒中，您只能模拟消息的发送。

**注意**  
2024 年 11 月， AWS 将 Amazon SNS 短信替换为。 AWS End User Messaging SMS目前，Amazon Cognito 控制台指的是 Amazon SNS 资源。用户池通过 Amazon SNS [发布](https://docs.aws.amazon.com/sns/latest/api/API_Publish.html)操作启动短信，该操作是直通的。 AWS End User Messaging SMS因此，您仍然必须为 `sns:Publish`，而不是 `sms-voice:SendTextMessage` 配置权限。

AWS End User Messaging SMS SMS 短信的费用。有关更多信息，请参阅[AWS End User Messaging SMS 定价](https://aws.amazon.com/end-user-messaging/pricing/)。

Amazon Cognito 会向您的用户发送带有他们可以输入的验证码的短信。下表显示了可以生成短信的事件。

**消息选项**


| Activity | API 操作 | 传递选项 | 格式选项 | 可自定义 | [消息模板](cognito-user-pool-settings-message-customizations.md) | 
| --- |--- |--- |--- |--- |--- |
| 忘记密码 | [ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html), [AdminResetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminResetUserPassword.html) | 电子邮件、短信 | 代码 | 是 | 验证消息 | 
| 邀请 | [AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html) | 电子邮件、短信 | 代码 | 是 | 邀请消息 | 
| 自行注册 | [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html), [ResendConfirmationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html) | 电子邮件、短信 | 代码，链接 | 是 | 验证消息 | 
| 电子邮件地址或电话号码验证 | [UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html), [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html), [GetUserAttributeVerificationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAttributeVerificationCode.html) | 电子邮件、短信 | 代码 | 是 | 验证消息 | 
| 多重身份验证 (MFA) | [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) | 电子邮件¹、短信、身份验证器应用程序 | 代码 | 是² | MFA 消息 | 
| 一次性密码认证 (OTP) | [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) | 电子邮件¹、短信 | 代码 | 是 | MFA 消息 ³ | 

¹ 需要基础版[功能计划](cognito-sign-in-feature-plans.md)或更高版本以及 [Amazon SES 电子邮件配置](user-pool-email.md#user-pool-email-developer)。

² 用于短信和电子邮件消息。

³ 只有在用户池中必须或可以选择使用 MFA 时，才能自定义 MFA 消息模板。当 MFA 处于非活动状态时，Amazon Cognito 会使用默认模板发送一次性密码。

AWS End User Messaging SMS SMS 消息的费用。有关更多信息，请参阅[AWS End User Messaging SMS 定价](https://aws.amazon.com/end-user-messaging/pricing/)。

要了解有关 MFA 的更多信息，请参阅 [短信和电子邮件消息 MFA](user-pool-settings-mfa-sms-email-message.md)。

Amazon Cognito 可能会在短时间内阻止向单个目的地传送额外的电子邮件或短信。如果您认为自己的用户池受到了影响，请配置并查看[日志中是否存在消息传送错误](exporting-quotas-and-usage.md#exporting-quotas-and-usage-messages)，然后联系您的账户团队。

## 最佳实践
<a name="user-pool-sms-settings-best-practices"></a>

由于全球范围内未经请求的短信流量巨大，一些政府在短信发送者和接收者之间设置了障碍。当您使用短信进行 MFA 和用户更新时，必须采取额外的步骤来确保您的短信已送达。您还必须监控用户可能居住的国家/地区的 SMS-message-related法规，并保持您的 SMS 消息配置处于最新状态。有关更多信息，请参阅《AWS End User Messaging SMS 用户指南》**中的[短信和彩信国家/地区功能和限制](https://docs.aws.amazon.com/sms-voice/latest/userguide/phone-numbers-sms-support-by-country.html)。

使用短信对用户进行身份验证和验证不是安全最佳做法。电话号码可能会变更所有者，而可能无法可靠地代表*您拥有的* 用户 MFA 要素。而是在应用程序中或使用第三方 IdP 实现 TOTP MFA。您还可以使用[自定义身份验证质询 Lambda 触发器](user-pool-lambda-challenge.md)创建其他自定义身份验证因素。

查看以下链接，了解有关保护短信传送架构的信息。
+ [Reduce risks of user sign-up fraud and SMS pumping with Amazon Cognito user pools](https://aws.amazon.com/blogs/security/reduce-risks-of-user-sign-up-fraud-and-sms-pumping-with-amazon-cognito-user-pools/)
+ [防范短信抽水：新 AWS 功能可帮助抵御人为膨胀的流量](https://aws.amazon.com/blogs/messaging-and-targeting/defending-against-sms-pumping-new-aws-features-to-help-combat-artificially-inflated-traffic/)

## 首次在 Amazon Cognito 用户池中设置 SMS 消息
<a name="user-pool-sms-settings-first-time"></a>

Amazon Cognito AWS End User Messaging SMS间接使用亚马逊 SNS 从您的用户池中发送短信。您还可以使用[自定义 SMS 发件人 Lambda 触发器](user-pool-lambda-custom-sms-sender.md)，通过自己的资源发送 SMS 消息。首次在特定区域设置 SMS 短信时 AWS 区域，会将您 AWS End User Messaging SMS 置 AWS 账户 于该区域的 SMS 沙箱中。 AWS End User Messaging SMS 使用沙盒来防止欺诈和滥用行为并满足合规性要求。[当你 AWS 账户 进入沙箱时，会 AWS End User Messaging SMS 施加一些限制。](https://docs.aws.amazon.com/sms-voice/latest/userguide/sandbox.html#sandbox-sms)例如，如果您有源身份，则最多可以向 10 个经过验证的目标号码发送短信，没有源身份时也可以模拟发送消息。当你 AWS 账户 仍在沙箱中时，不要在生产环境中发送 SMS 消息。当您位于沙盒中时，Amazon Cognito 无法向用户的电话号码发送消息。

**Topics**
+ [准备一个 Amazon Cognito 可以用来发送短信的 IAM 角色 AWS End User Messaging SMS](#sms-create-a-role)
+ [选择 S AWS 区域 MS 消息](#sms-choose-a-region)
+ [获取源身份以将 SMS 消息发送到美国电话号码](#user-pool-sms-settings-first-time-origination)
+ [确认您位于 SMS 沙盒中](#user-pool-sms-settings-first-time-confirm-sandbox)
+ [将您的账户移出沙盒](#user-pool-sms-settings-first-time-out-sandbox)
+ [使用模拟器号码或经过验证的电话号码 AWS End User Messaging SMS](#user-pool-sms-settings-first-time-verify-numbers)
+ [在 Amazon Cognito 中完成用户池设置](#user-pool-sms-settings-first-time-finish-user-pool)

### 准备一个 Amazon Cognito 可以用来发送短信的 IAM 角色 AWS End User Messaging SMS
<a name="sms-create-a-role"></a>

当您从用户池发送 SMS 消息时，Amazon Cognito 将代入您的账户中的 IAM 角色。Amazon Cognito 使用分配给该角色的 `sns:Publish` 权限向您的用户发送 SMS 消息。在 Amazon Cognito 控制台中，您可以从用户池**身份验证方法**菜单的 **SMS** 下设置 **IAM 角色选择**，或者在用户池创建向导过程中进行此选择。

以下示例 IAM 角色信任策略授予 Amazon Cognito 用户池有限代入角色的能力。只有在满足以下条件时 Amazon Cognito 才可以代入该角色：
+ 代入角色操作是代表 `aws:SourceArn` 条件下的用户池来执行。
+ 代入角色操作是代表通过 `aws:SourceAccount` 条件设置的 AWS 账户 中的用户池来执行。
+ 代入角色操作在 `sts:externalId` 条件中包括外部 ID。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "cognito-idp.amazonaws.com"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "sts:ExternalId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE22222",
                    "aws:SourceAccount": "111122223333"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:cognito-idp:us-west-2:111122223333:userpool/us-west-2_EXAMPLE"
                }
            }
        }
    ]
}
```

------

您可以在 `aws:SourceArn` 条件的值中指定准确的[用户池 ARN](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoncognitouserpools.html#amazoncognitouserpools-resources-for-iam-policies) 或通配符 ARN。使用 [DescribeUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeUserPool.html)API 请求在 ARNs AWS 管理控制台 或中查找您的用户池。

要发送用于[多重身份验证](user-pool-settings-mfa-sms-email-message.md)的短信消息，您的 IAM 角色信任策略必须有一个 `sts:ExternalId` 条件。此条件的值必须与您的用户池[SmsConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-SmsConfiguration)的`ExternalId`属性相匹配。当您在 Amazon Cognito 控制台中创建用户池的过程中创建 IAM 角色时，Amazon Cognito 会在角色和用户池设置中为您配置外部 ID。使用现有的 IAM 角色时，情况并非如此。

您必须更新 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求中的用户池`ExternalId`参数，并使用相同值的`sts:externalId`条件更新 IAM 角色信任策略。要了解如何使用 API 来更新用户池，同时保持原有配置不变，请参阅 [更新用户池和应用程序客户端配置](cognito-user-pool-updating.md)。

有关 IAM 角色和信任策略的更多信息，请参阅《AWS Identity and Access Management 用户指南》**中的[角色术语和概念](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html)。

### 选择 S AWS 区域 MS 消息
<a name="sms-choose-a-region"></a>

**注意**  
现在可以在中管理中的 AWS SMS 消息[AWS End User Messaging SMS](https://console.aws.amazon.com/sms-voice/home)。

在某些情况下 AWS 区域，您可以选择包含要用于发送 Amazon Cognito SMS 消息的 Amazon SNS 资源的区域。在任何提供 Amazon Cognito AWS 区域 的地方，除了亚太地区（首尔）之外，您都可以在创建用户池的地方使用 Amazon SNS 资源。 AWS 区域 在有多个区域可供选择时，为了使您的 SMS 消息收发更快且更可靠，请使用与您的用户池位于相同区域中的 Amazon SNS 资源。

在新建用户池向导的 **Configure message delivery**（配置消息传输）步骤中，为 SMS 资源选择区域。您还可以在现有用户池的**身份验证方法**菜单中，在 **SMS** 下选择**编辑**。

对于某些人来说，在发布时 AWS 区域，Amazon Cognito使用其他地区的Amazon SNS资源发送了短信。要设置您的首选区域，请使用您的用户池[SmsConfigurationType](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SmsConfigurationType.html)对象的`SnsRegion`参数。当您通过下表以编程方式在 **Amazon Cognito 区域**中创建 Amazon Cognito 用户池资源并且您不提供 `SnsRegion` 参数时，您的用户池可以使用旧 **Amazon SNS 区域**中的 Amazon SNS 资源发送 SMS 消息。

亚太地区（首尔）的 Amazon Cognito 用户池 AWS 区域 必须使用您在亚太地区（东京）地区的 Amazon SNS 配置。

Amazon SNS（通过 AWS End User Messaging SMS）将所有新账户的支出配额设置为每月 1.00 美元（美元）。在使用 Amazon Cognito 时 AWS 区域 ，你可能已经提高了支出限额。在更改 Amazon SNS 短信的配额之前，请在 AWS 支持中心提出增加配额的案例，以提高您在新区域的限额。 AWS 区域 有关更多信息，请参阅《*AWS End User Messaging SMS 用户*指南[》中的 “从 AWS End User Messaging SMS 彩信和语音沙箱转移到生产](https://docs.aws.amazon.com/sms-voice/latest/userguide/sandbox.html#sandbox-sms-move-to-production)环境”。

您可以使用相应短信区域中的 AWS End User Messaging SMS 资源向下表中的任何 **Amazon Cognito 区域**发送**短信**。


| Amazon Cognito 区域 | 短信区域 | 
| --- | --- | 
|  美国东部（俄亥俄州）  |  美国东部（俄亥俄）、美国东部（弗吉尼亚北部）  | 
|  美国东部（弗吉尼亚州北部）  |  美国东部（弗吉尼亚北部）  | 
|  美国西部（北加利福尼亚）  |  美国西部（北加利福尼亚）  | 
|  美国西部（俄勒冈州）  |  美国西部（俄勒冈州）  | 
|  加拿大（中部）  |  加拿大（中部）、美国东部（弗吉尼亚北部）  | 
|  加拿大西部（卡尔加里）  |  加拿大西部（卡尔加里）  | 
|  墨西哥（中部）  |  墨西哥（中部）  | 
|  欧洲地区（法兰克福）  |  欧洲（法兰克福）、欧洲（爱尔兰）  | 
|  欧洲地区（伦敦）  |  欧洲（伦敦）、欧洲（爱尔兰）  | 
|  欧洲地区（爱尔兰）  |  欧洲地区（爱尔兰）  | 
|  欧洲地区（巴黎）  |  欧洲地区（巴黎）  | 
|  欧洲地区（斯德哥尔摩）  |  欧洲地区（斯德哥尔摩）  | 
|  欧洲地区（米兰）  |  欧洲地区（米兰）  | 
|  欧洲（西班牙）  |  欧洲（西班牙）  | 
|  欧洲（苏黎世）  |  欧洲（苏黎世）  | 
| 亚太地区（马来西亚） | 亚太地区（新加坡） | 
|  亚太地区（泰国）  |  亚太地区（孟买）  | 
|  亚太地区（孟买）  |  亚太地区（孟买）、亚太地区（新加坡）  | 
|  亚太地区（海得拉巴）  |  亚太地区（海得拉巴）  | 
|  亚太地区（香港）  |  亚太地区（新加坡）  | 
|  亚太地区（首尔）  |  亚太地区（东京）  | 
|  亚太地区（新加坡）  |  亚太地区（新加坡）  | 
|  亚太地区（悉尼）  |  亚太地区（悉尼）  | 
|  亚太地区（东京）  |  亚太地区（东京）  | 
|  亚太地区（雅加达）  |  亚太地区（雅加达）  | 
|  亚太地区（大阪）  |  亚太地区（大阪）  | 
|  亚太地区（墨尔本）  |  亚太地区（墨尔本）  | 
|  中东（巴林）  |  中东（巴林）  | 
|  中东（阿联酋）：  |  中东（阿联酋）：  | 
|  南美洲（圣保罗）  |  南美洲（圣保罗）  | 
|  以色列（特拉维夫）  |  以色列（特拉维夫）  | 
|  非洲（开普敦）  |  非洲（开普敦）  | 

### 获取源身份以将 SMS 消息发送到美国电话号码
<a name="user-pool-sms-settings-first-time-origination"></a>

无论您是构建 SMS 沙盒测试环境还是生产环境，如果您计划向美国电话号码发送短信，则必须获取源身份。

美国运营商要求提供源身份才能向美国电话号码发送短信。如果您没有源身份，则必须获取一个。请参阅《AWS End User Messaging SMS 用户指南》**中的[申请电话号码](https://docs.aws.amazon.com/sms-voice/latest/userguide/phone-numbers-request.html)了解如何获取源身份。

当同一身份中有多个发起身份时 AWS 区域，请按以下优先顺序 AWS End User Messaging SMS 选择发起身份类型：短码、10DLC、免费电话号码。无法更改此优先级。有关更多信息，请参阅 [AWS End User Messaging SMS FAQs](https://aws.amazon.com/end-user-messaging/faqs/)。

### 确认您位于 SMS 沙盒中
<a name="user-pool-sms-settings-first-time-confirm-sandbox"></a>

按照以下过程确认您是否在 SMS 沙盒中。对每个有正式版 Amazon Cognito 用户池 AWS 区域 的地方重复此操作。

#### 在 Amazon Cognito 控制台中查看 SMS 沙盒状态
<a name="check-that-you-are-in-the-sms-sandbox"></a>

**确认您位于 SMS 沙盒中**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入 AWS 凭证。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 选择**身份验证方法**菜单。

1. 在 **SMS configuration**（SMS 配置）部分，展开 **Move to Amazon SNS production environment**（迁移到 Amazon SNS 生产环境）。如果您的账户位于 SMS 沙盒中，您将看到以下消息：

   **配置 AWS 服务 依赖关系以完成 SMS 消息设置**

   如果您没有看到此消息，则表明有人已经在您的账户中设置了 SMS 消息。跳至[在 Amazon Cognito 中完成用户池设置](#user-pool-sms-settings-first-time-finish-user-pool)。

1. 选择**迁移到 Amazon SNS 生产环境**下的 [Amazon SNS](https://console.aws.amazon.com/sns/home) 链接。这将在新选项卡中打开 Amazon SNS 控制台。

1. 验证您是否位于沙盒环境中。控制台消息会显示您的沙箱状态 AWS 区域，如下所示：

   `This account is in the SMS sandbox in US East (N. Virginia).`

### 将您的账户移出沙盒
<a name="user-pool-sms-settings-first-time-out-sandbox"></a>

要在生产环境中使用您的应用程序，请将账户移出 SMS 沙盒并放入生产环境。在中配置了包含您希望 Amazon Cognito 使用的 AWS End User Messaging SMS 资源的原始身份后，您可以在留在 SMS 沙箱中时 AWS 账户 验证美国电话号码。 AWS 区域 当您的环境投入生产时，您无需验证用户电话号码即可向它们发送短信。

您可以创建从 AWS End User Messaging SMS 控制台或 Amazon SNS 控制台退出沙箱的请求。有关详细说明，请参阅《AWS End User Messaging SMS 用户指南》**中的[移出短信沙盒](https://docs.aws.amazon.com/sms-voice/latest/userguide/sandbox.html#sandbox-sms-move-to-production)。

### 使用模拟器号码或经过验证的电话号码 AWS End User Messaging SMS
<a name="user-pool-sms-settings-first-time-verify-numbers"></a>

如果您已将账户移出 SMS 沙盒，则跳过此步骤。

如果您在沙盒中但已经设置了源号码，则可以向经过验证的目的地号码发送消息。要设置经过验证的目的地，请参阅《AWS End User Messaging SMS 用户指南》**中的[添加经过验证的目的地电话号码](https://docs.aws.amazon.com/sms-voice/latest/userguide/verify-destination-phone-number.html)。

您还可以使用模拟的发件人和目的地发送消息。模拟器消息会生成日志，但不会通过运营商网络发送。从[快捷方式](https://console.aws.amazon.com/sms-voice/home?#/shortcuts)菜单中，选择**使用短信模拟器测试短信发送**。有关更多信息，请参阅《AWS End User Messaging SMS 用户指南》中的**[模拟器电话号码](https://docs.aws.amazon.com/sms-voice/latest/userguide/test-phone-numbers.html)。

### 在 Amazon Cognito 中完成用户池设置
<a name="user-pool-sms-settings-first-time-finish-user-pool"></a>

返回您在其中创建或者[编辑](signing-up-users-in-your-app.md#verification-configure)用户池的浏览器选项卡。完成过程。当您成功将 SMS 配置添加到用户池后，Amazon Cognito 会向内部电话号码发送测试消息，以验证您的配置有效。Amazon SNS 会对每条测试 SMS 消息收费。

# 使用 Amazon Cognito 用户池安全功能
<a name="managing-security"></a>

您可能想要保护应用程序，防止受到网络入侵、密码猜测、用户模拟以及恶意注册和登录的侵害。Amazon Cognito 用户池安全特征的配置是安全架构中的一个关键组件。您的应用程序的安全性是*客户责任 “云端安全”*，如[责任 AWS 共担模型](https://aws.amazon.com/compliance/shared-responsibility-model/)中所述。本章中的工具有助于使您的应用程序安全设计符合这些目标。

在配置用户池时，必须作出的一项重要决定是，是否允许公开注册和登录。某些用户池选项（例如机密客户端、以管理员身份创建用户和确认，以及没有域的用户池）受到互联网攻击影响的程度较小。而一个常见的使用场景是公共客户端，它们接受互联网上任何人的注册并将所有操作直接发送到您的用户池。在任何配置中（尤其是在这些公共配置中），我们建议在规划和部署用户池时要考虑安全特征。当不受欢迎的来源创建新的活跃用户或试图利用现有用户时，安全性不足也会影响您的 AWS 账单。

MFA 和威胁防护适用于[本地用户](cognito-terms.md#terms-localuser)。第三方 IdPs 应对[联合用户](cognito-terms.md#terms-federateduser)的安全状况负责。用户池安全特征

**多重身份验证 (MFA)**  
请求一个由用户池通过电子邮件（使用基础版或增值版功能计划）或短信或身份验证器应用程序发送的验证码，用以确认用户池登录。

**威胁防护**  
监控登录以了解风险指标，并应用 MFA 或阻止登录。向访问令牌添加自定义声明和范围。通过电子邮件发送 MFA 代码。

**AWS WAF 网页 ACLs**  
检查[用户池端点和身份验证 API](authentication-flows-public-server-side.md#user-pools-API-operations) 的传入流量，以了解网络层和应用程序层是否存在不想要的活动。

**区分大小写**  
防止创建除了字符大小写有所不同之外，其电子邮件地址或首选用户名与另一个用户完全相同的用户。

**删除保护**  
防止自动化系统意外删除您的用户池。需要在 AWS 管理控制台中进一步确认删除用户池。

**用户存在错误**  
防止披露用户池中现有的用户名和别名。无论用户名是否有效，在身份验证失败时都返回一个通用错误。

**Topics**
+ [向用户池添加 MFA](user-pool-settings-mfa.md)
+ [具备威胁防护的高级安全功能](cognito-user-pool-settings-threat-protection.md)
+ [将 AWS WAF Web ACL 与用户池关联](user-pool-waf.md)
+ [用户池区分大小写](user-pool-case-sensitivity.md)
+ [用户池删除保护](user-pool-settings-deletion-protection.md)
+ [管理用户存在错误响应](cognito-user-pool-managing-errors.md)

# 向用户池添加 MFA
<a name="user-pool-settings-mfa"></a>

MFA 将*您具有的某种* 身份验证因素添加到*您已知的* 初始因素（通常是用户名和密码）中。对于使用密码作为主要身份验证因素的用户，您可以选择将短信文本消息、电子邮件消息或基于时间的一次性密码（TOTP）作为他们登录的额外安全因素。

多重身份验证（MFA）可提高应用程序中[本地用户](cognito-terms.md#terms-localuser)的安全性。对于[联合用户](cognito-terms.md#terms-federateduser)，Amazon Cognito 会将所有身份验证过程委托给 IdP，并且不会为他们提供额外的身份验证因素。

**注意**  
即使您的用户池需要 MFA，新用户首次登录您的应用程序时，Amazon Cognito 也会发放 OAuth 2.0 令牌。您的用户首次登录时的第二个身份验证因素是他们对 Amazon Cognito 发送给他们的验证消息的确认。如果您的用户池要求使用 MFA，Amazon Cognito 会提示您的用户注册一个额外的登录因素，以便在第一次之后的每次登录尝试期间使用。

借助自适应身份验证，可以将用户池配置为响应增加的风险级别需要额外的身份验证因素。要向用户池添加自适应身份验证，请参阅 [具备威胁防护的高级安全功能](cognito-user-pool-settings-threat-protection.md)。

将用户池的 MFA 设置为 `required` 时，所有用户都必须完成 MFA 才能登录。要登录，每个用户至少设置一个 MFA 安全因素。当需要进行 MFA 时，您必须在用户引导中包含 MFA 设置，以便您的用户池允许他们登录。

当您将 MFA 设置为必需时，托管登录会提示用户设置 MFA。当您在用户池中将 MFA 设置为可选时，托管登录不会提示用户。要使用可选的 MFA，您必须在应用程序中构建一个界面，以提示用户选择他们需要设置 MFA，然后引导他们完成 API 输入以验证他们的额外登录因素。

**Topics**
+ [有关用户池 MFA 的需知信息](#user-pool-settings-mfa-prerequisites)
+ [用户 MFA 首选项](#user-pool-settings-mfa-preferences)
+ [用户运行时的 MFA 逻辑详情](#user-pool-settings-mfa-user-outcomes)
+ [为用户池配置多重身份验证](#user-pool-configuring-mfa)
+ [短信和电子邮件消息 MFA](user-pool-settings-mfa-sms-email-message.md)
+ [TOTP 软件令牌 MFA](user-pool-settings-mfa-totp.md)

## 有关用户池 MFA 的需知信息
<a name="user-pool-settings-mfa-prerequisites"></a>

在设置 MFA 之前，请考虑以下情况：
+ *用户可以拥有 MFA，也可以使用无密码因素登录，但有一个例外：当您在用户池中设置为时，带有用户验证功能的密钥可以满足 MFA 要求。* `FactorConfiguration` `MULTI_FACTOR_WITH_USER_VERIFICATION` `WebAuthnConfiguration`
  + 在支持[一次性](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)密码的用户池中，您不能将 MFA 设置为必填项。
  + 当您的用户池中需要 MFA `AllowedFirstAuthFactors` 时，您无法添加`EMAIL_OTP`或`SMS_OTP`。您可以添加`WEB_AUTHN`何时设置`FactorConfiguration`为`MULTI_FACTOR_WITH_USER_VERIFICATION`。
  + 当用户池要求启用 MFA 时，所有应用程序客户端中[基于选择的登录](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)仅提供 `PASSWORD` 和 `PASSWORD_SRP` 两种因素。有关用户名密码流程的更多信息，请参阅本指南**身份验证**一章中的[使用永久密码登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-password)和[使用永久密码和安全有效载荷登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-srp)。
  + 在 MFA 为可选的用户池中，已配置 MFA 因素的用户在使用基于选择的登录时，只能通过用户名密码的身份验证流程进行登录。这些用户有资格使用所有[基于客户端的登录](authentication-flows-selection-sdk.md#authentication-flows-selection-client)流程。

  下表描述了用户池的 MFA 设置及用户对 MFA 因素的配置对用户使用无密码因素登录的能力的影响。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/user-pool-settings-mfa.html)
+ 用户首选 MFA 方法会影响他们可用于恢复密码的方法。首选 MFA 方式为电子邮件的用户无法通过电子邮件接收密码重置代码。首选 MFA 方式为短信的用户无法通过短信接收密码重置代码。

  当用户不符合条件，无法使用首选密码重置方法时，您的[密码恢复](managing-users-passwords.md#user-pool-password-reset-and-recovery)设置必须提供替代选项。例如，您的恢复机制可能将电子邮件列为第一优先选项，而电子邮件 MFA 可能是您的用户池中的一个选项。在这种情况下，添加短信消息账户恢复作为第二个选项，或者使用管理 API 操作为这些用户重置密码。

  对于没有有效恢复方式的用户发起的密码重置请求，Amazon Cognito 会返回 `InvalidParameterException` 错误响应。

  的示例请求正文[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#API_UpdateUserPool_Examples)说明了当电子邮件密码重置不可用时，用户可以通过短信回退到恢复状态。`AccountRecoverySetting`
+ 用户无法在同一电子邮件地址或电话号码上接收 MFA 验证码和密码重置验证码。如果他们使用电子邮件中的一次性密码 (OTPs) 进行 MFA，则必须使用 SMS 消息进行账户恢复。如果他们使用来 OTPs 自 SMS 消息的 MFA，则必须使用电子邮件进行账户恢复。在具有 MFA 的用户池中，如果用户有电子邮件地址的属性但没有电话号码，或者有电话号码但没有电子邮件地址，则他们可能无法完成自助密码恢复。

  要防止用户无法在使用此配置的用户池中重置密码的情况，请设置 `email` 和 `phone_number` [属性（按需设置）](user-pool-settings-attributes.md)。或者，您可以设置相关流程，在用户注册时或管理员创建用户配置文件时，始终收集并设置这些属性。当用户同时具备这两个属性时，Amazon Cognito 会自动将密码重置验证码发送到*不是*用户 MFA 因素的目的地。
+ 当您在用户池中激活 MFA 并选择**短信**或**电子邮件消息**作为第二安全因素时，可以向尚未在 Amazon Cognito 中验证的电话号码或电子邮件属性发送消息。用户完成 MFA 后，Amazon Cognito 会将其 `phone_number_verified` 或 `email_verified` 属性设置为 `true`。
+ 在五次尝试提交 MFA 代码均未成功后，Amazon Cognito 会开始如[失败登录尝试的锁定行为](authentication.md#authentication-flow-lockout-behavior)中所描述的指数超时锁定过程。
+ 如果您的账户位于包含您的用户池的亚马逊简单通知服务 (Amazon SNS) Simple Notification Service 资源的短信沙箱中，则必须先验证亚马逊 SNS 中的电话号码，然后才能发送短信。 AWS 区域 有关更多信息，请参阅 [Amazon Cognito 用户池的短信设置](user-pool-sms-settings.md)。
+ 为了更改用户的 MFA 状态以响应威胁防护功能检测到的事件，请激活 MFA 并在 Amazon Cognito 用户池控制台中将其设置为可选。有关更多信息，请参阅 [具备威胁防护的高级安全功能](cognito-user-pool-settings-threat-protection.md)。
+ 电子邮件和短信消息要求您的用户分别具有电子邮件地址和电话号码属性。您可以在用户池中将 `email` 或 `phone_number` 设置为必需的属性。在这种情况下，除非用户提供电话号码，否则他们无法完成注册。如果您未将这些属性设置为必需，但想要进行电子邮件或短信消息 MFA，则可以在用户注册时提示他们输入电子邮件地址或电话号码。妥善的做法是将用户池配置为自动向用户发送消息来[验证这些属性](signing-up-users-in-your-app.md)。

  如果用户通过短信或电子邮件成功接收了临时验证码，并在 [VerifyUserAttribute](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifyUserAttribute.html)API 请求中返回了该验证码，则 Amazon Cognito 会将电话号码或电子邮件地址视为已验证。或者，您的团队可以设置电话号码，并使用执行 [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)API 请求的管理应用程序将其标记为已验证。
+ 如果您已将 MFA 设置为必需且激活了多个身份验证因素，则 Amazon Cognito 会提示新用户选择他们想要使用的 MFA 因素。用户必须有电话号码才能设置短信消息 MFA，必须有电子邮件地址才能设置电子邮件消息 MFA。如果用户没有为任何基于消息的可用 MFA 定义属性，则 Amazon Cognito 会提示他们设置 TOTP MFA。选择 MFA 因子 (`SELECT_MFA_TYPE`) 和设置所选因子 (`MFA_SETUP`) 的提示是对[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)和 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)API 操作的质询响应。

## 用户 MFA 首选项
<a name="user-pool-settings-mfa-preferences"></a>

用户可以设置多个 MFA 因素。只能激活一个因素。您可以在用户池设置中或从用户提示为用户选择有效的 MFA 首选项。当用户池设置和他们自己的用户级设置满足以下条件时，用户池会提示用户输入 MFA 验证码：

1. 您可以在用户池中将 MFA 设置为可选或必需。

1. 用户具有有效的 `email` 或 `phone_number` 属性，或者已为 TOTP 设置身份验证器应用程序。

1. 至少有一个 MFA 因素处于活动状态。

1. 一个 MFA 因素设置为首选。

### 禁止在登录和 MFA 中使用相同的系数
<a name="user-pool-settings-mfa-preferences-same-factor"></a>

可以配置您的用户池，使一个登录因子成为部分或所有用户唯一可用的登录和 MFA 选项。当您的主要登录用例是电子邮件或短信一次性密码 () 时，可能会出现此结果。OTPs在以下条件下，用户的首选 MFA 可能与其登录的因素类型相同：
+ 用户池中需要 MFA。
+ 用户池中提供电子邮件和短信 OTP 登录和 *MF* A 选项。
+ 用户使用电子邮件或短信 OTP 登录。
+ 它们有电子邮件地址属性但没有电话号码属性，或者有电话号码属性但没有电子邮件地址属性。

在这种情况下，用户可以使用电子邮件 OTP 登录，并使用电子邮件 OTP 完成 MFA。此选项取消了 MFA 的基本功能。使用一次性密码登录的用户必须能够使用与 MFA 不同的交付方式进行登录。当用户同时使用短信和电子邮件选项时，Amazon Cognito 会自动分配不同的因子。例如，当用户使用电子邮件 OTP 登录时，他们的首选 MFA 是短信 OTP。

当您的用户池支持登录和 MFA 的 OTP 身份验证时，请执行以下步骤来解决同因子身份验证问题。

1. 启用电子邮件和短信 OTP 作为登录因子。

1. 启用电子邮件和短信 OTP 作为 MFA 因子。

1. 收集

### 用户池设置及其对 MFA 选项的影响
<a name="user-pool-settings-mfa-preferences-things-to-know"></a>

用户池的配置会影响用户可以选择的 MFA 方法。以下是一些会影响用户设置 MFA 能力的用户池设置。
+ 在 Amazon Cognito 控制台**登录**菜单中的**多重身份验证**配置中，您可以将 MFA 设置为可选或必需，也可以将其关闭。与此设置的 API 等效项是`CreateUserPool``UpdateUserPool`、和的[MfaConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-MfaConfiguration)参数`SetUserPoolMfaConfig`。

  此外，在**多重身份验证**配置中，**MFA 方法**设置决定了用户可以设置的 MFA 因素。与该设置相当的 API 就是[SetUserPoolMfaConfig](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserPoolMfaConfig.html)操作。
+ 在**用户账户恢复**下的**登录**菜单中，您可以配置用户池向忘记密码的用户发送消息的方式。用户的 MFA 方法不能与用户池用于发送“忘记密码”验证码的 MFA 传送方式相同。忘记密码传送方法的 API 参数是和的[AccountRecoverySetting](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-AccountRecoverySetting)参数。`CreateUserPool` `UpdateUserPool`

  例如，当恢复选项为**仅使用电子邮件**时，用户无法设置电子邮件 MFA。这是因为在同一个用户池中，您无法既启用电子邮件 MFA 又将恢复选项设置为**仅使用电子邮件**。当您将此选项设置为**如果电子邮件可用，则使用电子邮件发送，否则使用短信**时，电子邮件是优先恢复选项，但是当用户不符合通过电子邮件进行恢复的条件时，您的用户池可以回退到短信形式。在这种情况下，用户可以将电子邮件 MFA 设置为首选，并且只在尝试重置密码时才接收短信。
+ 如果您只将一种 MFA 方法设置为可用，则无需管理用户 MFA 首选项。
+ 激活的短信配置会自动使短信成为用户池中的可用 MFA 方法。

  用户池中包含您自己的 Amazon SES 资源的有效[电子邮件配置](user-pool-email.md)以及基础版或增值版功能计划，可自动使电子邮件消息成为用户池中的可用 MFA 方法。
+ 在用户池中将 MFA 设置为必需时，用户无法启用或禁用任何 MFA 方法。您只能设置首选方法。
+ 当您在用户池中将 MFA 设置为可选时，托管登录不会提示用户设置 MFA，而是在用户拥有首选 MFA 方法时，提示用户输入 MFA 验证码。
+ 当您激活[威胁防护](cognito-user-pool-settings-threat-protection.md)并在全功能模式下配置自适应身份验证响应时，在您的用户池中 MFA 必须是可选的。自适应身份验证的其中一个响应选项是要求其登录尝试被评估为包含一定风险级别的用户进行 MFA。

  控制台的**注册**菜单中的**必填属性**设置决定了用户是否必须提供电子邮件地址或电话号码才能注册您的应用程序。当用户具有相应属性时，电子邮件和短信将成为符合条件的 MFA 因素。`CreateUserPool` 的 [Schema](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#CognitoUserPools-CreateUserPool-request-Schema) 参数根据需要设置属性。
+ 当您在用户池中将 MFA 设置为必需且用户使用托管登录进行登录时，Amazon Cognito 会提示他们从用户池的可用方法中选择 MFA 方法。托管登录负责收集电子邮件地址或电话号码并设置 TOTP。下图展示了 Amazon Cognito 向用户提供的选项背后的逻辑。

### 为用户配置 MFA 首选项
<a name="user-pool-settings-mfa-preferences-configure"></a>

您可以在具有访问令牌授权的自助服务模式中为用户配置 MFA 首选项，或者在具有管理 API 操作的管理员管理模式中为用户配置 MFA 首选项。这些操作启用或禁用 MFA 方法，并将多种方法之一设置为首选选项。在用户设置 MFA 首选项后，Amazon Cognito 会在登录时提示他们提供来自他们首选 MFA 方法的验证码。未设置首选项的用户会收到在 `SELECT_MFA_TYPE` 质询中选择首选方法的提示。
+ 在用户自助服务模式或公共应用程序中 [SetUserMfaPreference](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserMFAPreference.html)，使用登录用户的访问令牌进行授权，设置 MFA 配置。
+ 在管理员管理的应用程序或机密应用程序中，使用管理 AWS 凭证进行授权 [AdminSetUserPreference](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserMFAPreference.html)，设置 MFA 配置。

您也可以从 Amazon Cognito 控制台的**用户**菜单中设置用户 MFA 首选项。有关 Amazon Cognito 用户池 API 中的公共和机密身份验证模式的更多信息，请参阅[了解 API、OIDC 和托管登录页面身份验证](authentication-flows-public-server-side.md#user-pools-API-operations)。

## 用户运行时的 MFA 逻辑详情
<a name="user-pool-settings-mfa-user-outcomes"></a>

为确定用户登录时要采取的步骤，您的用户池会评估用户 MFA 首选项、[用户属性](user-pool-settings-attributes.md)、[用户池 MFA 设置](#user-pool-configuring-mfa)、[威胁防护](cognito-user-pool-settings-adaptive-authentication.md)操作和[自助账户恢复](managing-users-passwords.md#user-pool-password-reset-and-recovery)设置。然后，它会让用户登录，提示他们选择 MFA 方法、设置 MFA 方法或进行 MFA 验证。要设置 MFA 方法，用户必须提供[电子邮件地址或电话号码](user-pool-settings-mfa-sms-email-message.md)或[注册 TOTP 身份验证器](user-pool-settings-mfa-totp.md#totp-mfa-set-up-api)。他们还可以设置 MFA 选项并提前[注册首选项](#user-pool-settings-mfa-preferences-configure)。下图列出了用户池配置对初始注册后立即登录尝试的详细影响。

此图所示的逻辑适用于基于 SDK 的应用程序和[托管登录](cognito-user-pools-managed-login.md)登录流程，但在托管登录中较不明显。当您排查 MFA 的问题时，应从用户遇到的结果出发，反向追溯到用户配置文件以及影响该结果的用户池配置。

![\[便于最终用户选择 MFA 方法的 Amazon Cognito 用户池决策过程示意图。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/cup-mfa-decision-tree.png)


以下清单对应于决策逻辑图中的编号，并详细描述了每个步骤。![\[checkmark\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png) 表示身份验证成功且流程已结束。![\[error\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/error.png) 表示身份验证失败。

1. 用户在登录界面输入其用户名，或用户名和密码。如果提供的凭证无效，其登录请求将被拒绝。

1. 如果用户成功通过用户名密码身份验证，则需判断 MFA 是必需、可选还是关闭。如果关闭，则使用正确的用户名和密码即可成功进行身份验证。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

   1. 如果 MFA 为可选，需判断用户之前是否已设置 TOTP 身份验证器。如果已设置 TOTP，则提示用户进行 TOTP MFA。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

   1. 判断威胁防护的自适应身份验证功能是否已要求该用户设置 MFA。如果未分配 MFA，则用户可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

1. 如果 MFA 为必需，或自适应身份验证已为用户分配 MFA，则需判断该用户是否已启用并设定首选的 MFA 因素。如果有，则使用该因素提示用户进行 MFA 验证。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

1. 如果用户尚未设置 MFA 首选项，则需判断该用户是否已注册 TOTP 身份验证器。

   1. 如果用户已注册 TOTP 身份验证器，则需判断该用户池中是否启用了 TOTP MFA（即使用户之前已设置身份验证器，此后 TOTP MFA 仍可能被禁用）。

   1. 判断用户池中电子邮件消息或短信形式的 MFA 是否也可用。

   1.  如果电子邮件和短信 MFA 均不可用，则提示用户进行 TOTP MFA 验证。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

   1. 如果电子邮件或短信 MFA 可用，则需判断用户是否具有相应的 `email` 或 `phone_number` 属性。如果已设置，则任何未被用作自助账户恢复的主要方式且已启用用于 MFA 的属性，均可供用户使用。

   1. 向用户发起一个 `SELECT_MFA_TYPE` 质询，其中 `MFAS_CAN_SELECT` 选项包含 TOTP 以及可用的短信或电子邮件 MFA 因素。

   1.  根据用户在 `SELECT_MFA_TYPE` 质询中选择的因素，提示用户完成该因素的验证。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

1. 如果用户尚未注册 TOTP 身份验证器，或者已注册但 TOTP MFA 当前已禁用，则需判断该用户是否设置了 `email` 或 `phone_number` 属性。

1.  如果用户仅有一个电子邮件地址或仅有一个电话号码，则需判断该属性是否同时也是用户池用于发送密码重置账户恢复消息的方式。如果是，则在 MFA 为必需的情况下，用户无法完成登录，Amazon Cognito 将返回错误。要使该用户成功登录，必须为其添加一个非恢复用途的属性，或为其注册一个 TOTP 身份验证器。![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/error.png)

   1. 如果用户拥有可用的、非恢复用途的电子邮件地址或电话号码，则需判断对应的电子邮件或短信 MFA 因素是否已启用。

   1. 如果用户拥有非恢复用途的电子邮件地址属性，且电子邮件 MFA 已启用，则可向其发起 `EMAIL_OTP` 质询。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

   1. 如果用户拥有非恢复用途的电话号码属性，且短信 MFA 已启用，则可向其发起 `SMS_MFA` 质询。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

   1. 如果用户没有可用于已启用电子邮件或短信 MFA 因素的属性，则需判断 TOTP MFA 是否已启用。如果 TOTP MFA 已禁用，则在 MFA 为必需的情况下，用户无法完成登录，Amazon Cognito 将返回错误。要使该用户成功登录，必须为其添加一个非恢复用途的属性，或为其注册一个 TOTP 身份验证器。![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/error.png)
**注意**  
如果用户已注册 TOTP 身份验证器但 TOTP MFA 已禁用，则此步骤此前已被判定为**否**。

   1. 如果 TOTP MFA 已启用，则向用户发起一个 `MFA_SETUP` 质询，并在 `MFAS_CAN_SETUP` 选项中包含 `SOFTWARE_TOKEN_MFA`。要完成此质询，您必须单独为用户注册一个 TOTP 身份验证器，然后使用 `"ChallengeName": "MFA_SETUP", "ChallengeResponses": {"USERNAME": "[username]", "SESSION": "[Session ID from VerifySoftwareToken]}"` 进行回应。

   1. 用户使用[VerifySoftwareToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifySoftwareToken.html)请求中的会话令牌回应`MFA_SETUP`质询后，提示他们提出`SOFTWARE_TOKEN_MFA`质疑。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

1. 如果用户同时拥有电子邮件地址和电话号码，则需判断其中哪一个属性（如果有的话）是密码重置账户恢复消息的主要发送方式。

   1. 如果自助账户恢复功能已禁用，则这两个属性均可用于 MFA。需判断电子邮件 MFA、短信 MFA 或两者是否已启用。

   1. 如果这两个属性均已启用为 MFA 因素，则向用户发起一个 `SELECT_MFA_TYPE` 质询，其中 `MFAS_CAN_SELECT` 选项为 `SMS_MFA` 和 `EMAIL_OTP`。

   1. 根据用户在 `SELECT_MFA_TYPE` 质询中选择的因素，提示他们完成该因素的验证。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

   1. 如果仅有一个属性符合 MFA 因素的条件，则向用户发起对应另一个因素的质询。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

      如果存在以下情形，可能会发生这种结果。

      1. 当用户同时拥有 `email` 和 `phone_number` 属性，短信和电子邮件 MFA 均已启用，且账户恢复的主要方式已设定为通过电子邮件或短信时。

      1. 当用户同时拥有 `email` 和 `phone_number` 属性，仅短信 MFA 或电子邮件 MFA 之一已启用，且自助账户恢复已禁用时。

1. 如果用户尚未注册 TOTP 身份验证器，且既无 `email` 也无 `phone_number` 属性，则向其发起一个 `MFA_SETUP` 质询。`MFAS_CAN_SETUP` 列表中包含用户池中所有已启用且不是账户恢复主要选项的 MFA 因素。用户可通过 `ChallengeResponses` 响应此质询，以设置电子邮件或 TOTP MFA。要设置短信 MFA，必须先单独为用户添加电话号码属性，然后重新开始身份验证流程。

   对于 TOTP MFA，使用 `"ChallengeName": "MFA_SETUP", "ChallengeResponses": {"USERNAME": "[username]", "SESSION": "[Session ID from VerifySoftwareToken]"}` 进行响应。

   对于电子邮件 MFA，使用 `"ChallengeName": "MFA_SETUP", "ChallengeResponses": {"USERNAME": "[username]", "email": "[user's email address]"}` 进行响应。

   1. 根据用户在 `SELECT_MFA_TYPE` 质询中选择的因素，提示他们完成该因素的验证。如果用户成功响应该 MFA 质询，即可成功登录。![\[Green circular icon with a checkmark symbol inside.\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/checkmark.png)

## 为用户池配置多重身份验证
<a name="user-pool-configuring-mfa"></a>

您可以在 Amazon Cognito 控制台中配置 MFA，也可以使用 API 操作和 SD [SetUserPoolMfaConfig](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserPoolMfaConfig.html)K 方法进行配置。

**在 Amazon Cognito 控制台中配置 MFA**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**登录**菜单。找到**多重身份验证**，然后选择**编辑**。

1. 选择您希望用于用户池的**MFA 强制执行**方法。  
![\[一张来自 Amazon Cognito 控制台的屏幕截图，显示了 MFA 选项。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/cup-mfa.png)

   1. **需要 MFA**。用户池中的所有用户必须使用额外的短信验证码、电子邮件验证码或基于时间的一次性密码（TOTP）验证码作为额外的身份验证因素进行登录。

   1. **可选 MFA**。您可以为用户提供选项来注册额外的登录安全因素，但仍允许未配置 MFA 的用户登录。如果您使用自适应身份验证，请选择此选项。有关自适应身份验证的更多信息，请参阅[具备威胁防护的高级安全功能](cognito-user-pool-settings-threat-protection.md)。

   1. **无 MFA**。您的用户无法注册其他登录安全要素。

1. 选择您在应用程序中支持的 **MFA 方法**。您可以将**电子邮件消息**、**短信**或 TOTP 生成的**身份验证器应用程序**设置为第二个因素。

1. 如果使用 SMS 文本消息作为第二安全要素，并且没有配置 IAM 角色与 Amazon Simple Notification Service（Amazon SNS）一起使用 SMS 消息，您可以在控制台中创建一个角色。在用户池的**身份验证方法**菜单中，找到**短信**，然后选择**编辑**。您还可以使用允许 Amazon Cognito 代表您向用户发送短信的现有角色。有关更多信息，请参阅 [IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)。

   如果使用电子邮件消息作为第二安全因素，但尚未为 Amazon Simple Email Service (Amazon SES) 配置源身份以发送电子邮件消息，则可以在控制台中创建一个。必须选择**使用 SES 发送电子邮件**选项。在用户池的**身份验证方法**菜单中，找到**电子邮件**，然后选择**编辑**。从列表中可用的已验证身份中，选择一个**发件人电子邮件地址**。如果您选择了一个已验证的域（例如 `example.com`），则还必须在该已验证域下配置一个**发件人姓名**，例如 `admin-noreply@example.com`。

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

# 短信和电子邮件消息 MFA
<a name="user-pool-settings-mfa-sms-email-message"></a>

短信和电子邮件 MFA 消息确认用户在登录之前对消息目的地具有访问权限。用户确认他们不仅可以访问密码，还可以访问原始用户的短信或电子邮件收件箱。Amazon Cognito 要求用户提供用户池在成功提供用户名和密码后发送的短代码。

用户向其配置文件添加电子邮件地址或电话号码后，短信和电子邮件 MFA 无需额外配置。Amazon Cognito 可以向未经验证的电子邮件地址和电话号码发送消息。当用户完成第一个 MFA 时，Amazon Cognito 会将其电子邮件地址或电话号码标记为已验证。

当拥有 MFA 的用户在您的应用程序中输入他们的用户名和密码时，MFA 身份验证开始。您的应用程序使用调用[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)或 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)API 请求的 SDK 方法提交这些初始参数。API 响应中的 `ChallengeParameters` 包括一个 `CODE_DELIVERY_DESTINATION` 值，指明发送授权码的位置。在您的应用程序中，显示一个表单，提示用户查看他们的手机，并包括一个输入框用于输入验证码。在他们输入验证码时，请在质询响应 API 请求中提交验证码以完成登录过程。

拥有 MFA 的用户在[托管登录](cognito-user-pools-managed-login.md)页面中使用用户名和密码登录后，系统会自动提示他们输入 MFA 验证码。

用户池使用您的 AWS 账户中的 Amazon Simple Notification Service（Amazon SNS）资源发送 MFA 和其他 Amazon Cognito 通知的短信。同样，用户池使用您账户中的 Amazon Simple Email Service（Amazon SES）发送电子邮件消息。这些关联服务在您的邮件传送 AWS 账单上自行产生费用。在以生产级别的规模发送消息时，还需要满足额外的要求。有关更多信息，请参阅以下链接：
+ [Amazon Cognito 用户池的短信设置](user-pool-sms-settings.md)
+ [全球短信定价](https://aws.amazon.com/sns/sms-pricing/)
+ [Amazon Cognito 用户池的电子邮件设置](user-pool-email.md)
+ [Amazon SES 定价](https://aws.amazon.com/ses/pricing)

## 短信和电子邮件消息 MFA 的注意事项
<a name="user-pool-settings-mfa-sms-email-message-considerations"></a>
+ 要允许用户使用电子邮件 MFA 登录，您的用户池必须具有以下配置选项：

  1. 您的用户池拥有增值版或基础版功能计划。有关更多信息，请参阅 [用户池功能计划](cognito-sign-in-feature-plans.md)。

  1. 您的用户池使用您自己的 Amazon SES 资源发送电子邮件消息。有关更多信息，请参阅 [Amazon SES 电子邮件配置](user-pool-email.md#user-pool-email-developer)。
+ MFA 验证码在您为应用程序客户端设置的**身份验证流程会话持续时间**内有效。

  当您**编辑**应用程序客户端时，需在 Amazon Cognito 控制台的**应用程序客户端**菜单中设置身份验证流程会话的持续时间。您还可以在 `CreateUserPoolClient` 或 `UpdateUserPoolClient` API 请求中设置身份验证流程会话持续时间。有关更多信息，请参阅 [身份验证会话示例](authentication.md#amazon-cognito-user-pools-authentication-flow)。
+ 当用户成功提供 Amazon Cognito 发送到未经验证的电话号码或电子邮件地址的短信或电子邮件中的验证码时，Amazon Cognito 会将相应的属性标记为已验证。
+ 要让用户自助更改与 MFA 关联的电话号码或电子邮件地址的值，他们必须使用访问令牌登录并授权请求。如果他们无法访问他们当前的电话号码或电子邮件地址，则无法登录。您的团队必须在 [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)API 请求中使用管理员 AWS 凭据更改这些值。
+ 在用户池中[配置短信](user-pool-sms-settings.md)后，即无法禁用将短信作为可用的 MFA 因素。

# TOTP 软件令牌 MFA
<a name="user-pool-settings-mfa-totp"></a>

当您在用户池中设置了 TOTP 软件令牌 MFA 时，您的用户通过用户名和密码登录，然后使用 TOTP 完成身份验证。用户设置并验证用户名和密码后，就可以为 MFA 激活 TOTP 软件令牌。如果应用程序使用 Amazon Cognito 托管登录来登录用户，则用户提交用户名和密码，然后在额外的登录页面上提交 TOTP 密码。

您可以在 Amazon Cognito 控制台中为用户池激活 TOTP MFA，也可以使用 Amazon Cognito API 操作来激活。在用户池级别，您可以调用[SetUserPoolMfaConfig](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserPoolMfaConfig.html)配置 MFA 并启用 TOTP MFA。

**注意**  
如果您没有为用户池激活 TOTP 软件令牌 MFA，则 Amazon Cognito 无法使用此令牌进行关联或验证用户。在这种情况下，用户会收到 `SoftwareTokenMFANotFoundException` 异常，并带有说明 `Software Token MFA has not been enabled by the userPool`。如果您稍后为用户池停用了软件令牌 MFA，则以前已关联并验证 TOTP 令牌的用户可以继续将其用于 MFA。

为用户配置 TOTP 是一个多步骤过程，在此过程中，用户将收到一个秘密代码，它们通过输入一次性密码来验证该代码。接下来，您可以为用户启用 TOTP MFA，或将 TOTP 设置为用户的首选 MFA 方法。

当您将用户池配置为需要 TOTP MFA 并且用户在托管登录中注册应用程序时，Amazon Cognito 会自动执行用户流程。Amazon Cognito 提示您的用户选择 MFA 方法，显示 QR 代码来设置身份验证器应用程序，并验证他们的 MFA 注册。在您允许用户在 SMS 和 TOTP MFA 之间进行选择的用户池中，Amazon Cognito 还为您的用户提供了方法选择。

**重要**  
当您的 AWS WAF Web ACL 与用户池相关联，并且您的 Web ACL 中的规则显示了验证码时，这可能会导致托管登录 TOTP 注册中出现不可恢复的错误。要创建具有 CAPTCHA 操作且不影响托管登录 TOTP 的规则，请参阅[为托管登录 TOTP MFA 配置您的 AWS WAF 网页 ACL](#totp-waf)。有关 AWS WAF 网络 ACLs 和 Amazon Cognito 的更多信息，请参阅。[将 AWS WAF Web ACL 与用户池关联](user-pool-waf.md)

要使用软件开发工具包和 Amazon Co [gnito 用户池 API 在自定义用户界面 AWS 中实现 TOTP MFA，请参](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html)阅。[为用户配置 TOTP MFA](#totp-mfa-set-up-api)

要向用户池添加 MFA，请参阅 [向用户池添加 MFA](user-pool-settings-mfa.md)。

**TOTP MFA 注意事项和限制**

1. Amazon Cognito 通过可生成 TOTP 代码的身份验证器应用程序支持软件令牌 MFA。Amazon Cognito 不支持基于硬件的 MFA。

1. 当您的用户池要求尚未进行配置的用户提供 TOTP 时，您的用户将收到一个一次性访问令牌，应用程序可使用该令牌为用户激活 TOTP MFA。在用户注册了额外的 TOTP 登录安全要素之前，后续的登录尝试将失败。
   + 通过 `SignUp` API 操作或通过托管登录来登录用户池的用户，在完成注册时将收到一次性的令牌。
   + 在您创建用户并且用户设置初始密码后，Amazon Cognito 会从托管登录向用户颁发一次性令牌。如果您为用户设置了永久密码，则 Amazon Cognito 会在用户首次登录时颁发一次性令牌。
   + Amazon Cognito 不会向使用或 API 操作登录的管理员创建的用户发放一次性令牌。[InitiateAuth[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)在您的用户成功完成质询来设置初始密码后，或者如果您为用户设置永久密码，Amazon Cognito 会立即向用户提出质询来设置 MFA。

1. 如果用户池中需要 MFA 的用户已收到一次性访问令牌但尚未设置 TOTP MFA，则在设置 MFA 之前，用户无法使用托管登录进行登录。您可以代替访问令牌，而是在请求中使用`MFA_SETUP`质询[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)或[AssociateSoftwareToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AssociateSoftwareToken.html)请求[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)中的`session`响应值。

1. 如果您的用户已设置 TOTP，则他们可以将其用于 MFA，即使您以后停用用户池的 TOTP。

1. Amazon Cognito TOTPs 仅接受使用 HMAC 哈希函数生成代码的身份验证器应用程序。SHA1 使用 SHA-256 哈希生成的代码会返回 `Code mismatch` 错误。

## 为用户配置 TOTP MFA
<a name="totp-mfa-set-up-api"></a>

当用户首次登录时，您的应用程序使用他们的一次性访问令牌生成 TOTP 私钥，并以文本或二维码格式将其呈现给用户。您的用户配置其身份验证器应用程序并为后续登录尝试提供 TOTP。您的应用程序或托管登录在 MFA 质询响应中向 Amazon Cognito 提交 TOTP。

在某些情况下，托管登录会提示新用户设置 TOTP 身份验证器。有关更多信息，请参阅[用户运行时的 MFA 逻辑详情](user-pool-settings-mfa.md#user-pool-settings-mfa-user-outcomes)。

**Topics**
+ [关联 TOTP 软件令牌](#user-pool-settings-mfa-totp-associate-token)
+ [验证 TOTP 令牌](#user-pool-settings-mfa-totp-verification)
+ [使用 TOTP MFA 登录](#user-pool-settings-mfa-totp-sign-in)
+ [删除 TOTP 令牌](#user-pool-settings-mfa-totp-remove)

### 关联 TOTP 软件令牌
<a name="user-pool-settings-mfa-totp-associate-token"></a>

要关联 TOTP 令牌，请向用户发送一个必须使用一次性密码来验证的秘密代码。关联令牌需要执行三个步骤。

1. 当您的用户选择 TOTP 软件令牌 MFA 时，[AssociateSoftwareToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AssociateSoftwareToken.html)调用返回为用户帐户生成的唯一共享密钥代码。您可以使用访问令牌或会话字符串进行授权 AssociateSoftwareToken 。

1. 您的应用程序向用户呈现私钥或您从私钥生成的二维码。您的用户必须将密钥输入到 TOTP 生成应用程序（如 Google Authenticator）中，方式可以是扫描您的应用程序根据私有密钥生成的二维码，也可以是手动输入该密钥。

1. 您的用户用身份验证器应用程序（例如 Google Authenticator）输入密钥或扫描二维码，该应用程序开始生成代码。

### 验证 TOTP 令牌
<a name="user-pool-settings-mfa-totp-verification"></a>

接下来验证 TOTP 令牌。要求您的用户提供示例代码并将其提供给 Amazon Cognito 服务，以确认用户成功生成 TOTP 代码，如下所示。

1. 您的应用程序会提示用户输入代码，以证明他们已正确设置了身份验证器应用程序。

1. 用户的身份验证器应用程序显示一个临时密码。身份验证器应用程序根据您提供给用户的密钥生成密码。

1. 用户输入他们的临时密码。您的应用程序在 `[VerifySoftwareToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifySoftwareToken.html)` API 请求中将临时密码传递给 Amazon Cognito。

1.  Amazon Cognito 保留与用户关联的密钥，并生成 TOTP 并将其与用户提供的 TOTP 进行比较。如果匹配，`VerifySoftwareToken` 返回 `SUCCESS` 响应。

1. Amazon Cognito 将 TOTP 要素与用户关联起来。

1. 如果 `VerifySoftwareToken` 操作返回 `ERROR` 响应，请确保用户的时钟正确且没有超过最大重试次数。Amazon Cognito 接受在尝试前后 30 秒之内的 TOTP 令牌，以容许轻微的时钟偏差。解决问题后，请重试该 VerifySoftwareToken 操作。

### 使用 TOTP MFA 登录
<a name="user-pool-settings-mfa-totp-sign-in"></a>

此时，您的用户可使用基于时间的一次性密码登录。过程如下所述。

1. 用户将输入其用户名和密码来登录客户端应用程序。

1. TOTP MFA 质询被调用，您的应用程序提示用户输入临时密码。

1. 您的用户从关联的 TOTP 生成应用程序获取临时密码。

1. 您的用户在您的客户端应用程序中输入 TOTP 代码。您的应用程序通知 Amazon Cognito 服务以验证该代码。对于每次登录，都[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)应调用以获取对新 TOTP 身份验证质询的响应。

1. 如果令牌通过 Amazon Cognito 验证，则登录成功，您的用户可以继续完成身份验证流程。

### 删除 TOTP 令牌
<a name="user-pool-settings-mfa-totp-remove"></a>

最后，您的应用程序应允许您的用户停用他们的 TOTP 配置。当前，您无法删除用户的 TOTP 软件令牌。要替换用户的软件令牌，请关联并验证新的软件令牌。要为用户停用 TOTP MFA，请致电[SetUserMFAPreference](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserMFAPreference.html)将您的用户修改为不使用 MFA 或仅使用 SMS MFA。

1. 在您的应用程序中为想要重置 MFA 的用户创建界面。在此界面中提示用户输入密码。

1. 如果 Amazon Cognito 返回 TOTP MFA 质询，请将用户的 MFA 偏好设置更新为。[SetUserMFAPreference](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetUserMFAPreference.html)

1. 在您的应用程序中，告知您的用户他们已停用 MFA 并提示他们重新登录。

## 为托管登录 TOTP MFA 配置您的 AWS WAF 网页 ACL
<a name="totp-waf"></a>

当您的 AWS WAF Web ACL 与用户池相关联，并且您的 Web ACL 中的规则显示了验证码时，这可能会导致托管登录 TOTP 注册中出现不可恢复的错误。 AWS WAF 验证码规则*仅*对托管登录和经典托管用户界面中的 TOTP MFA 产生这种影响。SMS MFA 不受影响。

当 CAPTCHA 规则不允许用户完成 TOTP MFA 设置时，Amazon Cognito 会显示以下错误。

由于 WAF captcha，不允许请求。

当你的用户池在后台发出的 [VerifySoftwareToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_VerifySoftwareToken.html)API 请求时 AWS WAF 提示输入验证码时，就会出现此错误。[AssociateSoftwareToken](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AssociateSoftwareToken.html)要创建一个包含 CAPTCHA 操作且不影响托管登录页面中 TOTP 的规则，请从您的规则中的 CAPTCHA 操作中排除 `x-amzn-cognito-operation-name` 标头的 `AssociateSoftwareToken` 和 `VerifySoftwareToken` 值。

以下屏幕截图显示了一个示例 AWS WAF 规则，该规则将 CAPTCHA 操作应用于`x-amzn-cognito-operation-name`标头值不为或的所有请求。`AssociateSoftwareToken` `VerifySoftwareToken`

![\[一条 AWS WAF 规则的屏幕截图，该规则将验证码操作应用于x-amzn-cognito-operation-name标头值不为或的所有请求。AssociateSoftwareToken VerifySoftwareToken\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/cup-WAF-rule-TOTP.png)


有关 AWS WAF 网络 ACLs 和 Amazon Cognito 的更多信息，请参阅。[将 AWS WAF Web ACL 与用户池关联](user-pool-waf.md)

# 具备威胁防护的高级安全功能
<a name="cognito-user-pool-settings-threat-protection"></a>

在创建用户池之后，即可使用 Amazon Cognito 控制台中导航菜单中的**威胁防护**。可以打开威胁防护功能并自定义为响应不同风险而执行的操作。或者，您可以使用审计模式收集与检测到的风险相关的指标，而无需应用任何安全缓解措施。在审计模式下，威胁防护会向 Amazon 发布指标 CloudWatch。在 Amazon Cognito 生成其第一个事件后，您即可看到指标。请参阅[查看威胁防护指标](metrics-for-cognito-user-pools.md#user-pool-settings-viewing-threat-protection-metrics)。

威胁防护（此前称为*高级安全功能*）是一组监控用户池中不必要活动的工具，也是用于自动关闭潜在恶意活动的配置工具。威胁防护为标准和自定义身份验证操作提供了不同的配置选项。例如，在设置了额外安全因素时，您可能想向使用可疑自定义身份验证登录的用户发送通知，而阻止使用基本的用户名和密码身份验证且处于相同风险级别的用户。

威胁防护在增值版功能计划中可用。有关更多信息，请参阅 [用户池功能计划](cognito-sign-in-feature-plans.md)。

以下用户池选项是威胁防护的组成部分。

**已泄露的凭证**  
用户将密码重复用于多个用户账户。Amazon Cognito 的已泄露凭证功能可编译公开泄露的用户名和密码数据，并将用户的凭证与泄露的凭证列表进行比较。已泄露凭证的检测还检查常猜测的密码。您可以在用户池的 username-and-password标准身份验证流程中检查凭据是否被泄露。Amazon Cognito 不会在安全远程密码（SRP）或自定义身份验证流程中检测凭证是否泄露。  
您可以选择用于提示检查已泄露凭证的用户操作，以及您希望 Amazon Cognito 采取的应对措施。对于登录、注册和密码更改事件，Amazon Cognito 可以**禁止登录**或**允许登录**。在这两种情况下，Amazon Cognito 都会生成用户活动日志，您可以在其中找到有关该事件的更多信息。  
**了解详情**  
[使用凭证遭泄露检测功能](cognito-user-pool-settings-compromised-credentials.md)

**自适应身份验证**  
Amazon Cognito 可以查看来自用户登录请求的位置和设备信息，并应用自动响应来保护用户池中的用户账户免受可疑活动的侵害。您可以监控用户活动，并自动响应在用户名密码和 SRP 以及自定义身份验证中检测到的风险级别。  
当您激活威胁防护时，Amazon Cognito 会为用户活动分配风险评分。您可以为可疑活动指定自动响应：您可以**需要 MFA**、**禁止登录**，或者只记录活动详细信息和风险评分。您还可以自动发送电子邮件，将可疑活动通知用户，以便他们可以重置密码或采取其他自助操作。  
**了解详情**  
[使用自适应身份验证](cognito-user-pool-settings-adaptive-authentication.md)

**IP 地址允许列表和拒绝列表**  
在**全功能**模式下使用 Amazon Cognito 威胁防护，您可以创建基于 IP 地址的**始终阻止**和**始终允许**例外规则。对于来自**始终阻止**例外列表中 IP 地址的会话，自适应身份验证不会向其分配风险级别，该会话也无法登录您的用户池。  

**有关 IP 地址允许列表和阻止列表的需知信息**
+ **始终阻止**和**始终允许**规则必须使用 CIDR 格式表示，例如 `192.0.2.0/24`（24 位子网掩码）或 `192.0.2.252/32`（单个 IP 地址）。
+  IP 地址在 “**始终阻止**” IP 范围内的设备无法使用基于 SDK 的或托管登录应用程序进行注册或登录，但它们可以使用第三方登录。 IdPs
+ **始终允许**和**始终阻止**列表不会影响令牌刷新。
+ Amazon Cognito 不会对来自**始终允许** IP 范围的设备应用自适应身份验证 MFA 规则，但会应用凭证泄露规则。

**日志导出**  
威胁防护会将用户向您的用户池发起的身份验证请求的详细信息记录到日志中。这些日志包含威胁评估、用户信息以及位置和设备等会话元数据。您可以为这些日志创建外部归档以进行保留和分析。Amazon Cognito 用户池将威胁防护日志导出到亚马逊 S3、 CloudWatch 日志和亚马逊数据 Firehose。有关更多信息，请参阅 [查看和导出用户事件历史记录](cognito-user-pool-settings-adaptive-authentication.md#user-pool-settings-adaptive-authentication-event-user-history)。  
**了解详情**  
[导出威胁防护用户活动日志](exporting-quotas-and-usage.md#exporting-quotas-and-usage-user-activity)

**Topics**
+ [威胁防护的注意事项和限制](#cognito-user-pool-threat-protection-considerations)
+ [在用户池中开启威胁防护](#cognito-user-pool-threat-protection-activating)
+ [威胁防护强制执行概念](#cognito-user-pool-settings-threat-protection-threat-protection-enforcement)
+ [标准身份验证和自定义身份验证的威胁防护](#cognito-user-pool-settings-threat-protection-threat-protection-types)
+ [威胁防护先决条件](#cognito-user-pool-threat-protection-prerequisites)
+ [设置威胁防护](#cognito-user-pool-settings-configure-threat-protection)
+ [使用凭证遭泄露检测功能](cognito-user-pool-settings-compromised-credentials.md)
+ [使用自适应身份验证](cognito-user-pool-settings-adaptive-authentication.md)
+ [在应用程序中收集威胁防护的数据](user-pool-settings-viewing-threat-protection-app.md)

## 威胁防护的注意事项和限制
<a name="cognito-user-pool-threat-protection-considerations"></a>

**不同身份验证流程的威胁防护选项有所不同**  
Amazon Cognito 通过身份验证流程 `USER_PASSWORD_AUTH` 和 `ADMIN_USER_PASSWORD_AUTH` 来支持自适应身份验证和凭证遭泄露检测。您可以仅为 `USER_SRP_AUTH` 启用自适应身份验证。不能将威胁防护与联合身份验证登录一起使用。

**始终屏蔽会增加 IPs 请求配额**  
在您的用户池中阻止来自**始终阻止**例外列表中 IP 地址的请求，可以帮助您的用户池保持在[请求速率配额](https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html#category_operations)以内。

**威胁防护不会应用速率限制**  
一些恶意流量具有请求量大的特征，例如分布式拒绝服务 (DDoS) 攻击。Amazon Cognito 对传入流量应用的风险评分是基于单个请求的，并不考虑请求数。在大批量事件中，即便某些请求与大规模攻击无关，它们仍然可能因为应用层的原因而被赋予风险评分，并触发自动化响应。要对用户池中的容量攻击实施防御，请添加 AWS WAF Web。 ACLs有关更多信息，请参阅 [将 AWS WAF Web ACL 与用户池关联](user-pool-waf.md)。

**威胁防护不影响 M2M 请求**  
客户凭证授予的目的是在与用户帐户无关的情况下进行 machine-to-machine（M2M）授权。威胁防护仅监控用户池中的用户账户和密码。要在 M2M 活动中实现安全功能，请考虑 AWS WAF 用于监控请求率和内容的功能。有关更多信息，请参阅 [将 AWS WAF Web ACL 与用户池关联](user-pool-waf.md)。

## 在用户池中开启威胁防护
<a name="cognito-user-pool-threat-protection-activating"></a>

------
#### [ Amazon Cognito user pools console ]

**为用户池激活威胁防护**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 如果尚未激活，从**设置**菜单中激活增值版功能计划。

1. 选择**威胁防护**菜单，然后选择**激活**。

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

------
#### [ API ]

在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求中将您的功能计划设置为 Plus。以下部分示例请求正文将威胁防护设置为全功能模式。有关完整的示例请求，请参阅[示例](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html#API_CreateUserPool_Examples)。

```
"UserPoolAddOns": { 
      "AdvancedSecurityMode": "ENFORCED"
   }
```

------

威胁防护是一个总括性术语，指的是一组特征，用于监控用户操作以发现账户盗用的迹象，并自动采取措施来保护受影响的用户账户。当用户使用标准和自定义身份验证流程登录时，您可以对用户应用威胁防护设置。

威胁防护会[生成日志](cognito-user-pool-settings-adaptive-authentication.md#user-pool-settings-adaptive-authentication-event-user-history)，详细说明用户的登录、注销和其他活动。您可以将这些日志导出到第三方系统。有关更多信息，请参阅 [查看和导出用户事件历史记录](cognito-user-pool-settings-adaptive-authentication.md#user-pool-settings-adaptive-authentication-event-user-history)。

## 威胁防护强制执行概念
<a name="cognito-user-pool-settings-threat-protection-threat-protection-enforcement"></a>

威胁防护从*仅限审计*模式开始，在此模式下，用户池会监控用户活动、分配风险级别和生成日志。妥善的做法是，在启用*全功能模式*之前，在仅限审计模式下运行两周或更长时间。全功能模式包括一组针对检测到的风险活动和密码泄露的自动响应措施。在仅限审计模式下，您可以监控 Amazon Cognito 正在执行的威胁评估。您还可以[提供反馈](cognito-user-pool-settings-adaptive-authentication.md#user-pool-settings-adaptive-authentication-feedback)，帮助训练该特征以改进误报和漏报。

您可以在用户池级别配置威胁防护强制执行措施，以覆盖用户池中的所有应用程序客户端，也可以在单个应用程序客户端级别配置威胁防护。应用程序客户端威胁防护配置会覆盖用户池配置。要为应用程序客户端配置威胁防护，请在 Amazon Cognito 控制台中，导航到用户池的**应用程序客户端**菜单中的应用程序客户端设置。在这里，您可以**使用客户端级设置**并配置应用程序客户端专有的强制执行。

此外，您可以分别为标准和自定义身份验证类型配置威胁防护。

## 标准身份验证和自定义身份验证的威胁防护
<a name="cognito-user-pool-settings-threat-protection-threat-protection-types"></a>

配置威胁防护的方式取决于您在用户池和应用程序客户端中进行的身份验证类型。以下每种类型的身份验证都可以有自己的强制执行模式和自动响应。

**标准身份验证**  
*标准身份验证*是指通过用户名密码流程和托管登录实现的用户登录、注销及密码管理。当用户使用托管登录进行登录或使用以下 API `AuthFlow` 参数时，Amazon Cognito 威胁防护会监控操作的风险指标：    
**[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-AuthFlow)**  
`USER_PASSWORD_AUTH`、`USER_SRP_AUTH`。泄露的凭证功能无法在 `USER_SRP_AUTH` 登录时访问密码，并且不会监控或对这个流程中的事件采取行动。  
**[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html#CognitoUserPools-AdminInitiateAuth-request-AuthFlow)**  
`ADMIN_USER_PASSWORD_AUTH`、`USER_SRP_AUTH`。泄露的凭证特征无法在 `USER_SRP_AUTH` 登录时访问密码，并且不会监控或对这个流程中的事件采取行动。
您可以将标准身份验证的**强制执行模式**设置为**仅限审计**或**全功能**。要禁用标准身份验证的威胁监控，请将威胁防护设置为**没有强制执行**。

**自定义身份验证**  
*自定义身份验证*是使用[自定义质询 Lambda 触发器](user-pool-lambda-challenge.md)的用户登录。您无法在托管登录中进行自定义身份验证。当用户使用 `InitiateAuth` 和 `AdminInitiateAuth` 的 API `AuthFlow` 参数 `CUSTOM_AUTH` 登录时，Amazon Cognito 威胁防护会监控操作的风险指标。  
您可以将自定义身份验证的**强制执行模式**设置为**仅限审计**、**全功能**或**没有强制执行**。**没有强制执行**选项可在不影响其他威胁防护功能的情况下禁用自定义身份验证的威胁监控。

## 威胁防护先决条件
<a name="cognito-user-pool-threat-protection-prerequisites"></a>

在开始之前，您需要：
+ 用户池和应用程序客户端。有关更多信息，请参阅 [用户池入门](getting-started-user-pools.md)。
+ 在 Amazon Cognito 控制台中将多重身份验证（MFA）设置为**可选**,以使用基于风险的自适应身份验证功能。有关更多信息，请参阅 [向用户池添加 MFA](user-pool-settings-mfa.md)。
+ 如果您使用电子邮件通知，请转到 [Amazon SES 控制台](https://console.aws.amazon.com/ses/home)配置并验证要用于通知电子邮件的电子邮件地址或域。有关 Amazon SES 的更多信息，请参阅[在 Amazon SES 中验证身份](https://docs.aws.amazon.com/ses/latest/dg/verify-addresses-and-domains.html)。

## 设置威胁防护
<a name="cognito-user-pool-settings-configure-threat-protection"></a>

请按照以下说明设置用户池威胁防护。

**注意**  
要在 Amazon Cognito 用户池控制台中为应用程序客户端设置不同的威胁防护配置，请从**应用程序客户端**菜单中选择应用程序客户端，然后选择**使用客户端级设置**。

------
#### [ AWS 管理控制台 ]

**为用户池配置威胁防护**

1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**威胁防护**菜单，然后选择**激活**。

1. 选择要配置的威胁防护方法：**标准身份验证和自定义身份验证**。您可以为自定义身份验证和标准身份验证设置不同的强制执行模式，但在**全功能**模式下，它们共享自动响应的配置。

1. 选择**编辑**。

1. 选择**强制执行模式**。要立即开始对检测到的风险作出响应，请选择**全功能**并配置针对已泄露凭证和自适应身份验证的自动响应。要在用户级日志中收集信息 CloudWatch，请选择 “**仅审计**”。

   建议在启用操作之前，先将威胁防护保持在审计模式两周。在此期间，Amazon Cognito 可以了解应用程序用户的使用模式，并且您可以提供事件反馈以调整响应。

1. 如果您已选择**仅限审计**，请选择**保存更改**。如果您已选择**全功能**：

   1. 选择是否要进行**自定义**操作或使用 **Cognito 默认设置**响应可疑**已泄露的凭证**。**Cognito 默认设置**：

      1. 检测**登录**、**注册**和**密码更改**中的已泄露的凭证。

      1. 使用**禁止登录**操作响应已泄露的凭证。

   1. 如果您为**已泄露的凭证**选择了**自定义**操作，请选择 Amazon Cognito 将用于**事件检测**的用户池操作，以及您希望 Amazon Cognito 执行的**已泄露凭证的响应**。您可以使用可疑的已泄露凭证进行**禁止登录**或**允许登录**。

   1. 在**自适应身份验证**下，选择如何响应恶意登录尝试。选择是否要进行**自定义**操作或使用 **Cognito 默认设置**响应可疑恶意活动。当您选择 **Cognito 默认设置**时，Amazon Cognito 会阻止所有风险级别的登录，并且不会通知用户。

   1. 如果您针对**自适应身份验证**已选择**自定义操作**，请根据严重性级别选择 Amazon Cognito 对检测到的风险执行的 **自动风险响应**操作。当您针对风险级别分配响应时，您无法为较高风险级别分配限制性较小的响应。您可以为风险级别分配以下响应：

      1. **允许登录** – 不采取任何预防性操作。

      1. **可选 MFA** – 如果用户配置了 MFA，Amazon Cognito 将始终要求用户在登录时提供其它 SMS 或基于时间的一次性密码（TOTP）因素。如果用户没有配置 MFA，他们可以继续正常登录。

      1. **需要 MFA** – 如果用户配置了 MFA，Amazon Cognito 将始终要求用户在登录时提供其它短信或 TOTP 因素。如果用户没有配置 MFA，Amazon Cognito 将提示他们设置 MFA。在您自动要求用户使用 MFA 之前，请在应用程序中配置一种机制来捕获 SMS MFA 的电话号码，或为 TOTP MFA 注册身份验证器应用程序。

      1. **禁止登录** – 阻止用户登录。

      1. **通知用户** – 向用户发送电子邮件，其中包含有关 Amazon Cognito 检测到的风险以及您所采取的响应的信息。您可以为发送的消息自定义电子邮件消息模板。

1. 如果您在上一步骤中选择了**通知用户**，您可以自定义电子邮件发送设置和电子邮件消息模板以进行自适应身份验证。

   1. 在**电子邮件配置**下，选择您希望用于自适应身份验证的 **SES 区域**、**发件人电子邮件地址**、**发件人姓名**和**回复电子邮件地址**。有关将用户池电子邮件消息与 Amazon Simple Email Service 集成的更多信息，请参阅 [Amazon Cognito 用户池的电子邮件设置](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-email.html)。  
![\[用户事件历史记录\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/cup-advanced-security-ses-notification.png)

   1. 展开**电子邮件模板**以自定义包含 HTML 和纯文本版本电子邮件消息的自适应身份验证通知。要了解有关电子邮件消息模板的更多信息，请参阅[消息模板](cognito-user-pool-settings-message-customizations.md#cognito-user-pool-settings-message-templates)。

1. 扩展 **IP 地址例外**以创建**始终允许**或**始终阻止**的列表 IPv4 或 IPv6 地址范围，无论威胁防护风险评估如何，这些地址范围都将始终被允许或阻止。用 [CIDR 表示法](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation)指定 IP 地址范围（例如，192.168.100.0/24）。

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

------
#### [ API (user pool) ]

要为用户池设置威胁防护配置，请发送包含参数但不包含`UserPoolId`参数的 [SetRiskConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetRiskConfiguration.html)API 请求。`ClientId`以下是用户池的一个示例请求正文。此风险配置会根据风险的严重程度执行一系列不断升级的操作，并通知所有风险级别的用户。它对注册操作应用已泄露凭证阻止。

要强制执行此配置，您必须在单独的请求[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求`ENFORCED`中`AdvancedSecurityMode`将设置为。有关占位符模板的更多信息（如本例中的 `{username}`），请参阅 [配置 MFA、身份验证、验证和邀请消息](cognito-user-pool-settings-message-customizations.md)。

```
{
   "AccountTakeoverRiskConfiguration": { 
      "Actions": { 
         "HighAction": { 
            "EventAction": "MFA_REQUIRED",
            "Notify": true
         },
         "LowAction": { 
            "EventAction": "NO_ACTION",
            "Notify": true
         },
         "MediumAction": { 
            "EventAction": "MFA_IF_CONFIGURED",
            "Notify": true
         }
      },
      "NotifyConfiguration": { 
         "BlockEmail": { 
            "Subject": "You have been blocked for suspicious activity",
            "TextBody": "We blocked {username} at {login-time} from {ip-address}."
         },
         "From": "admin@example.com",
         "MfaEmail": { 
            "Subject": "Suspicious activity detected, MFA required",
            "TextBody": "Unexpected sign-in from {username} on device {device-name}. You must use MFA."
         },
         "NoActionEmail": { 
            "Subject": "Suspicious activity detected, secure your user account",
            "TextBody": "We noticed suspicious sign-in activity by {username} from {city}, {country} at {login-time}. If this was not you, reset your password."
         },
         "ReplyTo": "admin@example.com",
         "SourceArn": "arn:aws:ses:us-west-2:123456789012:identity/admin@example.com"
      }
   },
   "CompromisedCredentialsRiskConfiguration": { 
      "Actions": { 
         "EventAction": "BLOCK"
      },
      "EventFilter": [ "SIGN_UP" ]
   },
   "RiskExceptionConfiguration": { 
      "BlockedIPRangeList": [ "192.0.2.0/24","198.51.100.0/24" ],
      "SkippedIPRangeList": [ "203.0.113.0/24" ]
   },
   "UserPoolId": "us-west-2_EXAMPLE"
}
```

------
#### [ API (app client) ]

要为应用程序客户端设置威胁防护配置，请发送包含`UserPoolId`参数和参数的 [SetRiskConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SetRiskConfiguration.html)API 请求。`ClientId`以下是应用程序客户端的一个示例请求正文。此风险配置比用户池配置更为严格，会阻止高风险条目。该配置还将已泄露的凭证阻止应用于注册、登录和密码重置操作。

要强制执行此配置，您必须在单独的请求[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求`ENFORCED`中`AdvancedSecurityMode`将设置为。有关占位符模板的更多信息（如本例中的 `{username}`），请参阅 [配置 MFA、身份验证、验证和邀请消息](cognito-user-pool-settings-message-customizations.md)。

```
{
   "AccountTakeoverRiskConfiguration": { 
      "Actions": { 
         "HighAction": { 
            "EventAction": "BLOCK",
            "Notify": true
         },
         "LowAction": { 
            "EventAction": "NO_ACTION",
            "Notify": true
         },
         "MediumAction": { 
            "EventAction": "MFA_REQUIRED",
            "Notify": true
         }
      },
      "NotifyConfiguration": { 
         "BlockEmail": { 
            "Subject": "You have been blocked for suspicious activity",
            "TextBody": "We blocked {username} at {login-time} from {ip-address}."
         },
         "From": "admin@example.com",
         "MfaEmail": { 
            "Subject": "Suspicious activity detected, MFA required",
            "TextBody": "Unexpected sign-in from {username} on device {device-name}. You must use MFA."
         },
         "NoActionEmail": { 
            "Subject": "Suspicious activity detected, secure your user account",
            "TextBody": "We noticed suspicious sign-in activity by {username} from {city}, {country} at {login-time}. If this was not you, reset your password."
         },
         "ReplyTo": "admin@example.com",
         "SourceArn": "arn:aws:ses:us-west-2:123456789012:identity/admin@example.com"
      }
   },
   "ClientId": "1example23456789",
   "CompromisedCredentialsRiskConfiguration": { 
      "Actions": { 
         "EventAction": "BLOCK"
      },
      "EventFilter": [ "SIGN_UP", "SIGN_IN", "PASSWORD_CHANGE" ]
   },
   "RiskExceptionConfiguration": { 
      "BlockedIPRangeList": [ "192.0.2.1/32","192.0.2.2/32" ],
      "SkippedIPRangeList": [ "192.0.2.3/32","192.0.2.4/32" ]
   },
   "UserPoolId": "us-west-2_EXAMPLE"
}
```

------

# 使用凭证遭泄露检测功能
<a name="cognito-user-pool-settings-compromised-credentials"></a>

Amazon Cognito 可以检测用户的用户名和密码是否已在别处遭盗用。这种情况可能出现在用户在多个站点重复使用凭证时或它们使用不安全的密码时。Amazon Cognito 通过托管登录和 Amazon Cognito API 检查使用用户名和密码登录的[本地用户](cognito-terms.md#terms-localuser)。

在 Amazon Cognito 控制台的**威胁防护**菜单中，您可以配置**已泄露的凭证**。配置**事件检测**以选择要监控的用户事件，以查看是否有已泄露的凭证。配置**已泄露凭证的响应**，以选择在检测到已泄露的凭证时是允许还是阻止用户。Amazon Cognito 可以在登录、注册和密码更改期间检查是否有已泄露的凭证。

选择 “**允许登录**” 后，您可以查看 Amazon CloudWatch Logs 以监控 Amazon Cognito 对用户事件所做的评估。有关更多信息，请参阅 [查看威胁防护指标](metrics-for-cognito-user-pools.md#user-pool-settings-viewing-threat-protection-metrics)。当您选择**禁止登录**时，Amazon Cognito 会阻止使用已泄露的凭证的用户登录。当 Amazon Cognito 阻止用户登录时，它将用户的 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UserType.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UserType.html) 设置为 `RESET_REQUIRED`。具有 `RESET_REQUIRED` 状态的用户必须先更改密码，然后才能再次登录。

已泄露的凭证可针对以下用户活动检查密码。

**注册**  
您的用户池会检查用户在[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)操作中以及托管登录的注册页面中传输的密码，以确定是否存在泄露迹象。

**登录**  
您的用户池会检查用户在基于密码的登录中提交的密码是否存在泄露迹象。Amazon Cognito 可以在[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)两者中查看`USER_PASSWORD_AUTH`流[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)入、流入和`USER_AUTH`流入的`PASSWORD`选项。`ADMIN_USER_PASSWORD_AUTH`  
当前，对于采用安全远程密码（SRP）流程的登录操作，Amazon Cognito 不会检查是否有已泄露的凭证。SRP 在登录期间发送经过哈希处理的密码证明。Amazon Cognito 无法在内部访问密码，因此，它只能评估您的客户端以纯文本形式传递给它的密码。

**密码重置**  
在使用[ConfirmForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html)自助密码重置操作设置新用户密码的操作中，您的用户池会检查是否存在泄露迹象。此操作所需的代码由[ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)和生成[AdminResetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminResetUserPassword.html)。  
被泄露的凭据无法检查管理员设置的临时或永久密码。[AdminSetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminSetUserPassword.html)但是，使用临时密码时，您的用户池会根据[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)和中对`NEW_PASSWORD_REQUIRED`质询的响应来检查密码[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)。

要向用户池添加已泄露的凭证保护，请参阅 [具备威胁防护的高级安全功能](cognito-user-pool-settings-threat-protection.md)。

# 使用自适应身份验证
<a name="cognito-user-pool-settings-adaptive-authentication"></a>

借助自适应身份验证，可以将用户池配置为阻止可疑登录，或为响应增加的风险级别添加第二安全要素身份验证。对于每次登录尝试，Amazon Cognito 都会生成一个风险分数来表示登录请求来自遭盗用源的可能性。此风险评分基于您的应用程序提供的设备和用户因素，以及 Amazon Cognito 从请求中得出的其他因素。会影响 Amazon Cognito 风险评估的一些因素包括：IP 地址、用户代理以及与其他登录尝试之间的地理距离。当 Amazon Cognito 检测到用户会话中存在风险且用户尚未选择多重身份验证（MFA）方法时，自适应身份验证可以为用户池中的用户开启或要求 MFA。当您为用户激活 MFA 时，无论您如何配置自适应身份验证，他们都会收到在身份验证期间提供或设置第二因素的质询。从用户的角度来看，您的应用程序可以帮助他们设置 MFA，也可以选择让 Amazon Cognito 阻止他们再次登录，直到他们配置了附加因素。

Amazon Cognito 向亚马逊发布了有关登录尝试、其风险等级和挑战失败的指标。 CloudWatch有关更多信息，请参阅 [查看威胁防护指标](metrics-for-cognito-user-pools.md#user-pool-settings-viewing-threat-protection-metrics)。

要向用户池添加自适应身份验证，请参阅 [具备威胁防护的高级安全功能](cognito-user-pool-settings-threat-protection.md)。

**Topics**
+ [自适应身份验证概览](#security-cognito-user-pool-settings-adaptive-authentication-overview)
+ [将用户设备和会话数据添加到 API 请求](#user-pool-settings-adaptive-authentication-device-fingerprint)
+ [查看和导出用户事件历史记录](#user-pool-settings-adaptive-authentication-event-user-history)
+ [提供事件反馈](#user-pool-settings-adaptive-authentication-feedback)
+ [发送通知消息](#user-pool-settings-adaptive-authentication-messages)

## 自适应身份验证概览
<a name="security-cognito-user-pool-settings-adaptive-authentication-overview"></a>

在 Amazon Cognito 控制台中的**威胁防护**菜单中，您可以选择自适应身份验证的设置，包括在不同风险级别下采取什么操作，以及向用户发送的通知消息的自定义设置。您可以为所有应用程序客户端分配全局威胁防护配置，但将客户端级配置应用于各个应用程序客户端。

Amazon Cognito 自适应身份验证为每个用户会话分配以下风险级别之一：**高**、**中**、**低**或**无风险**。

将**强制执行方法**从**仅限审计**更改为**全功能**时，请仔细斟酌您的选项。您对风险等级应用的自动响应会影响 Amazon Cognito 为具有相同特征的后续用户会话分配的风险等级。例如，在您选择不采取任何操作或**允许**之后，对于 Amazon Cognito 最初评估为高风险的用户会话，Amazon Cognito 会认为类似会话的风险较低。


**对于每个风险级别，您可以选择以下选项：**  

|  Option  |  Action  | 
| --- | --- | 
| 允许 | 用户无需额外安全要素即可登录。 | 
| 可选 MFA | 已配置第二安全要素的用户需要完成第二安全要素质询才能登录。用于 SMS 的电话号码和 TOTP 软件令牌是可供使用的第二个安全要素。未配置第二个因素的用户只能使用一组凭证登录。 | 
| 需要 MFA | 已配置第二安全要素的用户需要完成第二安全要素质询才能登录。Amazon Cognito 阻止未配置第二个安全要素的用户登录。 | 
| 阻止 | Amazon Cognito 阻止指定风险级别下的所有登录尝试。 | 

**注意**  
您无需验证手机号码即可将其用于 SMS 来作为第二个身份验证要素。

## 将用户设备和会话数据添加到 API 请求
<a name="user-pool-settings-adaptive-authentication-device-fingerprint"></a>

当您使用 API 对用户进行注册、登录和重置密码时，可以收集用户会话的相关信息并将其传递给 Amazon Cognito 威胁防护。此信息包括用户的 IP 地址和唯一的设备标识符。

您可能在用户和 Amazon Cognito 之间有中间网络设备，例如代理服务或应用程序服务器。您可以收集用户的上下文数据并将其传递给 Amazon Cognito，以便自适应身份验证根据用户端点（而不是服务器或代理）的特征来计算风险。如果您的客户端应用程序直接调用 Amazon Cognito API 操作，自适应身份验证会自动记录源 IP 地址。但是，它不会记录其他设备信息（例如 `user-agent`），除非您也收集设备指纹。

使用 Amazon Cognito 上下文数据收集库生成这些数据，然后使用和参数将其提交给 Amazon Cognito 威胁防护。[ContextData[UserContextData](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UserContextDataType.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ContextDataType.html)上下文数据收集库包含在 AWS SDKs。有关更多信息，请参阅 [将 Amazon Cognito 身份验证和授权与 Web 和移动应用程序集成](cognito-integrate-apps.md)。如果您有增值版功能计划，则可以提交 `ContextData`。有关更多信息，请参阅 [设置威胁防护](cognito-user-pool-settings-threat-protection.md#cognito-user-pool-settings-configure-threat-protection)。

当您从应用程序服务器调用以下经过 Amazon Cognito 身份验证的 API 操作时，请在 `ContextData` 参数中传递用户设备的 IP。此外，请传递服务器名称、服务器路径和编码的设备指纹数据。
+ [AdminInitiateAuth ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)
+ [AdminRespondToAuthChallenge ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)

当您调用 Amazon Cognito 未经身份验证的 API 操作时，您可以将 `UserContextData` 提交到 Amazon Cognito 威胁防护。此数据在 `EncodedData` 参数中包括设备指纹。如果您符合以下条件，也可以在 `UserContextData` 中提交 `IpAddress` 参数：
+ 您的用户池使用增值版功能计划。有关更多信息，请参阅 [用户池功能计划](cognito-sign-in-feature-plans.md)。
+ 您的应用程序客户端具有客户端密钥。有关更多信息，请参阅 [特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。
+ 您已在应用程序客户端中激活 **接受其他用户上下文数据**。有关更多信息，请参阅 [接受额外的用户上下文数据（AWS 管理控制台）](#user-pool-settings-adaptive-authentication-accept-user-context-data)。

您的应用程序可以在以下 Amazon Cognito 未经验证的 API 操作中，使用编码的设备指纹数据和用户设备的 IP 地址填充 `UserContextData` 参数。
+ [InitiateAuth ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)
+ [RespondToAuthChallenge ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)
+ [SignUp ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)
+ [ConfirmSignUp ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html)
+ [ForgotPassword ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)
+ [ConfirmForgotPassword ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html)
+ [ResendConfirmationCode ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html)

### 接受额外的用户上下文数据（AWS 管理控制台）
<a name="user-pool-settings-adaptive-authentication-accept-user-context-data"></a>

激活**接受其他用户上下文数据**功能后，用户池在 `UserContextData` 参数中接受 IP 地址。在以下情况下，您无需激活此功能：
+ 您的用户只能使用经过身份验证的 API 操作（例如）登录 [AdminInitiateAuth ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)，并且您使用`ContextData`参数。
+ 您只希望未经身份验证的 API 操作向 Amazon Cognito 威胁防护发送设备指纹，而不是 IP 地址。

在 Amazon Cognito 控制台中按如下方式更新应用程序客户端，以添加对其他用户上下文数据的支持。

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。

1. 在导航窗格中，选择 **管理您的用户池**，然后选择要编辑的用户池。

1. 选择**应用程序客户端**菜单。

1. 选择或创建一个应用程序客户端。有关更多信息，请参阅[配置用户池应用程序客户端](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html)。

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

1. 在应用程序客户端的**高级身份验证设置**下，选择**接受其他用户上下文数据**。

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

要将您的应用程序客户端配置为接受 Amazon Cognito API 中的用户情境数据，请在[CreateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)或`EnablePropagateAdditionalUserContextData`[UpdateUserPoolClient](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)请求`true`中设置为。有关在 Web 或移动应用程序中使用威胁防护功能的信息，请参阅[在应用程序中收集威胁防护的数据](user-pool-settings-viewing-threat-protection-app.md)。当您的应用程序从服务器调用 Amazon Cognito 时，从客户端收集用户上下文数据。以下是使用 JavaScript SDK 方法的示例`getData`。

```
var EncodedData = AmazonCognitoAdvancedSecurityData.getData(username, userPoolId, clientId);
```

在设计应用程序以使用自适应身份验证时，建议您将最新的 Amazon Cognito 开发工具包集成到应用程序中。最新版本的开发工具包收集设备指纹信息，如设备 ID、模型和时区。有关 Amazon Cognito 的更多信息 SDKs，请参阅[安装用户池软件开发](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-sdk-links.html)工具包。Amazon Cognito 威胁防护功能只为应用程序以正确格式提交的事件保存和分配风险评分。如果 Amazon Cognito 返回错误响应，请检查您的请求是否包含有效的密钥哈希以及该`IPaddress`参数是否有效 IPv4 或 IPv6 地址。

**`ContextData` 和 `UserContextData` 资源**
+ AWS Amplify 适用于 Android 的 SDK：[GetUserContextData](https://github.com/aws-amplify/aws-sdk-android/blob/main/aws-android-sdk-cognitoidentityprovider/src/main/java/com/amazonaws/mobileconnectors/cognitoidentityprovider/CognitoUserPool.java#L626)
+ AWS Amplify 适用于 iOS 的 SDK：[userContextData](https://github.com/aws-amplify/aws-sdk-ios/blob/d3cd4fa0086b526f2f5c9c6c58880c9da7004c66/AWSCognitoIdentityProviderASF/AWSCognitoIdentityProviderASF.m#L21)
+ JavaScript: [amazon-cognito-advanced-security-](https://amazon-cognito-assets.us-east-1.amazoncognito.com/amazon-cognito-advanced-security-data.min.js) data.min.js

## 查看和导出用户事件历史记录
<a name="user-pool-settings-adaptive-authentication-event-user-history"></a>

当您启用威胁防护时，Amazon Cognito 会为用户的每个身份验证事件生成日志。默认情况下，您可以在 Amazon Cognito 控制台的 “**用户**” 菜单中或[AdminListUserAuthEvents](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminListUserAuthEvents.html)通过 API 操作查看用户日志。您也可以将这些事件导出到外部系统，例如 CloudWatch 日志、Amazon S3 或 Amazon Data Firehose。导出特征使您自己的安全分析系统更容易访问有关应用程序中用户活动的安全信息。

**Topics**
+ [查看用户事件历史记录（AWS 管理控制台）](#user-pool-settings-adaptive-authentication-event-user-history-console)
+ [查看用户事件历史记录（API/CLI）](#user-pool-settings-adaptive-authentication-event-user-history-api-cli)
+ [导出用户身份验证事件](#user-pool-settings-adaptive-authentication-event-user-history-exporting)

### 查看用户事件历史记录（AWS 管理控制台）
<a name="user-pool-settings-adaptive-authentication-event-user-history-console"></a>

要查看某个用户的登录历史记录，您可以在 Amazon Cognito 控制台的**用户**菜单中选择该用户。Amazon Cognito 会将用户事件历史记录保留两年。

![\[用户事件历史记录\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/cup-advanced-security-event-history.png)


每个登录事件都有一个事件 ID。该事件还包含对应的上下文数据，如位置、设备详细信息和风险检测结果。

您还可以将事件 ID 与 Amazon Cognito 在记录事件时颁发的令牌关联起来。ID 和访问令牌在其有效载荷中包含此事件 ID。Amazon Cognito 还将刷新令牌的使用与原始事件 ID 相关联。您可以通过原始事件 ID 追溯到导致颁发 Amazon Cognito 令牌的登录事件的事件 ID。您可以跟踪系统中的令牌在特定身份验证事件中的使用。有关更多信息，请参阅 [了解用户池 JSON 网络令牌 (JWTs)](amazon-cognito-user-pools-using-tokens-with-identity-providers.md)。

### 查看用户事件历史记录（API/CLI）
<a name="user-pool-settings-adaptive-authentication-event-user-history-api-cli"></a>

[您可以使用 Amazon Cognito API 操作[AdminListUserAuthEvents](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminListUserAuthEvents.html)或带有-events 的 AWS Command Line Interface (AWS CLI) 来查询用户事件历史记录。admin-list-user-auth](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-list-user-auth-events.html)

------
#### [ AdminListUserAuthEvents request ]

以下请求正文 `AdminListUserAuthEvents` 返回一个用户的最新活动日志。

```
{
  "UserPoolId": "us-west-2_EXAMPLE", 
  "Username": "myexampleuser", 
  "MaxResults": 1
}
```

------
#### [ admin-list-user-auth-events request ]

以下请求 `admin-list-user-auth-events` 返回一个用户的最新活动日志。

```
aws cognito-idp admin-list-user-auth-events --max-results 1 --username myexampleuser --user-pool-id us-west-2_EXAMPLE
```

------
#### [ Response ]

Amazon Cognito 对两个请求返回相同的 JSON 响应正文。以下是未发现包含风险因素的托管登录事件的响应示例：

```
{
    "AuthEvents": [
        {
            "EventId": "[event ID]",
            "EventType": "SignIn",
            "CreationDate": "[Timestamp]",
            "EventResponse": "Pass",
            "EventRisk": {
                "RiskDecision": "NoRisk",
                "CompromisedCredentialsDetected": false
            },
            "ChallengeResponses": [
                {
                    "ChallengeName": "Password",
                    "ChallengeResponse": "Success"
                }
            ],
            "EventContextData": {
                "IpAddress": "192.168.2.1",
                "DeviceName": "Chrome 125, Windows 10",
                "Timezone": "-07:00",
                "City": "Bellevue",
                "Country": "United States"
            }
        }
    ],
    "NextToken": "[event ID]#[Timestamp]"
}
```

------

### 导出用户身份验证事件
<a name="user-pool-settings-adaptive-authentication-event-user-history-exporting"></a>

配置您的用户池以将用户事件从威胁防护导出到外部系统。支持的外部系统（Amazon S3、 CloudWatch Logs 和 Amazon Data Firehose）可能会增加您发送或检索的数据 AWS 账单的费用。有关更多信息，请参阅 [导出威胁防护用户活动日志](exporting-quotas-and-usage.md#exporting-quotas-and-usage-user-activity)。

------
#### [ AWS 管理控制台 ]

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**日志流式传输**菜单。选择**编辑**。

1. 在**日志记录状态**下，选中**激活用户活动日志导出**旁边的复选框。

1. 在**日志目标**下，选择要处理日志 AWS 服务 的：**CloudWatch 日志组**、**Amazon Data Firehose 流**或 **S3 存储**桶。

1. 您的选择将使用相应的资源类型填入资源选择器。从列表中选择日志组、流或存储桶。您也可以选择**创建**按钮，导航到所选服务的 AWS 管理控制台 并创建新资源。

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

------
#### [ API ]

为您的用户活动日志选择一种目标类型。

以下是将 Firehose 流设置为日志目标的示例 `SetLogDeliveryConfiguration` 请求正文。

```
{
   "LogConfigurations": [
      {
         "EventSource": "userAuthEvents",
         "FirehoseConfiguration": {
            "StreamArn": "arn:aws:firehose:us-west-2:123456789012:deliverystream/example-user-pool-activity-exported"
         },
         "LogLevel": "INFO"
      }
   ],
   "UserPoolId": "us-west-2_EXAMPLE"
}
```

以下是将 Amazon S3 存储桶设置为日志目标的示例 `SetLogDeliveryConfiguration` 请求正文。

```
{
   "LogConfigurations": [
      {
         "EventSource": "userAuthEvents",
         "S3Configuration": { 
            "BucketArn": "arn:aws:s3:::amzn-s3-demo-logging-bucket"
         },
         "LogLevel": "INFO"
      }
   ],
   "UserPoolId": "us-west-2_EXAMPLE"
}
```

以下是将 CloudWatch 日志组设置为日志目标的`SetLogDeliveryConfiguration`请求正文示例。

```
{
   "LogConfigurations": [
      {
         "EventSource": "userAuthEvents",
         "CloudWatchLogsConfiguration": { 
            "LogGroupArn": "arn:aws:logs:us-west-2:123456789012:log-group:DOC-EXAMPLE-LOG-GROUP"
         },
         "LogLevel": "INFO"
      }
   ],
   "UserPoolId": "us-west-2_EXAMPLE"
}
```

------

## 提供事件反馈
<a name="user-pool-settings-adaptive-authentication-feedback"></a>

事件反馈实时影响风险评估，并随着时间的推移改进风险评估算法。您可以通过 Amazon Cognito 控制台和 API 操作提供有关登录尝试有效性的反馈。

**注意**  
您的事件反馈会影响 Amazon Cognito 为具有相同特征的后续用户会话分配的风险等级。

在 Amazon Cognito 控制台中，从**用户**菜单中选择一个用户，然后选择**提供事件反馈**。您可以查看事件详细信息，并选择**设为有效**或**设为无效**。

控制台在**用户**菜单中的“用户详细信息”中列出了登录历史记录。您可以选择某个条目来将事件标记为有效或无效。您还可以通过用户池 API 操作和 AWS CLI 命令 [admin-update-auth-event-fe [AdminUpdateAuthEventFeedback](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateAuthEventFeedback.html)edback 提供反馈](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-update-auth-event-feedback.html)。

当您在 Amazon Cognito 控制台中选择**设为有效**或在 API 中提供 `valid` 的 `FeedbackValue` 值时，您告诉 Amazon Cognito 您信任某个用户会话（Amazon Cognito 已在其中评估了某种风险等级）。当您在 Amazon Cognito 控制台中选择**设为无效**或在 API 中提供 `invalid` 的 `FeedbackValue` 值时，您告诉 Amazon Cognito 您不信任某个用户会话，或者您不认为 Amazon Cognito 评估的风险等级足够高。

## 发送通知消息
<a name="user-pool-settings-adaptive-authentication-messages"></a>

通过威胁防护功能，Amazon Cognito 可以通知您的用户存在有风险的登录尝试。Amazon Cognito 还可以提示用户选择链接以指示登录是有效还是无效。Amazon Cognito 使用此反馈来提高用户池的风险检测准确性。

**注意**  
只有当用户的操作生成自动风险响应时，Amazon Cognito 才会向其发送通知消息：阻止登录、允许登录、将 MFA 设置为可选或要求 MFA。某些请求可能会被分配一定风险级别，但不会生成自适应身份验证的自动风险响应；对于这些请求，您的用户池不会发送通知。例如，错误的密码可能会被记录并附带风险评级，但 Amazon Cognito 的响应是直接拒绝登录，而不是应用自适应身份验证规则。

在**自动风险响应**部分，对低、中或高风险案例选择**通知用户**。

![\[通知用户\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/cup-adaptive-auth.png)


无论您的用户是否验证了电子邮件地址，Amazon Cognito 都会向他们发送电子邮件通知。

您可以自定义通知电子邮件消息，并提供这些消息的纯文本和 HTML 版本。要自定义您的电子邮件通知，请在威胁防护配置中，从**自适应身份验证消息**中打开**电子邮件模板**。要了解有关电子邮件模板的更多信息，请参阅 [消息模板](cognito-user-pool-settings-message-customizations.md#cognito-user-pool-settings-message-templates)。

# 在应用程序中收集威胁防护的数据
<a name="user-pool-settings-viewing-threat-protection-app"></a>

Amazon Cognito [自适应身份验证](cognito-user-pool-settings-adaptive-authentication.md)根据用户登录尝试的上下文详细信息评估账户盗用尝试的风险等级。您的应用程序必须向 API 请求添加*上下文数据*，这样 Amazon Cognito 威胁防护功能才能更准确地评估风险。上下文数据是诸如 IP 地址、浏览器代理、设备信息和请求标头之类的信息，这些信息提供有关用户如何连接到用户池的上下文信息。

向 Amazon Cognito 提交此上下文的应用程序的核心责任是向用户池发送身份验证请求中的一个 `EncodedData` 参数。要将这些数据添加到您的请求中，您可以使用软件开发工具包实现 Amazon Cognito，该软件开发工具包可以自动为您生成这些信息，也可以实现一个适用于 JavaScript iOS 或 Android 的模块来收集这些数据。必须实现直接向 Amazon Cognito 发出请求的@@ *仅限客户端*的应用程序。 AWS Amplify SDKs具有中间服务器或 API 组件的*客户端-服务器*应用程序必须实施单独的 SDK 模块。

在以下情况下，您的身份验证前端无需任何额外配置即可管理用户上下文数据的收集：
+ 托管登录会自动收集上下文数据并将其提交给威胁防护。
+ 所有 AWS Amplify 库的身份验证方法中都内置了上下文数据集合。

## 使用 Amplify 在仅限客户端的应用程序中提交用户上下文数据
<a name="user-pool-settings-viewing-threat-protection-app-amplify"></a>

![\[Amplify 应用程序中收集数据以进行威胁防护的概览图。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/user-pools-asf-amplify-data-collection.png)


Amplify SDKs 支持直接通过 Amazon Cognito 进行身份验证的移动客户端。此类客户端直接向 Amazon Cognito 公共 API 操作发出 API 请求。默认情况下，Amplify 客户端会自动收集上下文数据以进行威胁防护。

带的 Amplify 应用程序是个 JavaScript 例外。它们需要添加一个用于收集用户上下文数据的[JavaScript 模块](#user-pool-settings-viewing-threat-protection-app-additional-resources-js)。

通常，此配置中的应用程序使用未经身份验证的 API 操作，例如[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)和。[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)该[UserContextData](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UserContextDataType.html)对象有助于更准确地评估这些操作的风险。Amplify SDKs 将设备和会话信息添加到的`EncodedData`参数中。`UserContextData`

## 在客户端-服务器应用程序中收集上下文数据
<a name="user-pool-settings-viewing-threat-protection-app-server-side"></a>

某些应用程序的前端层用于收集用户身份验证数据，应用程序的后端层用于将身份验证请求提交到 Amazon Cognito。在由微服务支持的 Web 服务器和应用程序中，这是一种常见的架构。在这些应用程序中，必须导入公共上下文数据收集库。

![\[中包含威胁防护上下文数据的服务器端身份验证概述。 JavaScript\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/user-pools-asf-non-amplify-data-collection.png)


通常，此配置中的应用服务器使用经过身份验证的 API 操作，例如[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)和[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)。该[ContextData](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html#CognitoUserPools-AdminInitiateAuth-request-ContextData)对象可帮助 Amazon Cognito 更准确地评估这些操作的风险。`ContextData` 的内容是您的前端传递给服务器的编码数据，以及用户向服务器发出的 HTTP 请求中的其他详细信息。这些额外的上下文详细信息（例如 HTTP 标头和 IP 地址）为您的应用程序服务器提供了用户环境的特性。

您的应用服务器也可能使用未经身份验证的 API 操作（如[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)和）进行登录。[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)该[UserContextData](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-UserContextData)对象为这些操作中的威胁防护风险分析提供信息。可用的公共上下文数据收集库中的操作将安全信息添加到身份验证请求的 `EncodedData` 参数中。此外，将您的用户池配置为接受其他上下文数据，并将用户的源 IP 添加到 `UserContextData` 的 `IpAddress` 参数中。

**将上下文数据添加到客户端-服务器应用程序**

1. 在您的前端应用程序中，使用 iO [S、Android 或 JavaScript ](#user-pool-settings-viewing-threat-protection-app-additional-resources)模块从客户端收集经过编码的上下文数据。

1. 将编码后的数据和身份验证请求的详细信息传递给应用程序服务器。

1. 在应用程序服务器中，从 HTTP 请求中提取用户的 IP 地址、相关 HTTP 标头、请求的服务器名称和请求的路径。将这些值填充到你向 Amazon Cognito 发出 API 请求的[ContextData](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html#CognitoUserPools-AdminInitiateAuth-request-ContextData)参数中。

1. 使用您的 SDK 模块收集的已编码设备数据填充您的 API 请求中的 `ContextData` 的 `EncodedData` 参数。将此上下文数据添加到身份验证请求中。

## 客户端-服务器应用程序的上下文数据库
<a name="user-pool-settings-viewing-threat-protection-app-additional-resources"></a>

### JavaScript
<a name="user-pool-settings-viewing-threat-protection-app-additional-resources-js"></a>

`amazon-cognito-advanced-security-data.min.js` 模块收集了 `EncodedData`，您可以将其传递给应用程序服务器。

将该`amazon-cognito-advanced-security-data.min.js`模块添加到您的 JavaScript 配置中。`<region>`替换为以下 AWS 区域 列表中的：`us-east-1`、`us-east-2`、`us-west-2``eu-west-1`、`eu-west-2`、或`eu-central-1`。

```
<script src="https://amazon-cognito-assets.<region>.amazoncognito.com/amazon-cognito-advanced-security-data.min.js"></script>
```

要生成可在`EncodedData`参数中使用的`encodedContextData`对象，请将以下内容添加到您的 JavaScript 应用程序源中：

```
var encodedContextData = AmazonCognitoAdvancedSecurityData.getData(_username, _userpoolId, _userPoolClientId);
```

### iOS/Swift
<a name="user-pool-settings-viewing-threat-protection-app-additional-resources-ios"></a>

要生成上下文数据，iOS 应用程序可以集成适用于 iO [S 的移动 SDK](https://github.com/aws-amplify/aws-sdk-ios/tree/main) 模块 [AWSCognitoIdentityProviderASF](https://github.com/aws-amplify/aws-sdk-ios/tree/main/AWSCognitoIdentityProviderASF)。

要收集经过编码的上下文数据以进行威胁防护，请将以下代码段添加到您的应用程序中：

```
import AWSCognitoIdentityProviderASF

let deviceId = getDeviceId()
let encodedContextData = AWSCognitoIdentityProviderASF.userContextData(
                            userPoolId, 
                            username: username, 
                            deviceId: deviceId, 
                            userPoolClientId: userPoolClientId)
                                
/**
 * Reuse DeviceId from keychain or generate one for the first time.
 */
func getDeviceId() -> String {
    let deviceIdKey = getKeyChainKey(namespace: userPoolId, key: "AWSCognitoAuthAsfDeviceId")
    
   if let existingDeviceId = self.keychain.string(forKey: deviceIdKey) {
        return existingDeviceId
    }

    let newDeviceId = UUID().uuidString
    self.keychain.setString(newDeviceId, forKey: deviceIdKey)
    return newDeviceId
}

/**
 * Get a namespaced keychain key given a namespace and key
 */    
func getKeyChainKey(namespace: String, key: String) -> String {
    return "\(namespace).\(key)"
}
```

### Android
<a name="user-pool-settings-viewing-threat-protection-app-additional-resources-android"></a>

要生成上下文数据，安卓应用可以集成[适用于安卓的移动 SDK](https://github.com/aws-amplify/aws-sdk-android/tree/main) 模块 [aws-android-sdk-cognitoidentityprovider-asf](https://github.com/aws-amplify/aws-sdk-android/tree/main/aws-android-sdk-cognitoidentityprovider-asf)。

要收集经过编码的上下文数据以进行威胁防护，请将以下代码段添加到您的应用程序中：

```
UserContextDataProvider provider = UserContextDataProvider.getInstance();
// context here is android application context.
String encodedContextData = provider.getEncodedContextData(context, username, userPoolId, userPoolClientId);
```

# 将 AWS WAF Web ACL 与用户池关联
<a name="user-pool-waf"></a>

AWS WAF 是 Web 应用程序防火墙。借助 AWS WAF 网络访问控制列表 (Web ACL)，您可以保护您的用户池免受对经典托管用户界面、托管登录和 Amazon Cognito API 服务终端节点的不必要请求。Web ACL 使您可以对用户池响应的所有 HTTPS Web 请求进行精细控制。有关 AWS WAF Web 的更多信息 ACLs，请参阅《*AWS WAF 开发人员指南》*中的[管理和使用 Web 访问控制列表 (Web ACL)](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl.html)。

当您的 AWS WAF Web ACL 与用户池关联时，Amazon Cognito 会将您的用户请求中选定的非机密标头和内容转发到。 AWS WAF AWS WAF 检查请求的内容，将其与您在网页 ACL 中指定的规则进行比较，然后向 Amazon Cognito 返回响应。

## 关于 AWS WAF 网络 ACLs 和亚马逊 Cognito 的注意事项
<a name="user-pool-waf-things-to-know"></a>
+ 您无法配置 Web ACL 规则以匹配用户池请求中的个人身份信息（PII），例如用户名、密码、电话号码或电子邮件地址。此数据将不可用 AWS WAF。应改为配置 Web ACL 规则，使其基于标头、路径和正文中的会话数据进行匹配，例如 IP 地址、浏览器代理和所请求的 API 操作。
+ Web ACL 规则条件仅能在用户**首次**请求用户交互式托管登录页面时返回自定义的阻止响应。当后续连接与自定义阻止响应条件匹配时，虽然会返回您的自定义状态码、标头和重定向设置，但仍显示默认的阻止消息。
+ 被阻止的请求 AWS WAF 不计入任何请求类型的请求速率配额。该 AWS WAF 处理程序在 API 级别的限制处理程序之前被调用。
+ 当您创建 Web ACL 时，Web ACL 要经过一小段时间才能完全传播并可供 Amazon Cognito 使用。传播时间可以从几秒钟到几分钟不等。 AWS WAF [https://docs.aws.amazon.com/waf/latest/APIReference/API_AssociateWebACL.html#API_AssociateWebACL_Errors](https://docs.aws.amazon.com/waf/latest/APIReference/API_AssociateWebACL.html#API_AssociateWebACL_Errors)当您尝试在 Web ACL 完全传播之前将其关联时，将返回。
+ 您可以将一个 Web ACL 与每个用户池相关联。
+ 您的请求可能会导致负载超出 AWS WAF 可以检查的负载限制。请参阅*AWS WAF 开发者指南*中的[超大请求组件处理](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-oversize-handling.html)，了解如何配置如何 AWS WAF 处理来自 Amazon Cognito 的超大请求。
+ 您无法将使用[防 AWS WAF 欺诈控制账户盗用 (ATP)](https://docs.aws.amazon.com/waf/latest/developerguide/waf-atp.html) 的网络 ACL 与 Amazon Cognito 用户池相关联。ATP 功能位于 `AWS-AWSManagedRulesATPRuleSet` 托管规则组中。在将您的 Web ACL 与用户池关联之前，请确保它不使用此托管规则组。
+ 当您的 AWS WAF Web ACL 与用户池相关联，并且您的 Web ACL 中的规则显示了验证码时，这可能会导致托管登录 TOTP 注册中出现不可恢复的错误。要创建具有 CAPTCHA 操作且不影响托管登录 TOTP 的规则，请参阅[为托管登录 TOTP MFA 配置您的 AWS WAF 网页 ACL](user-pool-settings-mfa-totp.md#totp-waf)。

AWS WAF 检查对以下端点的请求。

**托管登录和经典托管 UI**  
对 [用户池端点和托管登录参考](cognito-userpools-server-contract-reference.md) 中所有端点的请求。

**公有 API 操作**  
您的应用程序向 Amazon Cognito API 发出的不使用 AWS 凭证进行授权的请求。这包括[InitiateAuth[RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)、和 API 操作[GetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html)。范围内的 API 操作 AWS WAF 不需要使用 AWS 凭据进行身份验证。它们未经身份验证，或者是使用会话字符串或访问令牌授权的。有关更多信息，请参阅 [按授权模型分组的 API 操作列表](authentication-flows-public-server-side.md#user-pool-apis-auth-unauth)。

您可以使用以下规则操作在 Web ACL 中配置规则：**计数**、**允许**、**阻止**，或者提供一个 **CAPTCHA** 以响应符合规则的请求。有关更多信息，请参阅 *AWS WAF 开发人员指南* 中的 [AWS WAF 规则](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rules.html)。根据规则操作，您可以自定义 Amazon Cognito 返回给用户的响应。

**重要**  
自定义错误响应的选项取决于您发出 API 请求的方式。  
您可以自定义托管登录请求的错误代码和响应正文。您只能在托管登录中为用户提供 CAPTCHA 以解决此问题。
对于您使用 Amazon Cognito [用户池 API](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html) 提出的请求，可以自定义收到**阻止**响应的请求的响应正文。您也可以指定 400–499 范围内的自定义错误代码。
 AWS Command Line Interface (AWS CLI) 和向生成**区块**或**验证码**响应的请求 AWS SDKs 返回`ForbiddenException`错误。

## 将 Web ACL 与您的用户池相关联
<a name="user-pool-waf-setting-up"></a>

要在您的用户池中使用网络 ACL，您的 AWS Identity and Access Management (IAM) 委托人必须具有以下 Amazon Cognito 和 AWS WAF 权限。有关 AWS WAF 权限的信息，请参阅《*AWS WAF 开发者指南》*中的 [AWS WAF API 权限](https://docs.aws.amazon.com/waf/latest/developerguide/waf-api-permissions-ref.html)。

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

****  

```
{
	"Version":"2012-10-17",		 	 	 
	"Statement": [
		{
			"Sid": "AllowWebACLUserPool",
			"Effect": "Allow",
			"Action": [
				"cognito-idp:ListResourcesForWebACL",
				"cognito-idp:GetWebACLForResource",
				"cognito-idp:AssociateWebACL"
			],
			"Resource": [
				"arn:aws:cognito-idp:*:123456789012:userpool/*"
			]
		},
		{
			"Sid": "AllowWebACLUserPoolWAFv2",
			"Effect": "Allow",
			"Action": [
				"wafv2:ListResourcesForWebACL",
				"wafv2:AssociateWebACL",
				"wafv2:DisassociateWebACL",
				"wafv2:GetWebACLForResource"
			],
			"Resource": "arn:aws:wafv2:*:123456789012:*/webacl/*/*"
		},
		{
			"Sid": "DisassociateWebACL1",
			"Effect": "Allow",
			"Action": "wafv2:DisassociateWebACL",
			"Resource": "*"
		},
		{
			"Sid": "DisassociateWebACL2",
			"Effect": "Allow",
			"Action": [
				"cognito-idp:DisassociateWebACL"
			],
			"Resource": [
				"arn:aws:cognito-idp:*:123456789012:userpool/*"
			]
		}
	]
}
```

------

尽管您必须授予 IAM 权限，但列出的操作仅用于说明权限，不对应于任何 [API 操作](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html)。

**激活 AWS WAF 您的用户池并关联 Web ACL**

1. 登录 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。

1. 在导航窗格中，选择 **用户池**，然后选择要编辑的用户池。

1. 在**安全性**部分，选择 **AWS WAF** 选项卡。

1. 选择**编辑**。

1. 选择 “** AWS WAF 与您的用户池一起使用**”。  
![\[选中 “与您的用户池 AWS WAF 一起使用” 的 AWS WAF 对话框的屏幕截图。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/cup-WAF-console.png)

1. 选择您已经创建**的AWS WAF Web ACL**，或者选择在中**创建 Web ACL AWS WAF，在中的**新 AWS WAF 会话中创建一个 Web ACL AWS 管理控制台。

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

要以编程方式将 Web ACL 与 AWS Command Line Interface 或 SDK 中的用户池关联，请使用 AWS WAF API [AssociateWeb中的 ACL](https://docs.aws.amazon.com/waf/latest/APIReference/API_AssociateWebACL.html)。Amazon Cognito 没有可关联 Web ACL 的单独 API 操作。

## 测试和记录 AWS WAF 网页 ACLs
<a name="user-pool-waf-evaluating-and-logging"></a>

当您在 Web ACL 中将规则操作设置为 C **ou** nt 时， AWS WAF 会将该请求添加到与该规则匹配的请求计数中。要使用您的用户池测试 Web ACL，请将规则操作设置为**计数**，并考虑与每条规则匹配的请求数量。例如，如果您要设置为**阻止**操作的规则与您确定为正常用户流量的大量请求相匹配，则您可能需要重新配置规则。有关更多信息，请参阅《AWS WAF 开发人员指南》**中的[测试和调整您的 AWS WAF 保护](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-testing.html)。

您还可以配置 AWS WAF 为将请求标头记录到亚马逊 CloudWatch 日志组、亚马逊简单存储服务 (Amazon S3) 存储桶或亚马逊数据 Firehose。您可以通过 `x-amzn-cognito-client-id` 和 `x-amzn-cognito-operation-name` 识别您使用用户池 API 发出的 Amazon Cognito 请求。托管登录请求仅包含 `x-amzn-cognito-client-id` 标头。有关更多信息，请参阅 *AWS WAF 开发人员指南* 中的[记录 Web ACL 流量](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html)。

AWS WAF web ACLs 在所有用户池[功能计划](cognito-sign-in-feature-plans.md)中都可用。 AWS WAF 的安全功能可作为 Amazon Cognito 威胁防护的补充。您可以在用户池中激活这两项功能。 AWS WAF 对用户池请求的检查单独收费。有关更多信息，请参阅[AWS WAF 定价](https://aws.amazon.com/waf/pricing)。

日志 AWS WAF 请求数据需要按您定位日志的服务收取额外费用。有关更多信息，请参阅 *AWS WAF 开发人员指南* 中的[记录 Web ACL 流量信息的定价](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html#logging-pricing)。

# 用户池区分大小写
<a name="user-pool-case-sensitivity"></a>

默认情况下，您在中创建的 Amazon Cognito 用户池不区分大小写。 AWS 管理控制台 当用户池不区分大小写时，*user@example.com* 和 *User@example.com* 指的是同一个用户。当用户池中的用户名不区分大小写时，`preferred_username` 和 `email` 属性也不区分大小写。

不区分大小写不仅适用于属性输入，也适用于输出。在不区分大小写的用户池中，混合大小写的属性值在用户池的文本输出中会被统一为小写。[用户池文本输出的示例包括用户[信息响应、用户](userinfo-endpoint.md)查询响应（如的输出）以及向 Lambda 触发器的输入事件。[GetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html)](cognito-user-pools-working-with-lambda-triggers.md)

要考虑用户池区分大小写设置，请根据备用用户属性识别应用程序代码中的用户。由于用户名、首选用户名或电子邮件地址属性的大小写在不同的用户配置文件中可能有所不同，因此请改为参阅 `sub` 属性。您还可以在用户池中创建不可变的自定义属性，并为每个新用户配置文件中的属性分配自己的唯一标识符值。首次创建用户时，可以将值写入您创建的不可改变的自定义属性。

**注意**  
无论您的用户池的区分大小写设置如何，Amazon Cognito 都要求来自 SAML 或 OIDC 身份提供商（IdP）的联合用户传递唯一且区分大小写的 `NameId` 或 `sub` 声明。有关唯一标识符区分大小写和 SAML 的更多信息 IdPs，请参阅[实施 SP 发起的 SAML 登录](cognito-user-pools-SAML-session-initiation.md#cognito-user-pools-saml-idp-authentication)。

创建区分大小写的用户池  
如果您使用 AWS Command Line Interface (AWS CLI) 和 API 操作（例如）创建资源 [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)，则必须将布尔`CaseSensitive`参数设置为`false`。此设置将创建不区分大小写的用户池。如果您不指定值，`CaseSensitive` 默认为 `true`。您在 Amazon Cognito 控制台中创建的用户池不区分大小写。要生成区分大小写的用户池，必须使用 `CreateUserPool` 操作。2020 年 2 月 12 日之前，无论平台如何，用户池都默认区分大小写。  
在 AWS 管理控制台 和`UsernameConfiguration`属性的**登录**菜单中 [DescribeUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UserPoolType.html#CognitoUserPools-Type-UserPoolType-UsernameConfiguration)，您可以查看账户中每个用户池的区分大小写设置。

迁移到新的用户池  
由于用户配置文件之间存在潜在冲突，您无法将 Amazon Cognito 用户池从区分大小写更改为不区分大小写。相反，请将用户迁移到新的用户池。您必须构建迁移代码才能解决与大小写相关的冲突。此代码必须返回唯一的新用户，或者在检测到冲突时拒绝登录尝试。在新的不区分大小写的用户池中，分配一个 [迁移用户 Lambda 触发器](user-pool-lambda-migrate-user.md)。该 AWS Lambda 函数可以在新的不区分大小写的用户池中创建用户。当用户使用不区分大小写的用户池登录失败时，Lambda 函数会从区分大小写的用户池中查找并复制该用户。您还可以针对事件激活迁移用户 Lambda 触发器。[ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)Amazon Cognito 会将用户信息和事件元数据从登录或密码恢复操作传递到您的 Lambda 函数。当函数在不区分大小写的用户池中创建新用户时，您可以使用事件数据来管理用户名和电子邮件地址之间的冲突。这些冲突是用户名和电子邮件地址之间的冲突，这些名称和地址在区分大小写的用户池中是唯一的，但在不区分大小写的用户池中则相同。  
有关如何在 Amazon Cognito 用户池之间使用迁移用户 Lambda 触发器的更多信息，[请参阅博客中的将用户迁移到 Amazon Cognito](https://aws.amazon.com/blogs/mobile/migrating-users-to-amazon-cognito-user-pools/) 用户池。 AWS 

# 用户池删除保护
<a name="user-pool-settings-deletion-protection"></a>

要使您的管理员不会意外删除用户池，请激活删除保护。启用删除保护后，必须先确认要删除用户池，然后才能将其删除。在中删除用户池时 AWS 管理控制台，可以同时停用删除保护。当您接受停用删除保护的提示并确认要删除时（如下图所示），Amazon Cognito 会删除您的用户池。

![\[的屏幕截图 AWS 管理控制台 显示了删除用户池的提示，并包含了同时停用删除保护的提示。\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/amazon-cognito-delete-user-pool-deactivate-deletion-protection.png)


如果您想通过 Amazon Cognito API 请求删除用户池，则必须先在请求`Inactive`中`DeletionProtection`更改为[UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)。如果您不停用删除保护，Amazon Cognito 会返回 `InvalidParameterException` 错误。停用删除保护后，可以在[DeleteUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DeleteUserPool.html)请求中删除用户池。

当您在 AWS 管理控制台中创建新的用户池时，Amazon Cognito 默认情况下会激活**删除保护**。当您使用 `CreateUserPool` API 创建用户池时，默认情况下未激活删除保护。要在使用 AWS CLI 或 AWS SDK 创建的用户池中使用此功能，请将`DeletionProtection`参数设置为`True`。

您可以在 Amazon Cognito 控制台的**设置**菜单中的**删除保护**容器中激活或停用删除保护状态。

# 配置删除保护


1. 转到 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。系统可能会提示您输入 AWS 凭证。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或[创建一个用户池](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 选择**设置**菜单并导航到**删除保护**选项卡。选择**激活**或**停用**。

1. 在下一个对话框中确认您的选择。

# 管理用户存在错误响应
<a name="cognito-user-pool-managing-errors"></a>

Amazon Cognito 支持自定义由用户池返回的错误响应。自定义错误响应可用于用户创建和身份验证、密码恢复和确认操作。

使用用户池应用程序客户端的 `PreventUserExistenceErrors` 设置，以启用或禁用用户存在相关错误。当您使用 Amazon Cognito 用户池 API 创建新的应用程序时，默认情况下 `PreventUserExistenceErrors` 为 `LEGACY` 或禁用。在 Amazon Cognito 控制台中，默认选定**防止用户已存在错误**选项（`PreventUserExistenceErrors` 设置为 `ENABLED`）。要更新 `PreventUserExistenceErrors` 配置，请执行以下操作之一：
+ 在 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html) API 请求中将 `PreventUserExistenceErrors` 的值更改为 `ENABLED` 和 `LEGACY`。
+ 在 Amazon Cognito 控制台中编辑应用程序客户端，并将**防止用户已存在错误**的状态更改为选定（`ENABLED`）和已取消选择（`LEGACY`）。

当此属性的值为 `LEGACY` 时，当用户尝试使用您的用户池中不存在的用户名登录时，应用程序客户端会返回 `UserNotFoundException` 错误响应。

当此属性的值为 `ENABLED` 时，应用程序客户端不会通过 `UserNotFoundException` 错误来透露您的用户池中不存在某个用户账户。当 `PreventUserExistenceErrors` 配置为 `ENABLED` 时，如果您提交一个不存在的用户名请求，会产生以下效果：
+ Amazon Cognito 会使用非特定信息响应 API 请求，否则其响应可能会泄露存在有效的用户。
+ Amazon Cognito 会向密码重置请求以及使用*除* [基于选择的身份验证](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)（`USER_AUTH`）之外的身份验证流程（例如 `USER_SRP_AUTH` 或 `CUSTOM_AUTH`）的身份验证请求，返回通用的身份验证失败响应。错误响应告知您用户名或密码不正确。
+ 对于基于选择的身份验证请求，Amazon Cognito 会从用户池允许的质询类型中随机选择一种进行响应。您的用户池可能会返回通行密钥、一次性密码或密码质询。
+ Amazon Cognito 账户确认和密码恢复的行为在返回表示代码已发送到模拟传送介质的响应和返回错误之间交 APIs 替进行。`InvalidParameterException`

以下信息详细说明了 `PreventUserExistenceErrors` 设置为 `ENABLED` 时用户池操作的行为。

## 身份验证和用户创建操作
<a name="cognito-user-pool-managing-errors-user-auth"></a>

您可以在用户名密码和安全远程密码（SRP）身份验证中配置错误响应。您还可以对使用自定义身份验证返回的错误进行自定义。基于选择的身份验证不受您的 `PreventUserExistenceErrors` 配置的影响。身份验证流程中的用户存在性披露细节

**基于选择的身份验证**  
在 `USER_AUTH` 基于选择的身份验证流程中，Amazon Cognito 会根据用户池配置和用户的属性，从可用的主身份验证因素中返回一个质询。此身份验证流程可以返回密码、安全远程密码 (SRP)、 WebAuthn (passkey)、SMS 一次性密码 (OTP) 或电子邮件 OTP 质询。当 `PreventUserExistenceErrors` 启用时，Amazon Cognito 会向不存在的用户发出质询，要求他们完成一种或多种可用的身份验证形式。当 `PreventUserExistenceErrors` 禁用时，Amazon Cognito 会返回 `UserNotFound` 异常。

**用户名和密码身份验证**  
当 `PreventUserExistenceErrors` 启用时，身份验证流程 `ADMIN_USER_PASSWORD_AUTH`、`USER_PASSWORD_AUTH` 以及 `USER_AUTH` 的 `PASSWORD` 流程会返回 `NotAuthorizedException`，附带 `Incorrect username or password` 消息。当 `PreventUserExistenceErrors` 禁用时，这些流会返回 `UserNotFoundException`。

**基于安全远程密码（SRP）的身份验证**  
作为最佳实践，应仅在没有配置电子邮件地址、电话号码或首选用户名[别名属性](user-pool-settings-attributes.md#user-pool-settings-aliases)的用户池中，对 `USER_SRP_AUTH` 或 `USER_AUTH` 中的 `PASSWORD_SRP` 流程实现 `PreventUserExistenceErrors`。在 SRP 身份验证流程中，具有别名属性的用户可能不会受到用户存在性隐藏的影响。用户名密码身份验证流程（`ADMIN_USER_PASSWORD_AUTH`、`USER_PASSWORD_AUTH` 和 `USER_AUTH` `PASSWORD` 质询）能够完全隐藏来自别名属性的用户存在性信息。  
当有人使用应用程序客户端未知的用户名尝试 SRP 登录时，Amazon Cognito 会在第一步返回一个模拟响应，如 [RFC 5054](https://tools.ietf.org/html/rfc5054#section-2.5.1.3) 所述。Amazon Cognito 始终针对相同的用户名和用户池组合返回相同的盐值以及 [UUID](cognito-terms.md#terms-uuid) 格式的内部用户 ID。当您发送带有密码证明的 `RespondToAuthChallenge` API 时，Amazon Cognito 在用户名或密码不正确时返回一个通用 `NotAuthorizedException` 错误。有关实施 SRP 身份验证的更多信息，请参阅[使用永久密码和安全有效载荷登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-srp)。  
如果您使用基于验证的别名属性，并且不可改变的用户名格式不是 [UUID](cognito-terms.md#terms-uuid)，则可以模拟使用用户名和密码身份验证的通用响应。

**自定义身份验证质询 Lambda 触发器**  
当用户尝试使用 `CUSTOM_AUTH` 身份验证流程登录但其用户名未找到时，Amazon Cognito 会调用[自定义身份验证质询 Lambda 触发器](user-pool-lambda-challenge.md)。输入事件中包含一个名为 `UserNotFound` 的布尔值参数，对于任何不存在的用户，该参数值为 `true`。此参数会出现在用户池发送给创建、定义和验证身份验证质询 Lambda 函数的请求事件中，这些函数构成自定义身份验证架构。在 Lambda 函数逻辑中检查该标识后，您可以为不存在的用户模拟自定义身份验证质询。

**身份验证前 Lambda 触发器**  
当用户尝试登录但其用户名未找到时，Amazon Cognito 会调用[身份验证前触发器](user-pool-lambda-pre-authentication.md)。输入事件中包含一个 `UserNotFound` 参数，对于任何不存在的用户，该参数值为 `true`。

以下列表描述了 `PreventUserExistenceErrors` 对用户账户创建的影响。用户创建流程中的用户存在性披露细节

**SignUp**  
当已使用用户名时，`SignUp` 操作始终返回 `UsernameExistsException`。如果在您的应用程序中注册用户时，您不希望 Amazon Cognito 为电子邮件地址和电话号码返回 `UsernameExistsException` 错误，请使用基于验证的别名属性。有关别名的更多信息，请参阅[自定义登录属性](user-pool-settings-attributes.md#user-pool-settings-aliases)。  
有关 Amazon Cognito 如何阻止使用 `SignUp` API 请求来发现用户池中用户的示例，请参阅 [在注册时防止出现电子邮件地址和电话号码的 `UsernameExistsException` 错误](#cognito-user-pool-managing-errors-prevent-userexistence-errors)。

**导入的用户**  
如果 `PreventUserExistenceErrors` 已启用，则在对导入的用户进行身份验证期间，将返回通用 `NotAuthorizedException` 错误，指示用户名或密码不正确，而不是返回 `PasswordResetRequiredException`。请参阅[要求导入的用户重置密码](cognito-user-pools-using-import-tool.md#cognito-user-pools-using-import-tool-password-reset)了解更多信息。

**迁移用户 Lambda 触发器**  
当 Lambda 触发器在原始事件上下文中设置了空响应时，Amazon Cognito 将为不存在的用户返回模拟响应。有关更多信息，请参阅 [利用用户迁移 Lambda 触发器导入用户](cognito-user-pools-import-using-lambda.md)。

### 在注册时防止出现电子邮件地址和电话号码的 `UsernameExistsException` 错误
<a name="cognito-user-pool-managing-errors-prevent-userexistence-errors"></a>

以下示例演示了在用户池中配置别名属性时，如何在对 `SignUp` API 请求的响应中，防止重复的电子邮件地址和电话号码生成 `UsernameExistsException` 错误。您必须在创建用户池时使用电子邮件地址或电话号码作为别名属性。有关更多信息，请参阅[用户池属性](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-aliases)的*自定义登录属性* 部分。

1. Jie 注册了一个新的用户名，还提供了电子邮件地址 `jie@example.com`。Amazon Cognito 将向其电子邮件地址发送一个代码。

   ** AWS CLI 命令示例**

   ```
   aws cognito-idp sign-up --client-id 1234567890abcdef0 --username jie --password PASSWORD --user-attributes Name="email",Value="jie@example.com"
   ```

   **响应示例**

   ```
   {
       "UserConfirmed": false, 
       "UserSub": "<subId>", 
       "CodeDeliveryDetails": {
           "AttributeName": "email", 
           "Destination": "j****@e****", 
           "DeliveryMedium": "EMAIL"
       }
   }
   ```

1. Jie 提供了发送过来的代码，确认其拥有该电子邮件地址。这样就完成了用户注册。

   ** AWS CLI 命令示例**

   ```
   aws cognito-idp confirm-sign-up --client-id 1234567890abcdef0 --username=jie --confirmation-code xxxxxx
   ```

1. Shirley 注册了一个新的用户账户并提供了电子邮件地址 `jie@example.com`。Amazon Cognito 不会返回 `UsernameExistsException` 错误，而是向 Jie 的电子邮件地址发送确认码。

   ** AWS CLI 命令示例**

   ```
   aws cognito-idp sign-up --client-id 1234567890abcdef0 --username shirley --password PASSWORD --user-attributes Name="email",Value="jie@example.com"
   ```

   **响应示例**

   ```
   {
       "UserConfirmed": false, 
       "UserSub": "<new subId>", 
       "CodeDeliveryDetails": {
           "AttributeName": "email", 
           "Destination": "j****@e****", 
           "DeliveryMedium": "EMAIL"
       }
   }
   ```

1. 在另一种情况下，Shirley 拥有对 `jie@example.com` 的所有权。Shirley 收到了 Amazon Cognito 发送到 Jie 电子邮件地址的代码，并尝试确认该账户。

   ** AWS CLI 命令示例**

   ```
   aws cognito-idp confirm-sign-up --client-id 1234567890abcdef0 --username=shirley --confirmation-code xxxxxx
   ```

   **响应示例**

   ```
   An error occurred (AliasExistsException) when calling the ConfirmSignUp operation: An account with the email already exists.
   ```

尽管已将 `jie@example.com` 分配给现有用户，Amazon Cognito 不会对 Shirley 的 `aws cognito-idp sign-up` 请求返回错误。在 Amazon Cognito 返回错误响应之前，Shirley 必须证明对该电子邮件地址的所有权。在具有别名属性的用户池中，此行为会阻止使用公共 `SignUp` API 来检查是否存在具有给定电子邮件地址或电话号码的用户。

此行为与 Amazon Cognito 向使用现有用户名的 `SignUp` 请求返回的响应不同，如以下示例所示。尽管 Shirley 从此回复中得知已经存在具有用户名 `jie` 的用户，但他们并不知道与该用户关联的任何电子邮件地址或电话号码。

**示例 CLI 命令**

```
aws cognito-idp sign-up --client-id 1example23456789 --username jie --password PASSWORD
      --user-attributes Name="email",Value="shirley@example.com"
```

**响应示例**

```
An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists
```

## 密码重置操作
<a name="cognito-user-pool-managing-errors-password-reset"></a>

当您防止出现用户存在错误时，Amazon Cognito 会对用户密码重置操作返回以下响应。

**ForgotPassword**  
当找不到用户、用户已停用或没有经过验证的传送机制来恢复其密码时，Amazon Cognito 会为用户返回 `CodeDeliveryDetails` 以及模拟的传递媒介。模拟的传递媒介由用户池的输入用户名格式和验证设置决定。

**ConfirmForgotPassword**  
Amazon Cognito 为不存在或已禁用的用户返回 `CodeMismatchException` 错误。如果在使用 `ForgotPassword` 时不请求代码，Amazon Cognito 将返回 `ExpiredCodeException` 错误。

## 确认操作
<a name="cognito-user-pool-managing-errors-confirmation"></a>

当您防止出现用户存在错误时，Amazon Cognito 会对用户确认和验证操作返回以下响应。

**ResendConfirmationCode**  
Amazon Cognito 为已禁用或不存在的用户返回 `CodeDeliveryDetails`。Amazon Cognito 会向现有用户的电子邮件或电话发送确认码。

**ConfirmSignUp**  
 如果代码已过期，则将返回 `ExpiredCodeException`。当用户未被授权时，Amazon Cognito 返回 `NotAuthorizedException`。1如果代码与服务器期望的代码不匹配，则 Amazon Cognito 返回 `CodeMismatchException`。

# 用户池端点和托管登录参考
<a name="cognito-userpools-server-contract-reference"></a>

Amazon Cognito 有两种用户池身份验证模式：使用用户池 API 和使用 OAuth 2.0 授权服务器。如果您想在应用程序后端使用 AWS 软件开发工具包检索 OpenID Connect (OIDC) 令牌，请使用 API。当您要将用户池实施为 OIDC 提供者时，请使用授权服务器。授权服务器添加了[联合身份验证登录](cognito-user-pools-identity-federation.md)、[具有访问令牌范围的 API 和 M2M 授权](cognito-user-pools-define-resource-servers.md)以及[托管登录](cognito-user-pools-managed-login.md)等功能。您可以单独使用 API 模型和 OIDC 模型，也可以将它们一起使用，并可以在用户池级别或[应用程序客户端](user-pool-settings-client-apps.md)级别进行配置。本节提供了实施 OIDC 模型的参考。有关这两种身份验证模型的更多信息，请参阅[了解 API、OIDC 和托管登录页面身份验证](authentication-flows-public-server-side.md#user-pools-API-operations)。

当您向用户池分配域时，Amazon Cognito 会激活此处列出的公开网页。您的域用作所有应用程序客户端的中央接入点。它们包括托管登录，您的用户可以在其中注册、登录（[登录端点](login-endpoint.md)）和注销（[注销端点](logout-endpoint.md))。有关这些资源的标签的更多信息，请参阅 [用户池托管登录](cognito-user-pools-managed-login.md)。

这些页面还包括公共网络资源，允许您的用户池与第三方 SAML、OpenID Connect (OIDC OAuth ) 和 2.0 身份提供商 () 进行通信。IdPs要使用联合身份提供者登录用户，您的用户必须向交互式托管登录[登录端点](login-endpoint.md)或 OIDC [对端点授权](authorization-endpoint.md)发起请求。授权端点将您的用户重定向到托管登录页面或 IdP 登录页面。

您的应用程序还可以使用 [Amazon Cognito 用户池 API](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html) 登录*本地用户*。本地用户仅存在于您的用户池目录中，无需通过外部 IdP 进行联合身份验证。

除了托管登录外，Amazon Cognito 还集成了 SDKs 适用于安卓 JavaScript、iOS 等设备的管理登录。 SDKs 提供了使用亚马逊 Cognito API 服务终端节点执行用户池 API 操作的工具。有关服务端点的更多信息，请参阅 [Amazon Cognito 身份端点和限额](https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html)。

**警告**  
不要锁定 Amazon Cognito 域的终端实体或中间传输层安全 (TLS) 证书。 AWS 管理所有用户池终端节点和前缀域的所有证书。信任链中支持 Amazon Cognito 证书的证书颁发机构 (CAs) 会动态轮换和续订。当您将应用程序固定到中间证书或叶证书时，您的应用程序在 AWS 轮换证书时可能会失败，恕不另行通知。  
而应将应用程序固定到所有可用的 [Amazon 根证书](https://www.amazontrust.com/repository/)。有关更多信息，请参阅《AWS Certificate Manager 用户指南》**的[证书固定](https://docs.aws.amazon.com/acm/latest/userguide/acm-bestpractices.html#best-practices-pinning)中的最佳做法和建议。

**Topics**
+ [用户交互式登录和经典托管 UI 端点](managed-login-endpoints.md)
+ [身份提供者和依赖方端点](federation-endpoints.md)
+ [OAuth 2.0 补助金](federation-endpoints-oauth-grants.md)
+ [在授权代码授予中使用 PKCE](using-pkce-in-authorization-code.md)
+ [托管登录和联合身份验证错误响应](federation-endpoint-idp-responses.md)

# 用户交互式登录和经典托管 UI 端点
<a name="managed-login-endpoints"></a>

当您向用户池添加域时，Amazon Cognito 会激活本节中的托管登录端点。这些端点是一些网页，您的用户可以在这些网页中完成用户池的核心身份验证操作。它们包括用于密码管理、多重身份验证（MFA）和属性验证的页面。

构成托管登录的网页是一个前端 Web 应用程序，用于与客户进行交互式用户会话。您的应用程序必须在用户的浏览器中调用托管登录。Amazon Cognito 不支持以编程方式访问本章中的网页。可以在应用程序代码中直接查询 [身份提供者和依赖方端点](federation-endpoints.md) 中那些返回 JSON 响应的联合端点。[对端点授权](authorization-endpoint.md)重定向到托管登录或 IdP 登录页面，并且还必须在用户的浏览器中打开。

所有用户池端点都接受来自 IPv4 和 IPv6 源 IP 地址的流量。

本指南中的主题详细描述了常用的托管登录和经典托管 UI 端点。托管登录和托管 UI 之间的区别在于可见性，而非功能性。除 `/passkeys/add` 之外，所有路径均在两个版本的托管登录品牌之间共享。

Amazon Cognito 会在您为用户池分配域时提供以下网页。


**托管登录端点**  

| 端点 URL | 说明 | 如何访问此端点 | 
| --- | --- | --- | 
| https://Your user pool domain/登录 | 登录用户池本地用户和联合用户。 |  从端点重定向，如[对端点授权](authorization-endpoint.md)、`/logout` 和 `/confirmforgotPassword`。请参阅[登录端点](login-endpoint.md)。  | 
| https://Your user pool domain/注销 | 注销用户池用户。 |  直接链接。请参阅[注销端点](logout-endpoint.md)。  | 
| https:// Your user pool domain /confirmus | 确认已选择电子邮件链接来验证其用户账户的用户。 |  电子邮件中用户选择的链接。  | 
| https://Your user pool domain/sign | 注册一个新用户。当您的用户选择注册时，/login 页面会将他们定向到 /signup。 |  与 `/oauth2/authorize` 具有相同参数的直接链接。  | 
| https://Your user pool domain/确认 | 在用户池向已注册的用户发送确认码后，提示您的用户输入验证码。 |  仅从 `/signup` 重定向。  | 
| https:// Your user pool domain /忘记密码 | 提示您的用户输入其用户名并发送密码重置代码。在您的用户选择忘记密码？时，/login 页面会将他们定向到 /forgotPassword。 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/managed-login-endpoints.html)  | 
| https://Your user pool domain/确认忘记密码 | 提示您的用户输入其密码重置代码和新的密码。在您的用户选择重置密码时，/forgotPassword 页面会将他们定向到 /confirmforgotPassword。 | 仅从 /forgotPassword 重定向。 | 
| https:/ Your user pool domain /resendcode | 向已在用户池中注册的用户发送新的确认码。 |  仅从 `/confirm` 中的**发送新代码**链接重定向。  | 
| https: ///passkeys Your user pool domain /add | 注册新的[通行密钥](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passkey)。仅在托管登录中可用。 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/managed-login-endpoints.html)  | 

**Topics**
+ [托管登录的登录端点：`/login`](login-endpoint.md)
+ [托管登录的注销端点：`/logout`](logout-endpoint.md)

# 托管登录的登录端点：`/login`
<a name="login-endpoint"></a>

登录端点是一个身份验证服务器，也是来自[对端点授权](authorization-endpoint.md)的重定向目的地。当您不指定身份提供者时，它是托管登录的入口点。当您生成到登录端点的重定向时，它加载登录页面，并向用户显示为客户端配置的身份验证选项。

**注意**  
登录端点是托管登录的一个组成部分。在您的应用程序中，调用重定向到登录端点的联合身份验证和托管登录页面。用户直接访问登录端点并不是最佳实践。

## GET /login
<a name="get-login"></a>

`/login` 端点仅支持对用户的初始请求执行 `HTTPS GET`。您的应用程序会在 Chrome 或 Firefox 等浏览器中调用该页面。当您从 [对端点授权](authorization-endpoint.md) 重定向到 `/login` 时，它会传递您在初始请求中提供的所有参数。登录端点支持授权端点的所有请求参数。您也可以直接访问登录端点。作为最佳实践，应在 `/oauth2/authorize` 上发起所有用户会话。

**示例 - 提示用户登录**

此示例显示登录屏幕。

```
GET https://mydomain.auth.us-east-1.amazoncognito.com/login?
                response_type=code&
                client_id=ad398u21ijw3s9w3939&
                redirect_uri=https://YOUR_APP/redirect_uri&
                state=STATE&
                scope=openid+profile+aws.cognito.signin.user.admin
```

**示例：响应**  
身份验证服务器重定向到您的应用程序并提供授权代码和状态。服务器必须在查询字符串参数中返回代码和状态，而不是在片段中。

```
HTTP/1.1 302 Found
                    Location: https://YOUR_APP/redirect_uri?code=AUTHORIZATION_CODE&state=STATE
```

## 用户发起的登录请求
<a name="post-login"></a>

在用户加载 `/login` 端点后，他们可以输入用户名和密码并选择**登录**。这样做时，将生成一个与 `GET` 请求具有相同标头请求参数的 `HTTPS POST` 请求，以及包含用户名、密码和设备指纹的请求正文。

# 托管登录的注销端点：`/logout`
<a name="logout-endpoint"></a>

`/logout` 端点是重定向端点。该端点使用户注销并重定向到您的应用程序客户端的授权注销 URL，或重定向到 `/login` 端点。`/logout` 端点的 GET 请求中的可用参数是针对 Amazon Cognito 托管登录使用案例量身定制的。

注销端点是一个前端 Web 应用程序，用于与客户进行交互式用户会话。您的应用程序必须在用户的浏览器中调用此端点和其他托管登录端点。

要将用户重定向到托管登录以再次登录，请在请求中添加 `redirect_uri` 参数。带 `redirect_uri` 参数的 `logout` 请求还必须包含对[登录端点](login-endpoint.md)的后续请求的参数，例如 `client_id`、`response_type` 和 `scope`。

要将用户重定向到您选择的页面，请在您的应用程序客户端**中 URLs添加允许**注销。在用户的对 `logout` 端点的请求中，添加 `logout_uri` 和 `client_id` 参数。如果的值`logout_uri`是您的应用程序客户端**允许的注销 URLs**之一，则 Amazon Cognito 会将用户重定向到该网址。

使用 SAML 2.0 的单点注销 (SLO)，Amazon IdPs Cognito 首先将您的用户重定向到您在 IdP 配置中定义的 SLO 终端节点。在您的 IdP 将您的用户重定向回到 `saml2/logout` 之后，Amazon Cognito 会根据您的请求，再向 `redirect_uri` 或 `logout_uri` 发送一次重定向响应。有关更多信息，请参阅 [通过单点注销来注销 SAML 用户](cognito-user-pools-saml-idp-sign-out.md)。

注销端点不会让用户退出 OIDC 或社交身份提供商 ()。IdPs要让用户从与外部 IdP 进行的会话中注销，请将他们引导到该提供者的注销页面。

## GET /logout
<a name="get-logout"></a>

`/logout` 端点只支持 `HTTPS GET`。用户池客户端通常通过浏览器发出此请求。浏览器在 Android 中通常是自定义 Chrome 标签页，在 iOS 中是 Safari 视图控件。

### 请求参数
<a name="get-logout-request-parameters"></a>

*client\$1id*  
您的应用程序的应用程序客户端 ID。要获取应用程序客户端 ID，您必须在用户池中注册该应用程序。有关更多信息，请参阅 [特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。  
必需。

*logout\$1uri*  
使用 *logout\$1uri* 参数将用户重新导向到自定义注销页面。将其值设置为应用程序客户端**注销 URL**，您要在用户退出后将其重新导向到此 URL。仅将 *logout\$1uri* 与 *client\$1id* 参数一起使用。有关更多信息，请参阅 [特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。  
您也可以使用 *logout\$1uri* 参数将用户重定向到另一个应用程序客户端的登录页面。将其他应用程序客户端的登录页面设置为您的应用程序客户端中的**允许的回调 URL**。在对 `/logout` 端点的请求中，将 *logout\$1uri* 参数的值设置为 URL 编码的登录页面。  
Amazon Cognito 要求在您对 `/logout` 端点的请求中使用 *logout\$1uri* 或 *redirect\$1uri* 参数。*logout\$1uri* 参数会将您的用户重定向到另一个网站。如果您对 `/logout` 端点的请求中同时包含 *logout\$1uri* 和 *redirect\$1uri* 参数，Amazon Cognito 将以独占方式使用 *logout\$1uri* 参数，而覆盖 *redirect\$1uri* 参数。

*`nonce`*  
（可选）您可以添加到请求中的随机值。您提供的 nonce 值包含在 Amazon Cognito 发出的 ID 令牌中。为了防范重播攻击，您的应用程序可以检查 ID 令牌中的 `nonce` 声明并将其与您生成的声明进行比较。有关 `nonce` 声明的更多信息，请参阅《OpenID Connect 标准》**中的 [ID token validation](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation)（ID 令牌验证）。

**redirect\$1uri**  
使用 *redirect\$1uri* 将用户重新导向到登录页以进行身份验证。将其值设置为应用程序客户端**允许的回调 URL**，您要在用户再次登录后将其重新导向到此 URL。添加您要传递给 `/login` 端点的 *client\$1id*、*scope*、*state* 和 *response\$1type* 参数。  
Amazon Cognito 要求在您对 `/logout` 端点的请求中使用 *logout\$1uri* 或 *redirect\$1uri* 参数。要将用户重定向到 `/login` 端点以重新验证身份并将令牌传递给您的应用程序，请添加 *redirect\$1uri* 参数。如果您向 `/logout` 端点发出的请求中同时包含 *logout\$1uri* 和 *redirect\$1uri* 参数，则 Amazon Cognito 会覆盖 *redirect\$1uri* 参数，并以独占方式处理 *logout\$1uri* 参数。

*response\$1type*  
您希望在用户登录后从 Amazon Cognito 收到的 OAuth 2.0 响应。 `code`和`token`是 r *esponse\$1t* ype 参数的有效值。  
在您使用 *redirect\$1uri* 参数时是必需的。

*状态*  
当应用程序向请求添加 *state* 参数时，如果 `/oauth2/logout` 端点重新导向您的用户，则 Amazon Cognito 将此参数的值返回给您的应用程序。  
将此值添加到您的请求中以防止 [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) 攻击。  
不能将 `state` 参数的值设置为 URL 编码的 JSON 字符串。要在 `state` 参数中传递与此格式匹配的字符串，请将该字符串编码为 base64，然后在应用程序中对其进行解码。  
如果您使用 *redirect\$1uri* 参数，强烈推荐使用此参数。

*范围*  
你想在使用 redi *re* ct\$1uri 参数注销后向亚马逊 Cognito 请求的 OAuth 2.0 范围。Amazon Cognito 使用您对 `/logout` 端点的请求中的 *scope* 参数将您的用户重定向到 `/login` 端点。  
在您使用 *redirect\$1uri* 参数时是可选的。如果不包括 *scope* 参数，Amazon Cognito 会使用 *scope* 参数将您的用户重定向到 `/login` 端点。当 Amazon Cognito 重定向用户并自动填充 `scope` 时，该参数包括应用程序客户端的所有授权范围。

### 示例请求
<a name="get-logout-request-sample"></a>

**示例：注销并将用户重新导向到客户端**

当请求包含 `logout_uri` 和 `client_id` 时，Amazon Cognito 会将用户会话重定向到 `logout_uri` 值中的 URL，忽略所有其他请求参数。这个 URL 必须是应用程序客户端的授权注销 URL。

以下是注销并重定向到 `https://www.example.com/welcome` 的请求示例。

```
GET https://mydomain.auth.us-east-1.amazoncognito.com/logout?
  client_id=1example23456789&
  logout_uri=https%3A%2F%2Fwww.example.com%2Fwelcome
```

**示例：注销并提示用户以其他用户身份登录**

如果请求忽略 `logout_uri`，但以其他方式提供了参数，可以构成对授权端点发出的、格式正确的请求，Amazon Cognito 会将用户重定向到托管登录的登录。注销端点会将原始请求中的参数附加到重定向目的地。

您添加到注销请求中的其他参数必须位于[请求参数](#get-logout-request-parameters)处的列表中。例如，注销端点不支持使用 `identity_provider` 或 `idp_identifier` 参数的自动 IdP 重定向。向注销终端节点发出的请求`redirect_uri`中的参数不是注销 URL，而是您要传递到授权端点的 post-sign-in URL。

以下是将用户注销，重定向到登录页面，然后在登录后向 `https://www.example.com` 提供授权代码的请求示例。

```
GET https://mydomain.auth.us-east-1.amazoncognito.com/logout?
  response_type=code&
  client_id=1example23456789&
  redirect_uri=https%3A%2F%2Fwww.example.com&
  state=example-state-value&
  nonce=example-nonce-value&
  scope=openid+profile+aws.cognito.signin.user.admin
```

# 身份提供者和依赖方端点
<a name="federation-endpoints"></a>

*联合端点*是用户池端点，用于用户池使用的身份验证标准之一。它们包括 SAML ACS URLs、OIDC 发现端点以及作为身份提供者和信赖方的用户池角色的服务端点。联合端点启动身份验证流程，接收来自客户端的身份验证证明 IdPs，并向客户端发放令牌。他们与 IdPs应用程序和管理员交互，但不与用户交互。

本页之后的整页主题包含有关 OAuth 2.0 和 OIDC 提供商端点的详细信息，当您向用户池中添加域名时，这些终端节点将变为可用。下图是所有联合身份验证端点的列表。

[用户池域](cognito-user-pools-assign-domain.md)的示例有：

1. 前缀域：`mydomain.auth.us-east-1.amazoncognito.com`

1. 自定义域：`auth.example.com`


**用户池联合身份验证端点**  

| 端点 URL | 说明 | 如何访问此端点 | 
| --- | --- | --- | 
| https://Your user pool domain/oauth2/授权 | 将用户重定向到托管登录或使用其 IdP 登录。 | 在客户浏览器中调用以开始用户身份验证。请参阅[对端点授权](authorization-endpoint.md)。 | 
| https:// Your user pool domain /oauth2/tok | 根据授权码或客户端凭证请求返回令牌。 | 应用程序请求检索令牌。请参阅[令牌端点](token-endpoint.md)。 | 
| https://Your user pool domain/oauth2/userInfo | 根据 OAuth 2.0 范围和访问令牌中的用户身份返回用户属性。 | 应用程序请求检索用户配置文件。请参阅[userInfo 端点](userinfo-endpoint.md)。 | 
| https://Your user pool domain/oauth2/revoke | 撤销刷新令牌和关联的访问令牌。 | 应用程序请求撤销令牌。请参阅[撤销端点](revocation-endpoint.md)。 | 
| https://cognito-idp。 Region.amazonaws.com/ /.wellknown/openid 配置 your user pool ID | 您的用户池 OIDC 架构的目录。 [1](#cognito-federation-oidc-discovery-note) | 应用程序请求查找用户池发布者元数据。 | 
| https://cognito-idp。 Region.amazonaws.com/ /.well your user pool ID-known/jwks.json | 可用于验证亚马逊 Cognito 令牌的公钥。 [2](#cognito-federation-oidc-jwks-note) | 由应用程序请求进行验证 JWTs。 | 
| https:/Your user pool domain/oauth2/idpresponse | 社交身份提供者必须使用授权码将用户重新导向到此端点。Amazon Cognito 在验证您的联合用户时将代码兑换为令牌。 | 已从 OIDC IdP 登录重定向为 IdP 客户端回调 URL。 | 
| https://Your user pool domain/saml2/idpresponse | 与 SAML 2.0 身份提供者集成所需的断言使用者响应（ACS）URL。 | 已从 SAML 2.0 IdP 重定向为 ACS URL，或 IdP 发起的登录的起点[3](#cognito-federation-idp-init-note)。 | 
| https://Your user pool domain/saml2/logout | 用于与 SAML 2.0 身份提供者集成的[单点注销](cognito-user-pools-saml-idp-sign-out.md#cognito-user-pools-saml-idp-sign-out.title)（SLO）URL。 | 已从 SAML 2.0 IdP 重定向为单点注销（SLO）URL。仅接受 POST 绑定。 | 

1 本`openid-configuration`文档可能随时更新，其中包含其他信息，以保持端点符合 OIDC 和 OAuth2 规范。

2 可能会随时使用新的公共令牌签名密钥更新 `jwks.json` JSON 文件。

3 有关 IDP 发起的 SAML 登录的更多信息，请参阅。[实施 IdP 发起的 SAML 登录](cognito-user-pools-SAML-session-initiation.md#cognito-user-pools-SAML-session-initiation-idp-initiation)

[有关 OpenID Connect 和 OAuth 标准的更多信息，请参阅 OpenID Con [nect](http://openid.net/specs/openid-connect-core-1_0.html) 1.0 和 2.0。OAuth](https://tools.ietf.org/html/rfc6749)

**Topics**
+ [重定向和授权端点](authorization-endpoint.md)
+ [令牌发布者端点](token-endpoint.md)
+ [用户属性端点](userinfo-endpoint.md)
+ [令牌撤销端点](revocation-endpoint.md)
+ [IdP SAML 断言端点](saml2-idpresponse-endpoint.md)

# 重定向和授权端点
<a name="authorization-endpoint"></a>

`/oauth2/authorize` 端点是支持两个重定向目标的重定向端点。如果您在 URL 中包括 `identity_provider` 或 `idp_identifier` 参数，则它会静默地将用户重定向到该身份提供者（IdP）的登录页面。否则，它会使用您在请求中包括的相同 URL 参数重定向到 [登录端点](login-endpoint.md)。

授权端点将会重定向到托管登录或 IdP 登录页面。此端点上的用户会话的目的地是您的用户必须直接在其浏览器中与之交互的网页。

要使用 authorize 端点，请在 `/oauth2/authorize` 上使用为您的用户池提供有关以下用户池详细信息的信息的参数调用用户的浏览器。
+ 您希望登录到的应用程序客户端。
+ 您希望最终到达的回调 URL。
+ 您要在用户的访问令牌中请求的 OAuth 2.0 范围。
+ （可选）您希望用于登录的第三方 IdP。

您还可以提供 Amazon Cognito 用来验证传入声明的 `state` 和 `nonce` 参数。

## GET `/oauth2/authorize`
<a name="get-authorize"></a>

`/oauth2/authorize` 端点只支持 `HTTPS GET`。您的应用程序通常在用户的浏览器中发起此请求。您只能通过 HTTPS 向 `/oauth2/authorize` 端点发出请求。

您可以在 OpenID Connect（OIDC）标准的[授权端点](http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthorizationEndpoint)中详细了解授权端点的定义。

### 请求参数
<a name="get-authorize-request-parameters"></a>

**`response_type`**  
必需。  
响应类型。必须为 `code` 或 `token`。  
`response_type` 为 `code` 的成功请求返回授权代码授予。授权代码授予是 Amazon Cognito 附加到重定向 URL 的 `code` 参数。您的应用程序可以将包含 [令牌端点](token-endpoint.md)的代码交换为访问权限、ID 和刷新令牌。作为安全最佳实践，以及要为您的用户接收刷新令牌，请在您的应用程序中使用授权代码授予。  
`response_type` 为 `token` 的成功请求返回隐式授予。隐式授予是 Amazon Cognito 附加到您的重定向 URL 的 ID 和访问令牌。隐式授予的安全性较差，因为它会向用户公开令牌和潜在的识别信息。您可以在应用程序客户端的配置中停用对隐式授予的支持。

**`client_id`**  
必需。  
应用程序客户端 ID。  
`client_id` 的值必须是您在其中发出请求的用户池中应用程序客户端的 ID。您的应用程序客户端必须支持由 Amazon Cognito 本地用户或至少一个第三方 IdP 登录。

**`redirect_uri`**  
必需。  
在 Amazon Cognito 授权用户之后，身份验证服务器将浏览器重定向到的 URL。  
重定向统一资源标识符（URI）必须具有以下属性：  
+ 必须是绝对 URI。
+ 您必须已经将 URI 预注册到客户端。
+ 不能包含片段组件。
请参阅 [OAuth 2.0-重定向端点](https://tools.ietf.org/html/rfc6749#section-3.1.2)。  
Amazon Cognito 要求您的重新导向 URI 使用 HTTPS，但 `http://localhost` 除外，您可以将其设置为回调 URL 以进行测试。  
Amazon Cognito 还支持应用程序回调， URLs 例如。`myapp://example`

**`state`**  
可选，建议。  
当应用程序向请求添加 *state* 参数时，如果 `/oauth2/authorize` 端点重新导向您的用户，则 Amazon Cognito 将此参数的值返回给您的应用程序。  
将此值添加到您的请求中以防止 [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) 攻击。  
不能将 `state` 参数的值设置为 URL 编码的 JSON 字符串。要在 `state` 参数中传递与此格式匹配的字符串，请将该字符串编码为 base64，然后在应用程序中对其进行解码。

**`identity_provider`**  
可选。  
添加此参数可绕过托管登录并将您的用户重定向到提供商登录页面。*identity\$1provider* 参数的值是出现在您的用户池中的身份提供者（IdP）的名称。  
+ 对于社交提供者，您可以使用 *identity\$1provider* 值 `Facebook`、`Google`、`LoginWithAmazon` 和 `SignInWithApple`。
+ 对于 Amazon Cognito 用户池，使用值 `COGNITO`。
+ 对于 SAML 2.0 和 OpenID Connect (OIDC) 身份提供商 (IdPs)，请使用您在用户池中分配给 IdP 的名称。

**`idp_identifier`**  
可选。  
添加此参数以重定向到具有 *identity\$1provider* 名称的替代名称的提供程序。您可以 IdPs 从 Amazon Cognito 控制台的**社交和外部提供商菜单中输入 SAML 2.0 和** OIDC 的标识符。

**`scope`**  
可选。  
可以是任何系统预留范围或与客户端关联的自定义范围的组合。范围必须以空格分隔。系统预留范围为 `openid`、`email`、`phone`、`profile` 和 `aws.cognito.signin.user.admin`。使用的任意范围必须与客户端关联，否则将在运行时忽略。  
如果客户端不请求任何范围，则身份验证服务器使用与客户端关联的所有范围。  
如果请求 `openid` 范围，则只返回 ID 令牌。如果请求 `aws.cognito.signin.user.admin` 范围，则访问令牌只能用于 Amazon Cognito 用户池。如果同时请求了 `phone` 范围，则只能请求 `email`、`profile` 和 `openid` 范围。这些范围控制进入 ID 令牌中的声明。

**`code_challenge_method`**  
可选。  
用于生成质询的哈希协议。[PKCE RFC](https://tools.ietf.org/html/rfc7636) 定义两个方法：S256 和 plain；但是，Amazon Cognito 身份验证服务器仅支持 S256。

**`code_challenge`**  
可选。  
从 `code_verifier` 生成的代码交换的证明密钥（PKCE）质询。有关更多信息，请参阅 [在授权代码授予中使用 PKCE](using-pkce-in-authorization-code.md)。  
仅当您指定 `code_challenge_method` 参数时是必需的。

**`nonce`**  
可选。  
您可以添加到请求中的随机值。您提供的 nonce 值包含在 Amazon Cognito 发出的 ID 令牌中。为了防范重播攻击，您的应用程序可以检查 ID 令牌中的 `nonce` 声明并将其与您生成的声明进行比较。有关 `nonce` 声明的更多信息，请参阅《OpenID Connect 标准》**中的 [ID token validation](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation)（ID 令牌验证）。

**`lang`**  
可选。  
您想要显示用户交互式页面的语言。托管登录页面可以本地化，但托管 UI（经典）页面不能。有关更多信息，请参阅 [托管登录本地化](cognito-user-pools-managed-login.md#managed-login-localization)。

**`login_hint`**  
可选。  
要传递给授权服务器的用户名提示。您可以从用户那里收集用户名、电子邮件地址或电话号码，并允许目的地提供者预先填入用户的登录名。当您向 `oauth2/authorize` 端点提交 `login_hint` 参数，而没有提交 `idp_identifier` 或 `identity_provider` 参数时，托管登录会使用您的提示值填写用户名字段。您也可以将此参数传递给 [登录端点](login-endpoint.md) 并自动填入用户名值。  
当您的授权请求调用到 OIDC 的重定向时，Amazon IdPs Cognito 会向该第三方授权机构在请求中添加一个`login_hint`参数。你无法将登录提示转发给 SAML、Apple、Login With Amazon、Google 或 Facebook（Meta） IdPs。

**`prompt`**  
可选。  
一个 OIDC 参数，用于控制现有会话的身份验证行为。仅在托管登录品牌版本中可用，不适用于经典托管 UI。有关 OIDC 规范的更多信息，请参阅[身份验证请求](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest)。值 `none` 和 `login` 会影响用户池的身份验证行为。  
 IdPs 当用户选择向第三方提供商进行身份验证时，Amazon Cognito 会`none`将`prompt`除您的值之外的所有值转发给您。当用户访问的 URL 包含 `identity_provider` 或 `idp_identifier` 参数，或者当授权服务器将他们重定向到[登录端点](login-endpoint.md)，然后他们从可用按钮中选择 IdP 时，也会出现这种情况。  
**Prompt 参数值**    
`prompt=none`  
Amazon Cognito 会以静默方式继续对拥有经过身份验证的有效会话的用户进行身份验证。通过此提示，用户可以在用户池中的不同应用程序客户端之间进行静默身份验证。如果用户尚未通过身份验证，则授权服务器返回 `login_required` 错误。  
`prompt=login`  
Amazon Cognito 要求用户重新进行身份验证，即使他们已有会话。请在您想再次验证用户的身份时发送此值。拥有现有会话的经过身份验证的用户可以在不使该会话失效的情况下返回登录。当拥有现有会话的用户再次登录时，Amazon Cognito 会为他们分配一个新的会话 Cookie。也可以将此参数转发给您的 IdPs。 IdPs接受此参数的用户还会向用户请求新的身份验证尝试。  
`prompt=select_account`  
此值对本地登录没有影响，必须在重定向到 IdPs的请求中提交。当包含在您的授权请求中时，此参数会将 `prompt=select_account` 添加到 IdP 重定向目的地的 URL 路径。当 IdPs 支持此参数时，他们会要求用户选择他们想要登录的账户。  
`prompt=consent`  
此值对本地登录没有影响，必须在重定向到 IdPs的请求中提交。当包含在您的授权请求中时，此参数会将 `prompt=consent` 添加到 IdP 重定向目的地的 URL 路径。当 IdPs支持此参数时，他们会先征得用户同意，然后再重定向回您的用户池。
当您在请求中忽略 `prompt` 参数时，托管登录将遵循默认行为：除非用户的浏览器具有有效的托管登录会话 Cookie，否则用户必须登录。您可以使用空格字符分隔符合并 `prompt` 的多个值，例如 `prompt=login consent`。

**`resource`**  
可选。  
您要在 `aud` 声明中绑定到访问令牌的资源的标识符。当您包含此参数时，Amazon Cognito 会验证该值是否为 URL，并将生成的访问令牌的受众设置到请求的资源。您可以使用 URL 格式的标识符或您选择的 URL 请求用户池[资源服务器](cognito-user-pools-define-resource-servers.md)。此参数的值必须以 `https://`、`http://localhost` 或自定义 URL 模式（例如 `myapp://`）开头。  
资源绑定在 [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html) 中定义。有关资源服务器和资源绑定的更多信息，请参阅[资源绑定](cognito-user-pools-define-resource-servers.md#cognito-user-pools-resource-binding)。

## 示例：授权代码授予
<a name="sample-authorization-code-grant"></a>

这是授权代码授予的示例请求。

以下请求会启动会话，以便检索您的用户在 `redirect_uri` 目的地传递给应用程序的授权代码。该会话请求的范围包括用户属性和对 Amazon Cognito 自助服务 API 操作的访问权限。

```
GET https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?
response_type=code&
client_id=1example23456789&
redirect_uri=https://www.example.com&
state=abcdefg&
scope=openid+profile+aws.cognito.signin.user.admin
```

Amazon Cognito 身份验证服务器使用授权代码和状态重新导向回您的应用程序。授权代码的有效期为五分钟。

```
HTTP/1.1 302 Found
Location: https://www.example.com?code=a1b2c3d4-5678-90ab-cdef-EXAMPLE11111&state=abcdefg
```

## 示例：使用 PKCE 进行授权代码授予
<a name="sample-authorization-code-grant-with-pkce"></a>

此示例流程使用 [PKCE](using-pkce-in-authorization-code.md#using-pkce-in-authorization-code.title) 执行授权代码授予。

此请求会添加 `code_challenge` 参数。要完成令牌代码的交换，必须在向 `/oauth2/token` 端点发出的请求中包括 `code_verifier` 参数。

```
GET https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?
response_type=code&
client_id=1example23456789&
redirect_uri=https://www.example.com&
state=abcdefg&
scope=aws.cognito.signin.user.admin&
code_challenge_method=S256&
code_challenge=a1b2c3d4...
```

授权服务器将授权代码和状态重定向回您的应用程序。您的应用程序处理授权码并将其交换为令牌。

```
HTTP/1.1 302 Found
Location: https://www.example.com?code=a1b2c3d4-5678-90ab-cdef-EXAMPLE11111&state=abcdefg
```

## 示例：使用 `prompt=login` 要求重新进行身份验证
<a name="sample-authorization-code-with-prompt-login"></a>

以下请求会添加一个 `prompt=login` 参数，要求用户重新进行身份验证，即使他们已有会话。

```
GET https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?
response_type=code&
client_id=1example23456789&
redirect_uri=https://www.example.com&
state=abcdefg&
scope=openid+profile+aws.cognito.signin.user.admin&
prompt=login
```

授权服务器重定向到[登录端点](login-endpoint.md)，要求重新进行身份验证。

```
HTTP/1.1 302 Found Location: https://mydomain.auth.us-east-1.amazoncognito.com/login?response_type=code&client_id=1example23456789&redirect_uri=https://www.example.com&state=abcdefg&scope=openid+profile+aws.cognito.signin.user.admin&prompt=login
```

## 示例：使用 `prompt=none` 进行静默身份验证
<a name="sample-authorization-code-with-prompt-none"></a>

以下请求会添加一个 `prompt=none` 参数，用于静默检查用户是否有有效会话。

```
GET https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?
response_type=code&
client_id=1example23456789&
redirect_uri=https://www.example.com&
state=abcdefg&
scope=openid+profile+aws.cognito.signin.user.admin&
prompt=none
```

当不存在有效会话时，授权服务器向重定向 URI 返回错误。

```
HTTP/1.1 302 Found Location: https://www.example.com?error=login_required&state=abcdefg
```

当存在有效会话时，授权服务器返回授权码。

```
HTTP/1.1 302 Found Location: https://www.example.com?code=AUTHORIZATION_CODE&state=abcdefg
```

## 示例：通过资源绑定进行授权码授予
<a name="sample-authorization-code-with-resource-binding"></a>

以下请求会添加一个 `resource` 参数，用于将访问令牌绑定到特定的资源服务器。生成的访问令牌将为目标 API 创建条件，以验证其是否是经过身份验证的用户请求的目标受众。

```
GET https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?
response_type=code&
client_id=1example23456789&
redirect_uri=https://www.example.com&
state=abcdefg&
scope=solar-system-data-api.example.com/asteroids.add&
resource=https://solar-system-data-api.example.com
```

授权服务器返回授权码，从而生成 `aud` 声明为 `https://solar-system-data-api.example.com` 的访问令牌。

```
HTTP/1.1 302 Found Location: https://www.example.com?code=AUTHORIZATION_CODE&state=abcdefg
```

## 示例：不带 `openid` 范围的令牌（隐式）授权
<a name="sample-token-grant-without-openid-scope"></a>

此示例流程生成隐式授权，并 JWTs 直接返回到用户的会话。

请求的是从您的授权服务器进行隐式授权。这在访问令牌中请求授权用户配置文件进行自助操作的范围。

```
GET https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?
response_type=token&
client_id=1example23456789&
redirect_uri=https://www.example.com&
state=abcdefg&
scope=aws.cognito.signin.user.admin
```

授权服务器仅使用访问令牌重定向回您的应用程序。由于未请求 `openid` 范围，Amazon Cognito 不会返回 ID 令牌。此外，Amazon Cognito 不会在此流程中返回刷新令牌。

```
HTTP/1.1 302 Found
Location: https://example.com/callback#access_token=eyJra456defEXAMPLE&token_type=bearer&expires_in=3600&state=STATE
```

## 示例：带 `openid` 范围的令牌（隐式）授权
<a name="sample-token-grant-with-openid-scope"></a>

此示例流程生成隐式授权并将令牌返回到用户的浏览器。

请求的是从您的授权服务器进行隐式授权。这在访问令牌中请求授权访问用户属性和自助操作的范围。

```
GET
https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize? 
response_type=token& 
client_id=1example23456789& 
redirect_uri=https://www.example.com& 
state=abcdefg&
scope=aws.cognito.signin.user.admin+openid+profile
```

授权服务器重定向回您的应用程序，带有访问令牌和 ID 令牌（因为包括了 `openid` 范围）：

```
HTTP/1.1 302 Found
Location: https://www.example.com#id_token=eyJra67890EXAMPLE&access_token=eyJra12345EXAMPLE&token_type=bearer&expires_in=3600&state=abcdefg
```

## 负向响应的示例
<a name="get-authorize-negative"></a>

Amazon Cognito 可能会拒绝您的请求。失败的请求附带 HTTP 错误代码和相关描述，您可以使用这些信息来更正请求参数。以下是负向响应的示例。
+ 如果 `client_id` 和 `redirect_uri` 有效，但请求参数格式不正确，身份验证服务器会将该错误重定向到客户端的 `redirect_uri` 并在 URL 参数中附加错误消息。以下是错误格式的示例。
  + 该请求不包括 `response_type` 参数。
  + 授权请求提供了 `code_challenge` 参数，但没有提供 `code_challenge_method` 参数。
  + `code_challenge_method` 参数的值不是 `S256`。

  以下是使用了错误格式的示例请求的响应。

  ```
  HTTP 1.1 302 Found Location: https://client_redirect_uri?error=invalid_request
  ```
+ 如果客户端在 `response_type` 中请求 `code` 或 `token`，但没有这些请求的权限，则 Amazon Cognito 授权服务器将 `unauthorized_client` 返回到客户端的 `redirect_uri`，如下所示：

  ```
  HTTP 1.1 302 Found Location: https://client_redirect_uri?error=unauthorized_client
  ```
+  如果客户端请求范围未知、格式错误或者无效，则 Amazon Cognito 授权服务器会将 `invalid_scope` 返回到客户端的 `redirect_uri`，如下所示：

  ```
  HTTP 1.1 302 Found Location: https://client_redirect_uri?error=invalid_scope
  ```
+ 如果服务器中有意外的错误，则授权服务器会将 `server_error` 返回到客户端的 `redirect_uri`。由于 HTTP 500 错误不会发送到客户端，所以在用户的浏览器中不会显示该错误。授权服务器返回以下错误。

  ```
  HTTP 1.1 302 Found Location: https://client_redirect_uri?error=server_error
  ```
+ 当 Amazon Cognito 通过联合身份验证向第三方 IdPs进行身份验证时，Amazon Cognito 可能会遇到连接问题，例如：
  + 如果从 IdP 处请求令牌时连接超时，身份验证服务器会将该错误重定向到客户端的 `redirect_uri`，如下所示：

    ```
    HTTP 1.1 302 Found Location: https://client_redirect_uri?error=invalid_request&error_description=Timeout+occurred+in+calling+IdP+token+endpoint
    ```
  + 如果在调用 `jwks_uri` 端点进行 ID 令牌验证时连接超时，身份验证服务器会重定向到客户端的 `redirect_uri`，并出现如下所示的错误：

    ```
    HTTP 1.1 302 Found Location: https://client_redirect_uri?error=invalid_request&error_description=error_description=Timeout+in+calling+jwks+uri
    ```
+ 通过联合第三方进行身份验证时 IdPs，提供商可能会返回错误响应。这可能是由于配置错误或其他原因而造成，例如以下原因：
  + 如果从其他提供商处收到错误响应，身份验证服务器会将该错误重定向到客户端的 `redirect_uri`，如下所示：

    ```
    HTTP 1.1 302 Found Location: https://client_redirect_uri?error=invalid_request&error_description=[IdP name]+Error+-+[status code]+error getting token
    ```
  + 如果从 Google 收到错误响应，身份验证服务器会将该错误重定向到客户端的 `redirect_uri`，如下所示：

    ```
    HTTP 1.1 302 Found Location: https://client_redirect_uri?error=invalid_request&error_description=Google+Error+-+[status code]+[Google-provided error code]
    ```
+ 如果 Amazon Cognito 在连接到外部 IdP 时遇到通信异常，则身份验证服务器会重定向到客户端的 `redirect_uri`，并显示以下错误消息：
  + 

    ```
    HTTP 1.1 302 Found Location: https://client_redirect_uri?error=invalid_request&error_description=Connection+reset
    ```
  + 

    ```
    HTTP 1.1 302 Found Location: https://client_redirect_uri?error=invalid_request&error_description=Read+timed+out
    ```

# 令牌发布者端点
<a name="token-endpoint"></a>

的 OAuth 2.0 [令牌端点](https://www.rfc-editor.org/rfc/rfc6749#section-3.2)向想要完成授权码和客户端凭证授予流程的应用程序`/oauth2/token`发放 JSON Web 令牌 (JWTs)。这些令牌是使用用户池进行身份验证的最终结果。这些令牌包含有关用户（ID 令牌）、用户的访问级别（访问令牌）以及用户保留其已登录会话的权利（刷新令牌）的信息。OpenID Connect（OIDC）依赖方库处理向此端点发出的请求以及来自此端点的响应有效载荷。令牌提供可验证的身份验证证明、配置文件信息以及用于访问后端系统的机制。

您的用户池 OAuth 2.0 授权服务器从令牌端点向以下类型的会话发放 JSON Web 令牌 (JWTs)：

1. 已完成授权码授权请求的用户。成功兑换代码会返回 ID、访问令牌和刷新令牌。

1. Machine-to-machine (M2M) 已完成客户端凭证授予的会话。成功使用客户端机密进行授权会返回访问令牌。

1. 之前已登录并收到刷新令牌的用户。刷新令牌身份验证会返回新的 ID 令牌和访问令牌。
**注意**  
在托管登录中使用授权码授予或通过联合身份验证登录的用户可以随时从令牌端点刷新其令牌。当[记忆设备](amazon-cognito-user-pools-device-tracking.md)在您的用户池中*未*处于活动状态时，使用 API 操作 `InitiateAuth` 和 `AdminInitiateAuth` 登录的用户可以使用令牌端点刷新其令牌。如果记忆设备处于活动状态，请使用应用程序客户端的[相关 API 或 SDK 令牌刷新操作](amazon-cognito-user-pools-using-the-refresh-token.md#using-the-refresh-token-api)刷新令牌。

当您向用户池添加域时，令牌端点将公开可用。它接受 HTTP POST 请求。为了实现应用程序安全性，请将 PKCE 与授权代码登录事件结合使用。PKCE 会验证传递授权码的用户是否与经过身份验证的用户相同。有关 PKCE 的更多信息，请参阅 [IETF RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636)。

要详细了解用户池应用程序客户端及其授权类型、客户端密钥、允许的范围和客户端，请 IDs 访问[特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。要详细了解 M2M 授权、客户端凭证授权以及使用访问令牌范围的授权，请访问[作用域、M2M 和资源服务器](cognito-user-pools-define-resource-servers.md)。

要从用户的访问令牌中检索有关用户的信息，可以将其传递给 [userInfo 端点](userinfo-endpoint.md) 或 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html) API 请求。访问令牌必须包含这些请求的相应范围，

## 为向令牌端点的 POST 请求设置格式
<a name="post-token"></a>

`/oauth2/token` 端点只支持 `HTTPS POST`。此端点非用户交互式。请在您的应用程序中使用 [OpenID Connect（OIDC）库](https://openid.net/developers/certified-openid-connect-implementations/)处理令牌请求。

令牌端点支持 `client_secret_basic` 和 `client_secret_post` 身份验证。有关 OIDC 规范的更多信息，请参阅[客户端身份验证](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication)。有关 OpenID Connect 规范中令牌端点的更多信息，请参阅[令牌端点](http://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint)。

### 标头中的请求参数
<a name="post-token-request-parameters"></a>

您可以将请求标头中的以下参数传递给令牌端点。

**`Authorization`**  
如果向客户端发布了密钥，则客户端可以在授权标头中将其 `client_id` 和 `client_secret` 作为 `client_secret_basic` HTTP 授权传递。您还可以在请求正文中包含 `client_id` 和 `client_secret` 作为 `client_secret_post` 授权。  
授权标头字符串是 [基本](https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side) `Base64Encode(client_id:client_secret)`。以下示例是具有客户端密钥 `abcdef01234567890` 的应用程序客户端 `djc98u3jiedmi283eu928` 的授权标头，其使用字符串 `djc98u3jiedmi283eu928:abcdef01234567890` 的 Base64 编码版本：  

```
Authorization: Basic ZGpjOTh1M2ppZWRtaTI4M2V1OTI4OmFiY2RlZjAxMjM0NTY3ODkw
```

**`Content-Type`**  
将此参数的值设置为 `'application/x-www-form-urlencoded'`。

### 正文中的请求参数
<a name="post-token-request-parameters-in-body"></a>

以下是您可以在请求正文中以 `x-www-form-urlencoded` 格式向令牌端点请求的参数。

**`grant_type`**  
*必填项*。  
要请求的 OIDC 授予的类型。  
必须为 `authorization_code`、`refresh_token` 或 `client_credentials`。在以下条件下，您可以从令牌端点请求自定义范围的访问令牌：  
+ 您在应用程序客户端配置中启用请求的范围。
+ 您为应用程序客户端配置了客户端密钥。
+ 您在应用程序客户端中启用客户端凭证授予。
仅当 `grant_type` 为 `authorization_code` 时，令牌端点才返回刷新令牌。

**`client_id`**  
*可选。当您在 `Authorization` 标头中提供应用程序客户端 ID 时不是必需项。*  
用户池中应用程序客户端的 ID。指定对用户进行身份验证的同一个应用程序客户端。  
如果客户端为公有且没有密钥，或在 `client_secret_post` 授权中有 `client_secret`，则必须提供此参数。

**`client_secret`**  
*可选。当您在 `Authorization` 标头中提供客户端密钥以及应用程序客户端没有密钥时不是必需项。*  
用于 `client_secret_post` 授权的应用程序客户端密钥（如果应用程序客户端有的话）。

**`scope`**  
*可选。*  
可以是与应用程序客户端关联的任何范围的组合。Amazon Cognito 会忽略请求中对于请求的应用程序客户端来说不允许使用的范围。如果您不提供此请求参数，则授权服务器会返回访问令牌 `scope` 声明，其中包含您在应用程序客户端配置中启用的所有授权范围。您可以请求对于请求的应用程序客户端来说允许使用的任何范围：标准范围、来自资源服务器的自定义范围以及 `aws.cognito.signin.user.admin` 用户自助范围。

**`redirect_uri`**  
*可选。授予客户端凭证时不是必需项。*  
必须是用于在 `/oauth2/authorize` 中获取 `authorization_code` 的相同 `redirect_uri`。  
如果 `grant_type` 是 `authorization_code`，则必须提供此参数。

**`refresh_token`**  
*可选。仅当用户已经拥有刷新令牌并希望获得新 ID 和访问令牌时使用。*  
要为用户的会话生成新的访问令牌和 ID 令牌，请将 `refresh_token` 的值设置为请求的应用程序客户端发布的有效刷新令牌。  
当[刷新令牌轮换](amazon-cognito-user-pools-using-the-refresh-token.md#using-the-refresh-token-rotation)处于活动状态时，返回带有新 ID 和访问令牌的新刷新令牌，否则仅返回 ID 和访问令牌。如果原始访问令牌[绑定到 API 资源](cognito-user-pools-define-resource-servers.md#cognito-user-pools-resource-binding)，则新的访问令牌会在 `aud` 声明中保留请求的 API URL。

**`code`**  
*可选。仅在授予授权码时必需。*  
来自授权码授予的授权码。如果授权请求包括 `authorization_code` 的 `grant_type`，则必须提供此参数。

**`aws_client_metadata`**  
*可选。*  
您要传递给输入 [machine-to-machine (M2M)](cognito-user-pools-define-resource-servers.md) 授权流程的信息。[令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md)您的应用程序可以收集有关会话的上下文信息，并将其传递到此参数中。当您以 URL 编码的 JSON 格式传递 `aws_client_metadata` 时，Amazon Cognito 会将其包含在触发器 Lambda 函数的输入事件中。令牌生成前触发器事件版本或全局 Lambda 触发器版本必须针对版本三或更高版本进行配置。尽管 Amazon Cognito 在授权码和客户端凭证 M2M 流程中接受对该端点的请求，但用户池仅从客户端凭证请求将 `aws_client_metadata` 传递到令牌生成前触发器。

**`code_verifier`**  
可选。仅当您在初始授权请求中提供了 `code_challenge_method` 和 `code_challenge` 参数时才必需。  
您的应用程序在 [PKCE](using-pkce-in-authorization-code.md) 的授权码授予请求中计算 `code_challenge` 的生成的代码验证程序。

## 为获取令牌交换授权代码
<a name="post-token-positive-exchanging-authorization-code-for-tokens"></a>

在通过授权码授予进行身份验证后，以下请求成功生成 ID、访问和刷新令牌。请求在 `Authorization` 标头中以 `client_secret_basic` 格式传递客户端密钥。

```
POST https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/token&
Content-Type='application/x-www-form-urlencoded'&
Authorization=Basic ZGpjOTh1M2ppZWRtaTI4M2V1OTI4OmFiY2RlZjAxMjM0NTY3ODkw

grant_type=authorization_code&
client_id=1example23456789&
code=AUTHORIZATION_CODE&
redirect_uri=com.myclientapp://myclient/redirect
```

响应向用户发布新的 ID、访问和刷新令牌以及其他元数据。

```
HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token": "eyJra1example",
    "id_token": "eyJra2example",
    "refresh_token": "eyJj3example",
    "token_type": "Bearer",
    "expires_in": 3600
}
```

## 基本授权的客户端凭证
<a name="exchanging-client-credentials-for-an-access-token-in-request-body"></a>

以下来自 M2M 应用程序的请求用于请求授予客户端凭证。由于客户端凭证需要客户端密钥，因此使用从应用程序客户端 ID 和密钥派生的 `Authorization` 标头对请求进行授权。该请求会生成一个具有两个请求范围的访问令牌。该请求还包括客户端元数据，在其中提供 IP 地址信息以及向此授予代表的用户发布的令牌。Amazon Cognito 将客户端元数据传递给令牌生成前 Lambda 触发器。

```
POST https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/token >
Content-Type='application/x-www-form-urlencoded'&
Authorization=Basic ZGpjOTh1M2ppZWRtaTI4M2V1OTI4OmFiY2RlZjAxMjM0NTY3ODkw

grant_type=client_credentials&
client_id=1example23456789&
scope=resourceServerIdentifier1%2Fscope1%20resourceServerIdentifier2%2Fscope2&
&aws_client_metadata=%7B%22onBehalfOfToken%22%3A%22eyJra789ghiEXAMPLE%22,%20%22ClientIpAddress%22%3A%22192.0.2.252%22%7D
```

Amazon Cognito 将以下输入事件传递给令牌生成前 Lambda 触发器。

```
{
    version: '3',
    triggerSource: 'TokenGeneration_ClientCredentials',
    region: 'us-east-1',
    userPoolId: 'us-east-1_EXAMPLE',
    userName: 'ClientCredentials',
    callerContext: {
        awsSdkVersion: 'aws-sdk-unknown-unknown',
        clientId: '1example23456789'
    },
    request: {
        userAttributes: {},
        groupConfiguration: null,
        scopes: [
           'resourceServerIdentifier1/scope1',
           'resourceServerIdentifier2/scope2'
        ],
        clientMetadata: {
            'onBehalfOfToken': 'eyJra789ghiEXAMPLE',
            'ClientIpAddress': '192.0.2.252'
        }
    },
    response: { claimsAndScopeOverrideDetails: null }
}
```

响应返回访问令牌。客户凭证授予用于 machine-to-machine（M2M）授权，并且仅返回访问令牌。

```
HTTP/1.1 200 OK
Content-Type: application/json
{
    "access_token": "eyJra1example",
    "token_type": "Bearer",
    "expires_in": 3600
}
```

## POST 正文授权的客户端凭证
<a name="post-token-positive-exchanging-client-credentials-for-an-access-token-in-request-body"></a>

以下客户端凭证授予请求在请求正文中包含 `client_secret` 参数，但是不包含 `Authorization` 标头。此请求使用 `client_secret_post` 授权语法。该请求会生成一个具有所请求范围的访问令牌。该请求还包括客户端元数据，在其中提供 IP 地址信息以及向此授予代表的用户发布的令牌。Amazon Cognito 将客户端元数据传递给令牌生成前 Lambda 触发器。

```
POST /oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
X-Amz-Target: AWSCognitoIdentityProviderService.Client credentials request
User-Agent: USER_AGENT
Accept: /
Accept-Encoding: gzip, deflate, br
Content-Length: 177
Referer: http://auth.example.com/oauth2/token
Host: auth.example.com
Connection: keep-alive

grant_type=client_credentials&
client_id=1example23456789&
scope=my_resource_server_identifier%2Fmy_custom_scope&
client_secret=9example87654321&
aws_client_metadata=%7B%22onBehalfOfToken%22%3A%22eyJra789ghiEXAMPLE%22,%20%22ClientIpAddress%22%3A%22192.0.2.252%22%7D
```

Amazon Cognito 将以下输入事件传递给令牌生成前 Lambda 触发器。

```
{
    version: '3',
    triggerSource: 'TokenGeneration_ClientCredentials',
    region: 'us-east-1',
    userPoolId: 'us-east-1_EXAMPLE',
    userName: 'ClientCredentials',
    callerContext: {
        awsSdkVersion: 'aws-sdk-unknown-unknown',
        clientId: '1example23456789'
    },
    request: {
        userAttributes: {},
        groupConfiguration: null,
        scopes: [
           'resourceServerIdentifier1/my_custom_scope'
        ],
        clientMetadata: {
            'onBehalfOfToken': 'eyJra789ghiEXAMPLE',
            'ClientIpAddress': '192.0.2.252'
        }
    },
    response: { claimsAndScopeOverrideDetails: null }
}
```

响应返回访问令牌。客户凭证授予用于 machine-to-machine（M2M）授权，并且仅返回访问令牌。

```
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Date: Tue, 05 Dec 2023 16:11:11 GMT
x-amz-cognito-request-id: 829f4fe2-a1ee-476e-b834-5cd85c03373b

{
    "access_token": "eyJra12345EXAMPLE",
    "expires_in": 3600,
    "token_type": "Bearer"
}
```

## PKCE 的授权码授予
<a name="post-token-positive-exchanging-authorization-code-grant-with-pkce-for-tokens"></a>

以下示例请求完成在 [PKCE](using-pkce-in-authorization-code.md) 的授权码授予请求中包含 `code_challenge_method` 和 `code_challenge` 参数的授权请求。

```
POST https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/token
Content-Type='application/x-www-form-urlencoded'&
Authorization=Basic ZGpjOTh1M2ppZWRtaTI4M2V1OTI4OmFiY2RlZjAxMjM0NTY3ODkw

grant_type=authorization_code&
client_id=1example23456789&
code=AUTHORIZATION_CODE&
code_verifier=CODE_VERIFIER&
redirect_uri=com.myclientapp://myclient/redirect
```

响应从应用程序的成功 PKCE 验证中返回 ID、访问和刷新令牌。

```
HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token": "eyJra1example",
    "id_token": "eyJra2example",
    "refresh_token": "eyJj3example",
    "token_type": "Bearer",
    "expires_in": 3600
}
```

## 无刷新令牌轮换的令牌刷新
<a name="post-token-positive-exchanging-a-refresh-token-for-tokens"></a>

以下示例请求向[刷新令牌轮换](amazon-cognito-user-pools-using-the-refresh-token.md#using-the-refresh-token-rotation)不处于活动状态的应用程序客户端提供刷新令牌。由于应用程序客户端有客户端密钥，因此请求会提供 `Authorization` 标头。

```
POST https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/token >
Content-Type='application/x-www-form-urlencoded'&
Authorization=Basic ZGpjOTh1M2ppZWRtaTI4M2V1OTI4OmFiY2RlZjAxMjM0NTY3ODkw

grant_type=refresh_token&
client_id=1example23456789&
refresh_token=eyJj3example
```

响应返回新的 ID 令牌和访问令牌。

```
HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token": "eyJra1example",
    "id_token": "eyJra2example",
    "token_type": "Bearer",
    "expires_in": 3600
}
```

## 带刷新令牌轮换的令牌刷新
<a name="post-token-positive-refresh-token-rotation"></a>

以下示例请求向[刷新令牌轮换](amazon-cognito-user-pools-using-the-refresh-token.md#using-the-refresh-token-rotation)处于活动状态的应用程序客户端提供刷新令牌。由于应用程序客户端有客户端密钥，因此请求会提供 `Authorization` 标头。

```
POST https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/token >
Content-Type='application/x-www-form-urlencoded'&
Authorization=Basic ZGpjOTh1M2ppZWRtaTI4M2V1OTI4OmFiY2RlZjAxMjM0NTY3ODkw

grant_type=refresh_token&
client_id=1example23456789&
refresh_token=eyJj3example
```

响应返回新的 ID、访问和刷新令牌。

```
HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token": "eyJra1example",
    "id_token": "eyJra2example",
    "refresh_token": "eyJj4example",
    "token_type": "Bearer",
    "expires_in": 3600
}
```

## 负向响应的示例
<a name="post-token-negative"></a>

格式错误的请求会从令牌端点生成错误。以下是令牌请求生成错误时响应正文的大致示意图。

```
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8

{
"error":"invalid_request|invalid_client|invalid_grant|unauthorized_client|unsupported_grant_type"
}
```

**`invalid_request`**  
请求缺少必需的参数、包括不支持的参数值（除了 `unsupported_grant_type` 之外）或者格式错误。例如，`grant_type` 是 `refresh_token`，但未包括 `refresh_token`。

**`invalid_client`**  
客户端身份验证失败。例如，客户端的授权标头中包含 `client_id` 和 `client_secret`，但没有这样的客户端带有 `client_id` 和 `client_secret`。

**`invalid_grant`**  
已撤销刷新令牌。  
授权代码已使用或不存在。  
应用程序客户端对请求的范围内的所有[属性](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html)都没有读取权限。例如，您的应用程序请求 `email` 范围，应用程序客户端可以读取 `email` 属性，但不能读取 `email_verified`。

**`unauthorized_client`**  
客户端不允许代码授予流或刷新令牌。

**`unsupported_grant_type`**  
如果 `grant_type` 是 `authorization_code`、`refresh_token` 或 `client_credentials` 之外的任意内容，则返回。

# 用户属性端点
<a name="userinfo-endpoint"></a>

在 OIDC 发布包含用户属性的 ID 令牌的地方， OAuth 2.0 实现端点。`/oauth2/userInfo`经过身份验证的用户或客户端会收到包含 `scopes` 声明的访问令牌。此声明决定了授权服务器应返回的属性。当应用程序向 `userInfo` 端点提供访问令牌时，授权服务器会返回一个响应正文，其中包含通过访问令牌范围设置的边界内的用户属性。只要您的应用程序持有至少具有 `openid` 范围声明的有效访问令牌，就可以从 `userInfo` 端点检索有关用户的信息。

`userInfo` 端点是 OpenID Connect（OIDC）[userInfo 端点](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)。当服务提供商出示您的[令牌端点](token-endpoint.md)发放的访问令牌时，响应中会包含用户属性。用户访问令牌中的范围定义了 userInfo 端点在其响应中返回的用户属性。`openid` 范围必须是访问令牌声明的范围之一。

Amazon Cognito 颁发访问令牌来响应用户池 API 请求，如 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)。由于它们不包含任何范围，因此 userInfo 端点不接受这些访问令牌。而是必须由您出示来自令牌端点的访问令牌。

您的 OAuth 2.0 第三方身份提供商 (IdP) 还托管一个userInfo终端节点。当您的用户使用该 IdP 进行身份验证时，Amazon Cognito 会以静默方式与 IdP `token` 端点交换授权代码。您的用户池传递 IdP 访问令牌以授权从 IdP `userInfo` 端点检索用户信息。

用户访问令牌中的范围由身份验证请求中的 `scopes` 请求参数或[令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md)添加的范围确定。您可以解码访问令牌并检查 `scope` 声明，以查看其包含的访问控制范围。以下是一些影响从 `userInfo` 端点返回的数据的范围组合。保留的 Amazon Cognito 范围 `aws.cognito.signin.user.admin` 对从该端点返回的数据没有影响。访问令牌中的示例范围及其对 `userInfo` 响应的影响

**`openid`**  
返回包含应用程序客户端可以读取的所有用户属性的响应。

**`openid profile`**  
返回用户属性 `name`、`family_name`、`given_name`、`middle_name`、`nickname`、`preferred_username`、`profile`、`picture`、`website`、`gender`、`birthdate`、`zoneinfo`、`locale` 和 `updated_at`。还会返回[自定义属性](user-pool-settings-attributes.md#user-pool-settings-custom-attributes)。在对每个属性都没有读取权限的应用程序客户端中，对此范围的响应是您的应用程序客户端具有读取权限的规范中的所有属性。

**`openid email`**  
返回基本配置文件信息以及 `email` 和 `email_verified` 属性。

**`openid phone`**  
返回基本配置文件信息以及 `phone_number` 和 `phone_number_verified` 属性。

## GET /oauth2/userInfo
<a name="get-userinfo"></a>

您的应用程序直接生成对此端点的请求，而不是通过浏览器。

有关更多信息，请参阅 OpenID Connect（OIDC）规范中的 [UserInfo 端点](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo)。

**Topics**
+ [GET /oauth2/userInfo](#get-userinfo)
+ [标头中的请求参数](#get-userinfo-request-header-parameters)
+ [示例：请求](#get-userinfo-positive-exchanging-authorization-code-for-userinfo-sample-request)
+ [示例：正向响应](#get-userinfo-response-sample)
+ [示例：负向响应](#get-userinfo-negative)

## 标头中的请求参数
<a name="get-userinfo-request-header-parameters"></a>

**`Authorization: Bearer <access_token>`**  
传递授权标头字段中的访问令牌。  
必需。

## 示例：请求
<a name="get-userinfo-positive-exchanging-authorization-code-for-userinfo-sample-request"></a>

```
GET /oauth2/userInfo HTTP/1.1
Content-Type: application/x-amz-json-1.1
Authorization: Bearer eyJra12345EXAMPLE
User-Agent: [User agent]
Accept: */*
Host: auth.example.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
```

## 示例：正向响应
<a name="get-userinfo-response-sample"></a>

```
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: [Integer]
Date: [Timestamp]
x-amz-cognito-request-id: [UUID]
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Server: Server
Connection: keep-alive
{
    "sub": "[UUID]",
    "email_verified": "true",
    "custom:mycustom1": "CustomValue",
    "phone_number_verified": "true",
    "phone_number": "+12065551212",
    "email": "bob@example.com",
    "username": "bob"
}
```

有关 OIDC 声明的列表，请参阅[标准声明](http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)。目前，Amazon Cognito 将 `email_verified` 和 `phone_number_verified` 的值返回为字符串。

## 示例：负向响应
<a name="get-userinfo-negative"></a>

### 示例：不正确的请求
<a name="get-userinfo-negative-400"></a>

```
HTTP/1.1 400 Bad Request
WWW-Authenticate: error="invalid_request",
error_description="Bad OAuth2 request at UserInfo Endpoint"
```

**`invalid_request`**  
请求缺少必需的参数、包括不支持的参数值或格式错误。

### 示例：不正确的令牌
<a name="get-userinfo-negative-401"></a>

```
HTTP/1.1 401 Unauthorized
WWW-Authenticate: error="invalid_token",
error_description="Access token is expired, disabled, or deleted, or the user has globally signed out."
```

**`invalid_token`**  
访问令牌已过期、已撤销、格式不正确或无效。

# 令牌撤销端点
<a name="revocation-endpoint"></a>

在会话中持有刷新令牌的用户拥有类似于浏览器 Cookie 的东西。只要刷新令牌有效，他们就可以继续现有会话。在用户的 ID 或访问令牌到期后，您的应用程序可以使用刷新令牌来获取新的有效令牌，而不是提示他们登录。但是，您可以从外部判断应该结束用户的会话，或者用户可能选择忘记其当前会话。此时，您可以撤销该刷新令牌，这样用户就无法再维持他们的会话。

`/oauth2/revoke` 端点撤销 Amazon Cognito 最初使用您提供的刷新令牌颁发的用户访问令牌。此端点还会撤销刷新令牌本身以及来自同一刷新令牌的所有后续访问和身份令牌。终端节点撤销令牌后，您无法使用已撤销的访问令牌来访问 Amazon Cognito APIs 令牌进行身份验证。

## POST /oauth2/revoke
<a name="post-revoke"></a>

`/oauth2/revoke` 端点只支持 `HTTPS POST`。用户池客户端直接对此端点发出请求，而不通过系统浏览器。

### 标头中的请求参数
<a name="revocation-request-parameters"></a>

**`Authorization`**  
如果应用程序客户端具有客户端密钥，则客户端必须通过基本 HTTP 授权在其授权标头中传递 `client_id` 和 `client_secret`。密钥是[基本](https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side) `Base64Encode(client_id:client_secret)`。

**`Content-Type`**  
必须始终为 `'application/x-www-form-urlencoded'`。

#### 正文中的请求参数
<a name="revocation-request-parameters-body"></a>

**`token`**  
（必需）客户端要撤销的刷新令牌。请求还撤销 Amazon Cognito 使用此刷新令牌颁发的所有访问令牌。  
必需。

**`client_id`**  
（可选）您要撤销的令牌的应用程序客户端 ID。  
如果客户端是公有的且没有密钥，则为必需。

## 撤销请求示例
<a name="revoke-sample-request"></a>

此撤销请求会撤销没有客户端密钥的应用程序客户端的刷新令牌。注意请求正文中的 `client_id` 参数。

```
POST /oauth2/revoke HTTP/1.1
Host: mydomain.auth.us-east-1.amazoncognito.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
token=2YotnFZFEjr1zCsicMWpAA&
client_id=1example23456789
```

此撤销请求会撤销*有*客户端密钥的应用程序客户端的刷新令牌。请注意，`Authorization` 标头包含已编码的客户端 ID 和客户端密钥，但请求正文中没有 `client_id`。

```
POST /oauth2/revoke HTTP/1.1
Host: mydomain.auth.us-east-1.amazoncognito.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
token=2YotnFZFEjr1zCsicMWpAA
```

## 撤销错误响应
<a name="revoke-sample-response"></a>

成功的响应包含空正文。错误响应是一个带有 `error` 字段和 `error_description` 字段（在某些情况下）的 JSON 对象。

**端点错误**
+ 如果令牌在请求中不存在或者应用程序客户端禁用了该特征，则您会收到 HTTP 400 和错误 `invalid_request`。
+ 如果 Amazon Cognito 在撤销请求中发送的令牌不是刷新令牌，则您会收到 HTTP 400 和错误 `unsupported_token_type`。
+ 如果客户端凭证无效，则您会收到 HTTP 401 和错误 `invalid_client`。
+ 如果令牌已撤销或客户端提交的令牌无效，您会收到 HTTP 200 OK。

# IdP SAML 断言端点
<a name="saml2-idpresponse-endpoint"></a>

`/saml2/idpresponse` 接收 SAML 断言。在 service-provider-initiated（SP 启动的）登录中，您的应用程序不会直接与该端点交互——您的 SAML 2.0 身份提供商 (IdP) 使用他们的 SAML 响应将您的用户重定向到此处。对于 SP 发起的登录，请将 IdP 配置为将 `saml2/idpresponse` 的路径作为断言使用者服务（ACS）URL。有关会话启动的更多信息，请参阅 [SAML 会话在 Amazon Cognito 用户池中启动](cognito-user-pools-SAML-session-initiation.md)。

在 IdP 发起的登录中，用户通过您的 SAML 2.0 提供者登录后，在您的应用程序中调用此端点的请求。您的用户在浏览器中使用您的 IdP 登录，然后您的应用程序收集 SAML 断言并将其提交到此端点。您必须通过 HTTPS 在 `HTTP POST` 请求的正文中提交 SAML 断言。`POST` 请求的正文必须是 `SAMLResponse` 参数和 `Relaystate` 参数。有关更多信息，请参阅 [实施 IdP 发起的 SAML 登录](cognito-user-pools-SAML-session-initiation.md#cognito-user-pools-SAML-session-initiation-idp-initiation)。

`saml2/idpresponse` 端点可以接受长度长达 100,000 个字符的 SAML 断言。

## POST `/saml2/idpresponse`
<a name="saml2-idpresponse-endpoint-post"></a>

要在 IdP 发起的登录中使用 `/saml2/idpresponse` 端点，请生成一个 POST 请求，其中包含为您的用户池提供用户会话信息的参数。
+ 他们希望登录到的应用程序客户端。
+ 他们希望最终到达的回调 URL。
+ 他们想要在用户的访问令牌中请求的 OAuth 2.0 范围。
+ 启动登录请求的 IdP。

### IdP 发起的请求正文参数
<a name="saml2-idpresponse-endpoint-post-request"></a>

*SAMLResponse*  
来自与您用户池中有效应用程序客户端和 IdP 配置关联的 IdP 的 Base64 编码 SAML 声明。

*RelayState*  
`RelayState` 参数包含您原本要传递给 `oauth2/authorize` 端点的请求参数。有关这些参数的详细信息，请参阅[对端点授权](authorization-endpoint.md)。    
*response\$1type*  
 OAuth 2.0 的拨款类型。  
*client\$1id*  
应用程序客户端 ID。  
*redirect\$1uri*  
在 Amazon Cognito 授权用户之后，身份验证服务器将浏览器重定向到的 URL。  
*identity\$1provider*  
要将用户重定向到其中的身份提供者的名称。  
*idp\$1identifier*  
要将用户重定向到其中的身份提供者的标识符。  
*范围*  
您希望用户向授权服务器请求的 OAuth 2.0 范围。

### 具有正向响应的示例请求
<a name="saml2-idpresponse-endpoint-post-example"></a>

**示例：POST 请求**  
以下请求适用于在应用程序客户端 `1example23456789` 中从 IdP `MySAMLIdP` 获取用户的授权代码授予。用户`https://www.example.com`使用其授权码重定向到，该授权码可以兑换包含范围为 OAuth 2.0 和`openid``email``phone`、的访问令牌的令牌。

```
POST /saml2/idpresponse HTTP/1.1
User-Agent: USER_AGENT
Accept: */*
Host: example.auth.us-east-1.amazoncognito.com
Content-Type: application/x-www-form-urlencoded

SAMLResponse=[Base64-encoded SAML assertion]&RelayState=identity_provider%3DMySAMLIdP%26client_id%3D1example23456789%26redirect_uri%3Dhttps%3A%2F%2Fwww.example.com%26response_type%3Dcode%26scope%3Demail%2Bopenid%2Bphone
```

**示例：响应**  
以下是对上一个请求的响应。

```
HTTP/1.1 302 Found
Date: Wed, 06 Dec 2023 00:15:29 GMT
Content-Length: 0
x-amz-cognito-request-id: 8aba6eb5-fb54-4bc6-9368-c3878434f0fb
Location: https://www.example.com?code=[Authorization code]
```

# OAuth 2.0 补助金
<a name="federation-endpoints-oauth-grants"></a>

Amazon Cognito 用户池 OAuth 2.0 授权服务器发布令牌以响应三种类型的 OAuth 2.0 [授权授权](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3)。您可以为用户池中的每个应用程序客户端设置支持的授权类型。您不能在同一应用程序客户端中启用*客户端凭证*授予作为*隐式* 或*授权码* 授予。隐式和授权码授予的请求从[对端点授权](authorization-endpoint.md)开始，而客户端凭证授予的请求从[令牌端点](token-endpoint.md)开始。

**授予授权代码**  
为了响应您的成功身份验证请求，授权服务器会在回调 URL 的 `code` 参数中添加一个授权码。然后，您必须与[令牌端点](token-endpoint.md)交换 ID、访问令牌和刷新令牌的代码。要请求授权码授予，请在请求中将 `response_type` 设置为 `code`。有关示例请求，请参阅[示例：授权代码授予](authorization-endpoint.md#sample-authorization-code-grant)。Amazon Cognito 在授权码授予中支持[代码交换的证明密钥（PKCE）](using-pkce-in-authorization-code.md)。  
授权码授予是最安全的授权授予形式。它不会直接向您的用户显示令牌内容。相反，您的应用程序负责检索和安全存储用户的令牌。在 Amazon Cognito 中，授权码授予是从授权服务器获取所有三种令牌类型（ID、访问和刷新）的唯一方法。您也可以通过 Amazon Cognito 用户池 API 从身份验证中获取所有三种令牌类型，但是 API 不使用除 `aws.cognito.signin.user.admin` 以外的范围发布访问令牌。

**隐式授予**  
为了响应成功的身份验证请求，授权服务器会在 `access_token` 参数中附加一个访问令牌，并在您的回调 URL 的 `id_token` 参数中附加一个 ID 令牌。隐式授予不要求与[令牌端点](token-endpoint.md)进行额外的交互。要请求隐式授予，请在请求中将 `response_type` 设置为 `token`。隐式授予仅生成 ID 和访问令牌。有关示例请求，请参阅[示例：不带 `openid` 范围的令牌（隐式）授权](authorization-endpoint.md#sample-token-grant-without-openid-scope)。  
隐式授予是旧版授权授予。与授权码授予不同，用户可以拦截和检查您的令牌。要防止通过隐式授予交付令牌，请将您的应用程序客户端配置为仅支持授权码授予。

**客户端凭证**  
客户凭证是一种仅限授权的访问授权。 machine-to-machine要获得客户凭证授予，请绕过[对端点授权](authorization-endpoint.md)，并直接向[令牌端点](token-endpoint.md)生成请求。您的应用程序客户端必须具有客户端密钥，并且仅支持客户端凭证授予。为了响应您的成功请求，授权服务器会返回访问令牌。  
来自客户端凭证授予的访问令牌是一种包含 OAuth 2.0 范围的授权机制。通常，令牌包含授权 HTTP 操作受访问 APIs保护的自定义作用域声明。有关更多信息，请参阅 [作用域、M2M 和资源服务器](cognito-user-pools-define-resource-servers.md)。  
客户凭证授予会增加您的 AWS 账单费用。有关更多信息，请参阅 [Amazon Cognito 定价](https://aws.amazon.com/cognito/pricing)。

**刷新令牌**  
您可以直接从[令牌端点](token-endpoint.md)请求刷新令牌授予。此授予会返回新的 ID 令牌和访问令牌，以交换有效的刷新令牌。

有关这些赠款及其实施的更多视角，请参阅如何[在 Amazon Cognito 中使用 OAuth 2.0：在*AWS 安全*博客中了解不同的 OAuth 2.0 授权](https://aws.amazon.com/blogs/security/how-to-use-oauth-2-0-in-amazon-cognito-learn-about-the-different-oauth-2-0-grants/)。

# 在授权代码授予中使用 PKCE
<a name="using-pkce-in-authorization-code"></a>

Amazon Cognito 在授权代码授予中支持代码交换的证明密钥（PKCE）身份验证。PKCE 是公共客户端的 OAuth 2.0 授权代码授予的扩展。PKCE 可防止兑换拦截的授权代码。

## Amazon Cognito 如何使用 PKCE
<a name="how-pkce-works"></a>

要开始使用 PKCE 进行身份验证，您的应用程序必须生成一个唯一的字符串值。此字符串是代码验证程序，Amazon Cognito 使用该密钥值将请求初始授权授予的客户端与使用授权代码交换令牌的客户端进行比较。

您的应用程序必须对代码验证器字符串应用 SHA256 哈希值，并将结果编码为 base64。将经过哈希处理的字符串作为请求正文中的 `code_challenge` 参数传递到 [对端点授权](authorization-endpoint.md)。当您的应用程序将授权代码交换为令牌时，它必须以纯文本形式包括代码验证程序字符串，作为请求正文中的 `code_verifier` 参数传递到 [令牌端点](token-endpoint.md)。Amazon Cognito 对代码验证器执行相同的 hash-and-encode操作。Amazon Cognito 仅在确定代码验证程序产生的代码质询与在授权请求中收到的代码质询相同时，才会返回 ID 令牌、访问令牌和刷新令牌。

**使用 PKCE 实现授权授予流程**

1. 打开 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或创建一个用户池。如果您创建用户池，系统将在向导期间提示您设置应用程序客户端并配置托管登录。

   1. 如果您创建新用户池，请在引导式设置期间设置应用程序客户端并配置托管登录。

   1. 如果您配置现有用户池，请添加[域](cognito-user-pools-assign-domain.md)和[公共应用程序客户端](user-pool-settings-client-apps.md)（如果尚未添加）。

1. 生成一个随机的字母数字字符串 [通常是一个全局唯一标识符（[UUID](cognito-terms.md#terms-uuid)）]，以便为 PKCE 创建代码质询。此字符串是您将在发送给 [令牌端点](token-endpoint.md) 的请求中提交的 `code_verifier` 参数的值。

1. 用 SHA256 算法对`code_verifier`字符串进行哈希处理。将哈希操作的结果编码为 base64。此字符串是您将在发送给 [对端点授权](authorization-endpoint.md) 的请求中提交的 `code_challenge` 参数的值。

   以下 Python 示例生成 `code_verifier` 并计算 `code_challenge`：

   ```
   #!/usr/bin/env python3
   
   import secrets
   from base64 import urlsafe_b64encode
   from hashlib import sha256
   from string import ascii_letters
   from string import digits
   
   # use the secrets module for cryptographically strong random values
   alphabet = ascii_letters + digits
   code_verifier = ''.join(secrets.choice(alphabet) for _ in range(128))
   code_verifier_hash = sha256(code_verifier.encode()).digest()
   code_challenge = urlsafe_b64encode(code_verifier_hash).decode().rstrip('=')
   
   print(f"code challenge: {code_challenge}")
   print(f"code verifier: {code_verifier}")
   ```

   以下是 Python 脚本的示例输出：

   ```
   code challenge: Eh0mg-OZv7BAyo-tdv_vYamx1boOYDulDklyXoMDtLg
   code verifier: 9D-aW_iygXrgQcWJd0y0tNVMPSXSChIc2xceDhvYVdGLCBk-JWFTmBNjvKSdOrjTTYazOFbUmrFERrjWx6oKtK2b6z_x4_gHBDlr4K1mRFGyE8yA-05-_v7Dxf3EIYJH
   ```

1. 使用 PKCE 的授权码授予请求完成托管登录的登录。以下是示例 URL：

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?response_type=code&client_id=1example23456789&redirect_uri=https://www.example.com&code_challenge=Eh0mg-OZv7BAyo-tdv_vYamx1boOYDulDklyXoMDtLg&code_challenge_method=S256
   ```

1. 收集授权 `code` 并使用令牌端点将其兑换为令牌。以下是一个示例请求：

   ```
   POST /oauth2/token HTTP/1.1
   Host: mydomain.auth.us-east-1.amazoncognito.com
   Content-Type: application/x-www-form-urlencoded
   Content-Length: 296
   
   redirect_uri=https%3A%2F%2Fwww.example.com&
   client_id=1example23456789&
   code=7378f445-c87f-400c-855e-0297d072ff03&
   grant_type=authorization_code&
   code_verifier=9D-aW_iygXrgQcWJd0y0tNVMPSXSChIc2xceDhvYVdGLCBk-JWFTmBNjvKSdOrjTTYazOFbUmrFERrjWx6oKtK2b6z_x4_gHBDlr4K1mRFGyE8yA-05-_v7Dxf3EIYJH
   ```

1. 查看响应。响应将包含 ID 令牌、访问令牌和刷新令牌。有关使用 Amazon Cognito 用户池令牌的更多信息，请参阅[了解用户池 JSON 网络令牌 (JWTs)](amazon-cognito-user-pools-using-tokens-with-identity-providers.md)。

# 托管登录和联合身份验证错误响应
<a name="federation-endpoint-idp-responses"></a>

托管登录或联合登录中的登录过程可能会返回错误。以下是一些可能导致身份验证以错误结束的情况。
+ 用户执行了您的用户池无法完成的操作。
+ Lambda 触发器不以预期的语法响应。
+ 您的身份提供者（IdP）返回错误。
+ Amazon Cognito 无法验证您的用户提供的属性信息。
+ 您的 IdP 未发送与所需属性对应的声明。

当 Amazon Cognito 遇到错误时，它通过以下方式之一进行通信。

1. Amazon Cognito 发送的重定向 URL 的请求参数中存在错误。

1. Amazon Cognito 在托管登录中显示错误。

Amazon Cognito 附加到请求参数的错误具有以下格式。

```
https://<Callback URL>/?error_description=error+description&error=error+name
```

如果您帮助用户在无法执行操作时提交错误信息，则要求他们捕获 URL *和*文本或页面的屏幕截图。

**注意**  
Amazon Cognito 错误描述不是固定字符串，您不应使用依赖于固定模式或格式的逻辑。

**OIDC 和社交身份提供者错误消息**  
您的身份提供者可能会返回错误。当 OIDC 或 2.0 I OAuth dP 返回符合标准的错误时，Amazon Cognito 会将您的用户重定向到回传 URL，并将提供商错误响应添加到错误请求参数中。Amazon Cognito 将提供者名称和 HTTP 错误代码添加到现有的错误字符串中。

以下 URL 是从返回错误的 IdP 重定向到 Amazon Cognito 的示例。

```
https://www.amazon.com/?error_description=LoginWithAmazon+Error+-+400+invalid_request+The+request+is+missing+a+required+parameter+%3A+client_secret&error=invalid_request
```

由于 Amazon Cognito 仅返回它从提供者处收到的内容，因此您的用户可能会看到这些信息的一部分。

如果用户在通过您的 IdP 进行初始登录时遇到问题，IdP 会直接向用户发送任何错误消息。当 Amazon Cognito 向您的 IdP 生成验证用户会话的请求时，它会向您的用户中继一条错误消息。Amazon Cognito 中继了 OAuth 来自以下终端节点的 OIDC IdP 错误消息。

`/token`  
Amazon Cognito 交换 IdP 授权代码以获得访问令牌。

`/.well-known/openid-configuration`  
Amazon Cognito 发现了通往发行者端点的路径。

`/.well-known/jwks.json`  
为了验证用户的 JSON 网络令牌 (JWTs)，Amazon Cognito 会发现你的 IdP 用来签署令牌的 JSON 网络密钥 (JWKs)。

由于 Amazon Cognito 不会启动到可能返回 HTTP 错误的 SAML 2.0 提供者的出站会话，因此，用户在与 SAML 2.0 IdP 会话期间出现的错误不包括这种形式的提供者错误消息。