

# 将 REST API 与 Amazon Cognito 用户池集成
<a name="apigateway-enable-cognito-user-pool"></a>

创建 Amazon Cognito 用户池后，您必须在 API Gateway 中创建一个使用该用户池的 `COGNITO_USER_POOLS` 授权方。以下过程介绍如何使用 API Gateway 控制台执行此操作。

**注意**  
您可以使用 [https://docs.aws.amazon.com/apigateway/latest/api/API_CreateAuthorizer.html](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateAuthorizer.html) 操作来创建使用多个用户池的 `COGNITO_USER_POOLS` 授权方。一个 `COGNITO_USER_POOLS` 授权方最多可以使用 1000 个用户池。不能提高此限制。

**重要**  
在执行以下任意步骤之后，您都需要部署或重新部署 API 以便传播更改。有关部署 API 的更多信息，请参阅[在 API Gateway 中部署 REST API。](how-to-deploy-api.md)。

**使用 API Gateway 控制台创建 `COGNITO_USER_POOLS` 授权方**

1. 在 API Gateway 中创建新的 API 或选择现有 API。

1. 在主导航窗格中，选择**授权方**。

1. 选择**创建授权方**。

1. 要配置新的授权方来使用用户池，请执行以下操作：

   1.  在**授权方名称**中，输入名称。

   1. 对于**授权方类型**，请选择 **Cognito**。

   1. 对于 **Cognito 用户群体**，请选择您创建 Amazon Cognito 的 AWS 区域并选择可用的用户群体。

      您可以使用阶段变量来定义用户池。对用户池使用以下格式：`arn:aws:cognito-idp:us-east-2:111122223333:userpool/${stageVariables.MyUserPool}`。

   1.  对于**令牌来源**，输入 **Authorization** 作为标头名称，以在用户成功登录时传递 Amazon Cognito 所返回的身份令牌或访问令牌。

   1. （可选）在**令牌验证**字段中输入一个正则表达式，以在使用 Amazon Cognito 对请求进行授权之前，验证身份令牌的 `aud`（受众）字段。请注意，在使用访问令牌时，由于访问令牌不包含 `aud` 字段，此验证将拒绝请求。

   1. 选择**创建授权方**。

1. 创建 `COGNITO_USER_POOLS` 授权方之后，您可以通过提供从用户池预置的身份验证令牌来对其进行测试调用。您不能使用访问令牌来对授权方进行测试调用。

   您可以通过调用 [Amazon Cognito 身份开发工具包](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-integrate-apps.html)来获取此身份令牌以执行用户登录。您也可以使用 [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 Gateway 会将提供的令牌视为身份令牌。

上述过程创建使用新创建的 Amazon Cognito 用户池的 `COGNITO_USER_POOLS` 授权方。根据在 API 方法上启用授权方的方法，您可以使用从集成用户池预置的身份令牌或访问令牌。

**在方法上配置 `COGNITO_USER_POOLS` 授权方**

1. 选择**资源**。选择新方法或选择现有方法。如有必要，请创建资源。

1. 在**方法请求**选项卡上的**方法请求设置**下，选择**编辑**。

1. 对于**授权方**，从下拉菜单中选择您刚刚创建的 **Amazon Cognito 用户群体授权方**。

1.  要使用身份令牌，请执行以下操作：

   1. 将**授权范围**保留为空。

   1. 如果需要，在**集成请求**中，在正文映射模板中添加 `$context.authorizer.claims['property-name']` 或 `$context.authorizer.claims.property-name` 表达式，从而将指定的身份声明属性从用户群体传递到后端。对于简单的属性名称，例如 `sub` 或 `custom-sub`，两种表示法相同。对于复杂的属性名称，例如 `custom:role`，不能使用点表示法。例如，以下映射表达式会将声明的 `sub` 和 `email` 的[标准字段](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)传递到后端：

      ```
      {
      	"context" : {
      		"sub" : "$context.authorizer.claims.sub",
      		"email" : "$context.authorizer.claims.email"
      	}
      }
      ```

      如果您在配置用户池时声明了自定义声明字段，那么您可以用同样的方式来访问自定义字段。以下示例获取的是声明的自定义 `role` 字段：

      ```
      {
      	"context" : {
      		"role" : "$context.authorizer.claims.role"
          }
      }
      ```

      如果自定义声明字段被声明为 `custom:role`，可以使用以下示例来获取声明的属性：

      ```
      {
      	"context" : {
      		"role" : "$context.authorizer.claims['custom:role']"
          }
      }
      ```

1.  要使用访问令牌，请执行以下操作：

   1. 对于**授权范围**，输入某个范围的一个或多个全名，该范围在创建 Amazon Cognito 用户池时已配置。例如，根据 [为 REST API 创建 Amazon Cognito 授权用户池](apigateway-create-cognito-user-pool.md) 中给出的示例，其中一个范围是 `https://my-petstore-api.example.com/cats.read`。

      在运行时，如果在此步骤的方法上指定的任何范围与在传入令牌中声明的范围匹配，则方法调用成功。否则，调用失败并出现 `401 Unauthorized` 响应。

   1.  选择**保存**。

1. 对您选择的其他方法重复这些步骤。

使用 `COGNITO_USER_POOLS` 授权方，如果未指定 **OAuth 范围**选项，则 API Gateway 将提供的令牌视为身份令牌，并根据来自用户池的身份之一验证所声明的身份。否则，API Gateway 将提供的令牌视为访问令牌，并根据在方法上声明的授权范围，验证在令牌中所声明的访问范围。

除了使用 API Gateway 控制台之外，您还可以指定 OpenAPI 定义文件并将 API 定义导入到 API Gateway，从而在方法上启用 Amazon Cognito 用户池。

**用 OpenAPI 定义文件导入 COGNITO\$1USER\$1POOLS 授权方**

1. 为您的 API 创建（或导出）一个 OpenAPI 定义文件。

1. 作为 OpenAPI 3.0 中的 `COGNITO_USER_POOLS` 部分或 Open API 2.0 中的 `MyUserPool` 部分，指定 `securitySchemes` 授权方 (`securityDefinitions`) JSON 定义，如下所示：

------
#### [ OpenAPI 3.0 ]

   ```
     "securitySchemes": {
       "MyUserPool": {
         "type": "apiKey",
         "name": "Authorization",
         "in": "header",
         "x-amazon-apigateway-authtype": "cognito_user_pools",
         "x-amazon-apigateway-authorizer": {
           "type": "cognito_user_pools",
           "providerARNs": [
             "arn:aws:cognito-idp:{region}:{account_id}:userpool/{user_pool_id}"
           ]
         }
       }
   ```

------
#### [ OpenAPI 2.0 ]

   ```
     "securityDefinitions": {
       "MyUserPool": {
         "type": "apiKey",
         "name": "Authorization",
         "in": "header",
         "x-amazon-apigateway-authtype": "cognito_user_pools",
         "x-amazon-apigateway-authorizer": {
           "type": "cognito_user_pools",
           "providerARNs": [
             "arn:aws:cognito-idp:{region}:{account_id}:userpool/{user_pool_id}"
           ]
         }
       }
   ```

------

1. 要将身份令牌用于方法授权，请将 `{ "MyUserPool": [] }` 添加到方法的 `security` 定义，如根资源上的以下 GET 方法所示。

   ```
     "paths": {
       "/": {
         "get": {
           "consumes": [
             "application/json"
           ],
           "produces": [
             "text/html"
           ],
           "responses": {
             "200": {
               "description": "200 response",
               "headers": {
                 "Content-Type": {
                   "type": "string"
                 }
               }
             }
           },
           "security": [
             {
               "MyUserPool": []
             }
           ],        
           "x-amazon-apigateway-integration": {
             "type": "mock",
             "responses": {
               "default": {
                 "statusCode": "200",
                 "responseParameters": {
                   "method.response.header.Content-Type": "'text/html'"
                 },
               }
             },
             "requestTemplates": {
               "application/json": "{\"statusCode\": 200}"
             },
             "passthroughBehavior": "when_no_match"
           }
         },
         ...
      }
   ```

1.  要为方法授权使用访问令牌，请将以上安全定义更改为 `{ "MyUserPool": [resource-server/scope, ...] }`：

   ```
     "paths": {
       "/": {
         "get": {
           "consumes": [
             "application/json"
           ],
           "produces": [
             "text/html"
           ],
           "responses": {
             "200": {
               "description": "200 response",
               "headers": {
                 "Content-Type": {
                   "type": "string"
                 }
               }
             }
           },
           "security": [
             {
               "MyUserPool": ["https://my-petstore-api.example.com/cats.read", "http://my.resource.com/file.read"]
             }
           ],        
           "x-amazon-apigateway-integration": {
             "type": "mock",
             "responses": {
               "default": {
                 "statusCode": "200",
                 "responseParameters": {
                   "method.response.header.Content-Type": "'text/html'"
                 },
               }
             },
             "requestTemplates": {
               "application/json": "{\"statusCode\": 200}"
             },
             "passthroughBehavior": "when_no_match"
           }
         },
         ...
      }
   ```

1. 如果需要，您可以使用合适的 OpenAPI 定义或扩展来设置其他 API 配置设置。有关更多信息，请参阅 [适用于 API Gateway 的 OpenAPI 扩展](api-gateway-swagger-extensions.md)。