

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

# 身份池身份验证流程
<a name="authentication-flow"></a>

Amazon Cognito 可帮助您为终端用户创建在多个设备和平台间保持一致的唯一标识符。Amazon Cognito 还会向您的应用程序提供临时的、权限有限的凭证以访问资源。 AWS 此页面介绍有关 Amazon Cognito 中的身份验证如何工作的基础知识，并解释了身份池中身份的生命周期。

**外部提供商身份验证流程**

使用 Amazon Cognito 进行身份验证的用户将通过一个多步骤流程来引导启动其凭证。Amazon Cognito 提供两个不同的通过公有提供商进行身份验证的流程：增强型流程和基本流程。

完成其中一个流程后，您可以访问由您的角色访问策略定义的其他 AWS 服务 流程。默认情况下，[Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/)创建可访问 Amazon Cognito Sync 存储和 Amazon Mobile Analytics 的角色。有关如何授予额外访问权限的更多信息，请参阅 [IAM 角色](iam-roles.md)。

身份池接受来自提供商的以下构件：


| Provider | 身份验证构件 | 
| --- | --- | 
| Amazon Cognito 用户池 | ID 令牌 | 
| OpenID Connect（OIDC） | ID 令牌 | 
| SAML 2.0 | SAML 断言 | 
| 社交提供商 | 访问令牌 | 

## 增强（简化）的身份验证流程
<a name="authentication-flow-enhanced"></a>

当您使用增强版身份验证流程时，您的应用程序会首先在请求中提供来自授权的 Amazon Cognito 用户池或第三方身份提供商的身份验证证明。[GetId](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetId.html)

1. 您的应用程序显示 [GetId](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetId.html) 请求中来自已授权 Amazon Cognito 用户池或第三方身份提供者的身份验证证明（JSON Web 令牌或 SAML 断言）。

1. 您的身份池返回身份 ID。

1. 您的应用程序在[GetCredentialsForIdentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html)请求中将身份 ID 与相同的身份验证证明相结合。

1. 您的身份池会返回 AWS 证书。

1. 您的应用程序使用临时证书签署 AWS API 请求。

增强型身份验证管理您的身份池配置中的 IAM 角色选择和凭证检索的逻辑。您可以配置身份池以选择默认角色，将基于属性的访问权限控制（ABAC）或基于角色的访问权限控制（RBAC）原则应用于角色选择。来自增强身份验证的 AWS 凭证有效期为一小时。

**增强型身份验证中的操作顺序**

1. `GetId`

1. `GetCredentialsForIdentity`

