

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

# SAML 会话在 Amazon Cognito 用户池中启动
<a name="cognito-user-pools-SAML-session-initiation"></a>

亚马逊 Cognito 支持服务提供商发起 (SP-initiated) 单点登录 (SSO) 和 SSO。 IdP-initiated 作为最佳安全实践，请在用户池中实施 SP-initiated SSO。[SAML V2.0 技术概述的第 5.1.2 节](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)描述了 SP-initiated SSO。Amazon Cognito 是您的应用程序的身份提供者 (IdP)。该应用程序是为经过身份验证的用户检索令牌的服务提供程序 (SP)。但是，当您使用第三方 IdP 对用户进行身份验证时，Amazon Cognito 就是 SP。当您的 SAML 2.0 用户使用 SP-initiated 流程进行身份验证时，他们必须始终首先向 Amazon Cognito 提出请求并重定向到 IdP 进行身份验证。

对于某些企业使用案例，对内部应用程序的访问从企业 IdP 托管的控制面板上的书签开始。当用户选择书签时，IdP 会生成一个 SAML 响应并将其发送到 SP 以向应用程序验证用户身份。

您可以在用户池中配置 SAML IdP 以支持 IdP-initiated SSO。当您支持 IdP-initiated 身份验证时，亚马逊 Cognito 无法验证它是否已请求收到的 SAML 响应，因为亚马逊 Cognito 不会通过 SAML 请求启动身份验证。在 SP-initiated SSO 中，Amazon Cognito 设置了状态参数，用于验证针对原始请求的 SAML 响应。通过 SP-initiated 登录，您还可以防范跨站请求伪造 (CSRF)。

**Topics**
+ [实现 SP-initated SAML 登录](#cognito-user-pools-saml-idp-authentication)
+ [实现 IdP-initiated SAML 登录](#cognito-user-pools-SAML-session-initiation-idp-initiation)

## 实现 SP-initated SAML 登录
<a name="cognito-user-pools-saml-idp-authentication"></a>

最佳做法是实施服务提供商发起 (SP-initiated) 登录用户池。Amazon Cognito 会启动用户的会话并将他们重定向到您的 IdP。使用这种方法，您可以更大限度地控制谁提出登录请求。您还可以在某些条件下允许 IdP-initiated 登录。

以下过程显示用户如何通过 SAML 提供商完成对用户池的 SP-initiated 登录。

![亚马逊 Cognito SP-initiated SAML 登录的身份验证流程图。](https://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 Web 令牌（JWT）。

1. 应用程序接受并处理用户的 ID 令牌作为身份验证，使用其访问令牌生成对资源的授权请求，并存储他们的刷新令牌。

当用户进行身份验证并接收授权码授予时，用户池会返回 ID 令牌、访问令牌和刷新令牌。ID 令牌是用于身份管理的 OIDC-based 身份验证对象。访问令牌是具有 [OAuth 2.0 范围](https://oauth.net/2/)的授权对象。刷新令牌是在用户当前令牌到期时生成新 ID 令牌和访问令牌的对象。您可以在用户池应用程序客户端中配置用户令牌的持续时间。

您还可以选择刷新令牌的持续时间。用户的刷新令牌到期后，他们必须重新登录。如果他们通过 SAML IdP 进行身份验证，则用户的会话持续时间由其令牌的到期时间，而不是他们与 IdP 的会话到期时间来设置。您的应用程序必须存储每位用户的刷新令牌，并在刷新令牌到期时更新他们的会话。托管登录会在浏览器的 Cookie 中维持用户的会话，这个 Cookie 的有效期为 1 小时。

## 实现 IdP-initiated SAML 登录
<a name="cognito-user-pools-SAML-session-initiation-idp-initiation"></a>

当您为 IdP-initiated SAML 2.0 登录配置身份提供商时，您可以向用户池域中的`saml2/idpresponse`终端节点提供 SAML 断言，而无需在上启动会话。[对端点授权](authorization-endpoint.md)具有此配置的用户池接受来自所请求应用程序客户端支持的用户池外部身份提供商的 IdP-initiated SAML 断言。

![亚马逊 Cognito IdP-initiated SAML 登录的身份验证流程图。](https://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 Web 令牌（JWT）。

1. 应用程序接受并处理用户的 ID 令牌作为身份验证，使用其访问令牌生成对资源的授权请求，并存储他们的刷新令牌。

以下步骤描述了 IdP-initiated SAML 2.0 提供商配置和登录的整个过程。

1. 创建或指定用户池和应用程序客户端。

1. 在您的用户池中创建 SAML 2.0 IdP。

1. 配置您的 IdP 以支持 IdP 启动。 IdP-initiated SAML 引入了其他 SSO 提供商不受约束的安全注意事项。因此，您无法将非 SAML IdPs（包括用户池本身）添加到任何使用 SAML 提供商登录的应用程序客户端。 IdP-initiated 

1. 将您的 IdP-initiated SAML 提供商与用户池中的应用程序客户端相关联。

1. 将您的用户引导至 SAML IdP 的登录页面并检索 SAML 断言。

1. 使用 SAML 断言将用户引导至用户池 `saml2/idpresponse` 端点。

1. 接收 JSON Web 令牌（JWT）。

要在用户池中接受未经请求的 SAML 断言，必须考虑其对应用程序安全性的影响。当您接受请求时，可能会出现请求欺骗和 CSRF 尝试。 IdP-initiated 尽管您的用户池无法验证 IdP-initiated 登录会话，但 Amazon Cognito 会验证您的请求参数和 SAML 断言。

此外，SAML 声明不得包含 `InResponseTo` 声明，并且必须在前 6 分钟内发出。

您必须使用 IdP-initiated SAML 向您`/saml2/idpresponse`提交请求。对于 SP-initiated 和管理登录授权请求，您必须提供用于标识所请求的应用程序客户端、范围、重定向 URI 和其他详细信息的参数，作为`HTTP GET`请求中的查询字符串参数。但是，对于 IdP-initiated SAML 断言，请求的详细信息必须格式化为请求正文中的`RelayState`参数。`HTTP POST`请求正文还必须包含您的 SAML 断言，作为 `SAMLResponse` 参数。

以下是 IdP-initiated 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%3D{{MySAMLIdP}}%26client_id%3D{{1example23456789}}%26redirect_uri%3D{{https%3A%2F%2Fwww.example.com}}%26response_type%3D{{code}}%26scope%3D{{email%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 管理控制台 ]

**为 SAML 配置 Id IdP-initiated P**

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-initiated SAML 登录下**，选择**接受 SP-initiated 和和 IdP-initiated SAML 断言。**

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

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

**为 SAML 配置 Id IdP-initiated P **

使用[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-initiated SAML。以下是支持 IdP-initiated SAM `ProviderDetails` L 的 IdP 示例。

```
"ProviderDetails": { 
      "MetadataURL" : "{{https://myidp.example.com/saml/metadata}}",
      "IDPSignout" : "true",
      "RequestSigningAlgorithm" : "rsa-sha256",
      "EncryptedResponses" : "true",
      "IDPInit" : "true"
}
```

------