将 REST API 与 Amazon Cognito 用户池集成 - Amazon API Gateway
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

将 REST API 与 Amazon Cognito 用户池集成

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

注意

您可以使用 CreateAuthorizer 操作来创建使用多个用户池的 COGNITO_USER_POOLS 授权方。一个 COGNITO_USER_POOLS 授权方最多可以使用 1000 个用户池。不能提高此限制。

重要

在执行以下任意步骤之后,您都需要部署或重新部署 API 以便传播更改。有关部署 API 的更多信息,请参阅在 Amazon API Gateway 中部署 REST API

使用 API Gateway 控制台创建 COGNITO_USER_POOLS 授权方
  1. 在 API Gateway 中创建新的 API 或选择现有 API。

  2. 在主导航窗格中,选择授权方

  3. 选择 Create Authorizer(创建授权方)。

  4. 要配置新的授权方来使用用户池,请执行以下操作:

    1. 授权方名称中,输入名称。

    2. 对于授权方类型,请选择 Cognito

    3. 对于 Cognito 用户群体,请选择您创建 Amazon Cognito 的 Amazon Web Services 区域并选择可用的用户群体。

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

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

    6. 选择 Create Authorizer(创建授权方)。

  5. 创建了 COGNITO_USER_POOLS 授权方之后,您可以通过提供从用户池预置的身份验证令牌来对其进行测试调用。您可以通过调用 Amazon Cognito 身份开发工具包来获取此身份令牌以执行用户登录。您也可以使用 InitiateAuth 操作。如果您未配置任何授权范围,API Gateway 会将提供的令牌视为身份令牌。

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

在方法上配置 COGNITO_USER_POOLS 授权方
  1. 选择资源。选择新方法或选择现有方法。如有必要,请创建资源。

  2. 方法请求选项卡上的方法请求设置下,选择编辑

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

  4. 要使用身份令牌,请执行以下操作:

    1. 授权范围保留为空。

    2. 如果需要,在集成请求中,在正文映射模板中添加 $context.authorizer.claims['property-name']$context.authorizer.claims.property-name 表达式,从而将指定的身份声明属性从用户群体传递到后端。对于简单的属性名称,例如 subcustom-sub,两种表示法相同。对于复杂的属性名称,例如 custom:role,不能使用点表示法。例如,以下映射表达式会将声明的 subemail标准字段传递到后端:

      { "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']" } }
  5. 要使用访问令牌,请执行以下操作:

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

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

    2. 选择 Save(保存)。

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

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

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

用 OpenAPI 定义文件导入 COGNITO_USER_POOLS 授权方
  1. 为您的 API 创建(或导出)一个 OpenAPI 定义文件。

  2. 作为 OpenAPI 3.0 中的 securitySchemes 部分或 Open API 2.0 中的 securityDefinitions 部分,指定 COGNITO_USER_POOLS 授权方 (MyUserPool) 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}" ] } }
  3. 要将身份令牌用于方法授权,请将 { "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" } }, ... }
  4. 要为方法授权使用访问令牌,请将以上安全定义更改为 { "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" } }, ... }
  5. 如果需要,您可以使用合适的 OpenAPI 定义或扩展来设置其他 API 配置设置。有关更多信息,请参阅使用基于 OpenAPI 的 API Gateway 扩展