![\[显示了增强型身份验证流程的示意图\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/amazon-cognito-ext-auth-enhanced-flow.png)


## 基本（经典）身份验证流程
<a name="authentication-flow-basic"></a>

在实施基本身份验证流程时，您的应用程序会选择您希望用户代入的 IAM 角色。

1. 您的应用程序显示 [GetId](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetId.html) 请求中来自已授权 Amazon Cognito 用户池或第三方身份提供者的身份验证证明（JSON Web 令牌或 SAML 断言）。

1. 您的身份池返回身份 ID。

1. 您的应用程序在[GetOpenIdToken](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdToken.html)请求中将身份 ID 与相同的身份验证证明相结合。

1. `GetOpenIdToken`返回由您的身份池颁发的新 OAuth 2.0 令牌。

1. 您的应用程序在[AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html)请求中显示新令牌。

1. AWS Security Token Service (AWS STS) 返回 AWS 凭证。

1. 您的应用程序使用临时证书签署 AWS API 请求。

通过基本型工作流，您可以更精细地控制分发给用户的凭证。增强型身份验证流程的 `GetCredentialsForIdentity` 请求根据访问令牌的内容请求角色。经典工作流程中的`AssumeRoleWithWebIdentity`请求使您的应用程序能够更好地请求您配置了足够信任策略的任何 AWS Identity and Access Management 角色的凭证。您也可以请求自定义角色会话持续时间。

您可以在没有角色映射的用户池中使用基本身份验证流程进行登录。这种类型的身份池没有默认的已验证角色或未经身份验证的角色，也没有配置基于角色或基于属性的访问控制。当您在使用角色映射的身份池中尝试 `GetOpenIdToken` 时，会收到以下错误。

```
Basic (classic) flow is not supported with RoleMappings, please use enhanced flow.
```

**基本身份验证中的操作顺序**

1. `GetId`

1. `GetOpenIdToken`

1. `AssumeRoleWithWebIdentity`

![\[显示了基本身份验证流程的示意图\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/amazon-cognito-ext-auth-basic-flow.png)


## 经过开发者身份验证的身份验证流程
<a name="authentication-flow-developer"></a>

使用[经开发人员验证的身份](developer-authenticated-identities.md)时，您的客户端将使用包括 Amazon Cognito 外部代码的不同身份验证流程，在您自己的身份验证系统中验证用户。从您的身份池的角度来看，您在身份请求中提出的声明是任意标识符，并且身份验证由您在应用程序中编码的 IAM 凭证进行授权。

**开发人员提供商的增强型身份验证中的操作顺序**

1. 通过开发人员提供商登录（Amazon Cognito 外部代码）

1. 验证用户登录（Amazon Cognito 外部代码）

1. [GetOpenIdTokenForDeveloperIdentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html)

1. [GetCredentialsForIdentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html)

![\[一个示意图，显示了经开发人员验证身份的增强型身份验证流程\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/amazon-cognito-dev-auth-enhanced-flow.png)


**开发人员提供商的基本身份验证中的操作顺序**

1. 在身份池之外实施逻辑来登录，并生成开发人员提供商标识符。

1. 检索存储的服务器端 AWS 凭证。

1. 在使用授权 AWS 凭证签名[GetOpenIdTokenForDeveloperIdentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html)的 API 请求中发送开发者提供商标识符。

1. 使用请求应用程序凭证[AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html)。

![\[一个示意图，显示了经开发人员验证身份的基本身份验证流程\]](http://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/images/amazon-cognito-dev-auth-basic-flow.png)


## 我应该实施哪个身份验证流程？
<a name="authentication-flow-choosing"></a>

**增强型流程**是更安全的选择，开发人员的工作量更少：
+ 增强型流程降低了 API 请求的复杂性、大小和频率。
+ 您的应用程序无需向 AWS STS发出其他 API 请求。
+ 您的身份池会评估您的用户应收到的 IAM 角色凭证。您无需在客户端中嵌入用于角色选择的逻辑。

**重要**  
创建新的身份池时，最好不要默认激活基本（经典）身份验证。要实施基本身份验证，请先评估您的 IAM 角色与 Web 身份之间的信任关系。然后在您的客户端中构建角色选择逻辑，并保护客户端不被用户修改。

**基本身份验证流程**将 IAM 角色选择的逻辑委托给您的应用程序。在此流程中，Amazon Cognito 会验证您的用户经过身份验证或未经身份验证的会话，并颁发一个令牌，您可以用该令牌交换证书。 AWS STS用户可以将基本身份验证中的令牌交换为信任您的身份池和 `amr` /或 authenticated/unauthenticated 状态的任何 IAM 角色。

同样，您要明白，**开发人员身份验证**是一种绕过身份提供者身份验证的快捷方式。Amazon Cognito 信任授权[GetOpenIdTokenForDeveloperIdentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html)请求的 AWS 凭证，无需对请求内容进行额外验证。保护用于授权开发人员身份验证的密钥，防止用户访问这些信息。

## 身份验证流程 API 操作概述
<a name="authentication-flow-operations"></a>

**GetId**  
[GetId](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetId.html) API 调用是在 Amazon Cognito 中建立新身份所必需的第一个调用。    
未经身份验证的访问  
Amazon Cognito 能够在您的应用程序中授权未经身份验证的访客访问。如果您的身份池中已启用此功能，用户可以随时通过 `GetId` API 请求新的身份 ID。该应用程序应缓存此身份 ID，以对 Amazon Cognito 发出后续调用。 AWS 移动设备 SDKs 和浏览器 JavaScript 中的 S AWS DK 都有凭据提供商，可以为您处理缓存。  
经过身份验证的访问  
当你将应用程序配置为支持公共登录提供商（Facebook、Google\$1、使用亚马逊登录或用苹果登录）时，用户还可以提供令牌（或 OAuth OpenID Connect），用于在这些提供商中识别他们。在对 `GetId` 的调用中使用时，Amazon Cognito 创建一个经过身份验证的新身份，或者是返回已与该特定登录关联的身份。Amazon Cognito 通过向提供商验证令牌并确保以下各项来实现此目的：  
+ 令牌有效且来自已配置的提供商。
+ 令牌未过期。
+ 令牌与使用该提供商创建的应用程序标识符（如 Facebook 应用程序 ID）匹配。
+ 令牌与用户标识符匹配。

**GetCredentialsForIdentity**  
在建立身份 ID 后，即可调用 [GetCredentialsForIdentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html) API。因此，此操作在功能上等同于调用[GetOpenIdToken](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdToken.html)。[AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html)  
要让 Amazon Cognito 代表您调用 `AssumeRoleWithWebIdentity`，您的身份池必须具有与之关联的 IAM 角色。为此，您可以使用 Amazon Cognito 控制台，也可以通过 [SetIdentityPoolRoles](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_SetIdentityPoolRoles.html) 手动操作实现此目的。

**GetOpenIdToken**  
在建立身份 ID 后，即可发出 [GetOpenIdToken](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdToken.html) API 请求。 IDs 在您第一次请求后缓存身份，然后使用启动该身份的后续基本（经典）会话`GetOpenIdToken`。  
对 `GetOpenIdToken` API 请求的响应是 Amazon Cognito 生成的令牌。您可以将此令牌作为 [AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html) 请求中的 `WebIdentityToken` 参数提交。  
在提交 OpenID 令牌之前，请在您的应用程序中进行验证。您可以使用 SDK 中的 OIDC 库或类似于 [https://github.com/awslabs/aws-jwt-verify](https://github.com/awslabs/aws-jwt-verify) 的库来确认 Amazon Cognito 颁发了令牌。OpenID 令牌的签名密钥 ID 或 `kid` 是 Amazon Cognito 身份 [jwks\$1uri 文档](https://cognito-identity.amazonaws.com/.well-known/jwks_uri)中列出的密钥之一。这些密钥可能会发生变化。验证 Amazon Cognito 身份令牌的函数应定期更新它在 *jwks\$1uri* 文档中的密钥列表。Amazon Cognito 在 *jwks\$1uri* 缓存控制响应标头中设置刷新时长，而 `max-age` 当前设置为 30 天。    
未经身份验证的访问  
要为未经身份验证的身份获取令牌，您只需身份 ID 本身。无法为经身份验证的身份或已停用的身份获取未经身份验证的令牌。  
经过身份验证的访问  
如果您有一个经过身份验证的身份，您必须为已与该身份关联的登录名传递至少一个令牌。在 `GetOpenIdToken` 调用期间，所有传入的令牌都必须通过之前提到的同一验证；如果有任何令牌失败，整个调用都会失败。`GetOpenIdToken` 调用的响应中还包括身份 ID。这是因为您传入的身份 ID 可能不是返回的那个身份 ID。  
关联登录名  
如果您为尚未与任何身份关联的登录名提交令牌，该登录名将视为已“关联”到关联身份。您只能为每个公共提供商链接一个登录名。如果尝试将多个登录名链接到一个公共提供商，将导致 `ResourceConflictException` 错误响应。如果登录名只链接到一个现有身份，则 `GetOpenIdToken` 返回的身份 ID 将与传入的相同。  
合并身份  
如果您为目前未链接到给定身份，但链接到另一身份的登录名传入令牌，这两个身份将合并。合并后，一个身份成为所有关联登录 parent/owner 名中的一个，另一个身份被禁用。在这种情况下，将返回的 parent/owner 身份 ID。如果此值不同，则必须更新本地缓存。 AWS 移动版 SDKs 或浏览器版 AWS SDK JavaScript 中的提供商会为您执行此操作。

**GetOpenIdTokenForDeveloperIdentity**  
当使用经过开发者身份验证[GetId](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetId.html)的[GetOpenIdToken](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdToken.html)身份时，该[GetOpenIdTokenForDeveloperIdentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html)操作取代了对设备的使用。由于您的应用程序使用 AWS 凭证签署此 API 操作的请求，Amazon Cognito 相信请求中提供的用户标识符有效。开发人员身份验证会替代 Amazon Cognito 对外部提供商执行的令牌验证。  
此 API 的有效载荷包括 `logins` 映射。此映射必须包含您的开发人员提供商密钥，以及作为系统中用户标识符的值。如果用户标识符尚未关联到现有身份，Amazon Cognito 会创建新的身份，并为该身份返回新身份 ID 以及 OpenID Connect 令牌。如果用户标识符已关联，Amazon Cognito 返回预先存在的身份 ID 和 OpenID Connect 令牌。 IDs在您第一次请求后缓存开发者身份，然后使用启动该身份的后续基本（经典）会话`GetOpenIdTokenForDeveloperIdentity`。  
对 `GetOpenIdTokenForDeveloperIdentity` API 请求的响应是 Amazon Cognito 生成的令牌。您可以将此令牌作为 `AssumeRoleWithWebIdentity` 请求中的 `WebIdentityToken` 参数提交。  
在提交 OpenID Connect 令牌之前，请在您的应用程序中进行验证。您可以使用 SDK 中的 OIDC 库或类似于 [https://github.com/awslabs/aws-jwt-verify](https://github.com/awslabs/aws-jwt-verify) 的库来确认 Amazon Cognito 颁发了令牌。OpenID Connect 令牌的签名密钥 ID 或 `kid` 是 Amazon Cognito 身份 [*jwks\$1uri* 文档](https://cognito-identity.amazonaws.com/.well-known/jwks_uri)中列出的密钥之一。这些密钥可能会发生变化。验证 Amazon Cognito 身份令牌的函数应定期更新它在 *jwks\$1uri* 文档中的密钥列表。Amazon Cognito 在 *jwks\$1uri* `cache-control` 响应标头中设置刷新时长，`max-age` 当前设置为 30 天。    
关联登录名  
与外部提供商一样，提供尚未与身份关联的额外登录名会将这些登录名隐式关联到该身份。如果您将一个外部提供商登录名链接到一个身份，用户可以对该提供商使用外部提供商身份验证流程。但是，他们无法在调用 `GetId` 或 `GetOpenIdToken` 时使用登录映射中的开发人员提供商名称。  
合并身份  
借助已经过开发人员验证的身份，Amazon Cognito 支持隐式合并以及通过 [MergeDeveloperIdentities](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_MergeDeveloperIdentities.html) API 进行显式合并。通过显式合并，您可以使用系统中的用户标识符将两个身份标记为单个身份。如果您提供了源和目标用户标识符，Amazon Cognito 会将其合并。您下次为任一用户标识符请求 OpenID Connect 令牌时，系统都会返回同一身份 ID。

**AssumeRoleWithWebIdentity**  
在你获得 OpenID Connect 令牌后，你可以通过 [AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html)API 请求将其换成临时 AWS 证书 AWS Security Token Service ()AWS STS。  
由于可以创建的身份数量没有限制，所以您务必要了解向用户授予的权限。为应用程序设置不同的 IAM 角色：一个用于未经身份验证的用户，一个用于经过身份验证的用户。当您首次设置身份池时，Amazon Cognito 控制台会创建默认角色。实际上没有向这些角色授予任何权限。修改这些角色以满足您的需求。  
了解有关 [角色信任和权限](iam-roles.md#role-trust-and-permissions) 的更多信息。

† 原定设置 Amazon Cognito 身份 [https://cognito-identity.amazonaws.com/.well-known/jwks_uri](https://cognito-identity.amazonaws.com/.well-known/jwks_uri) 文档包含有关在大多数 AWS 区域中用于签署身份池令牌的密钥的信息。以下区域有不同的 *jwks\$1uri* 文档。


| AWS 区域 | *jwks\$1uri* 文档的路径 | 
| --- |--- |
| AWS GovCloud （美国西部） | https://cognito-identity.us-gov-west-1.amazonaws.com/.well-known/jwks\$1uri | 
| 中国（北京） | https://cognito-identity---cn-north-1.amazonaws.com.rproxy.govskope.ca.cn/.well-known/jwks\$1uri | 
| 欧洲（米兰）和非洲（开普敦）等选择加入区域 | https://cognito-identity.Region.amazonaws.com/.well-known/jwks\$1uri | 

您还可以从颁发者推断出 *jwks\$1uri*，或者从 Amazon Cognito 推断出在 OpenID 令牌中收到的 `iss`。OIDC 标准发现端点 `<issuer>/.well-known/openid-configuration` 列出了您的令牌的 *jwks\$1uri* 的路径。