

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

# 将 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` 响应。用户池将所有与映射规则匹配的声明写入用户池用户配置文件中的用户属性。用户池会忽略与映射规则匹配、但不是必需且在提供者的声明中找不到的属性。