

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

# 作用域、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` 声明。