

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 Amazon Cognito 使用者集區做為授權方，藉以控制對 REST API 的存取
<a name="apigateway-integrate-with-cognito"></a>

除了使用 [IAM 角色和政策](permissions.md)或 [Lambda 授權方](apigateway-use-lambda-authorizer.md) (先前稱為自訂授權方) 之外，您還可以使用 [Amazon Cognito 使用者集區](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html)來控制誰可以在 Amazon API Gateway 中存取您的 API。

若要搭配使用 Amazon Cognito 使用者集區與您的 API，您必須先建立 `COGNITO_USER_POOLS` 類型的授權方，然後設定 API 方法使用該授權方。API 部署後，用戶端必須先將使用者登入使用者集區，取得該使用者的[身分或存取字符](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)，然後透過通常會設定為請求 `Authorization` 標頭的字符其中之一來呼叫 API 方法。API 呼叫只有在您提供有效的字符時才會成功；否則，用戶端無權發出呼叫，因為用戶端沒有可獲得授權的登入資料。

身分字符是根據登入使用者宣告的身分，用來授權 API 呼叫。存取字符是根據指定的受存取保護資源的自訂範圍，用來授權 API 呼叫。如需詳細資訊，請參閱[將字符用於使用者集區](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)和[資源伺服器和自訂範圍](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-define-resource-servers.html)。

若要為您的 API 建立和設定 Amazon Cognito 使用者集區，您要執行下列任務：
+ 使用 Amazon Cognito 主控台、CLI/SDK 或 API 來建立使用者集區，或使用另一個 AWS 帳戶擁有的使用者集區。
+ 使用 API Gateway 主控台、CLI/軟體開發套件或 API 建立 API Gateway authorizer 與所選的使用者集區。
+ 使用 API Gateway 主控台、CLI/軟體開發套件或 API 在選取的 API 方法中啟用授權方。

 若要在使用者集區啟用的狀況下呼叫任何 API 方法，您的 API 用戶端要執行下列任務：
+  使用 Amazon Cognito CLI/[軟體開發套件](https://github.com/aws/amazon-cognito-identity-js/)或 API 將使用者登入至所選擇的使用者集區，並取得身分字符或存取字符。若要進一步了解如何使用 SDKs，請參閱 [Amazon Cognito AWS SDKs程式碼範例](https://docs.aws.amazon.com/cognito/latest/developerguide/service_code_examples.html)。
+  使用用戶端特定架構呼叫已部署的 API Gateway API，並在 `Authorization` 標頭中提供適當的字符。

身為 API 開發人員，您必須為您的用戶端開發人員提供使用者集區 ID、用戶端 ID，以及定義為使用者集區一部分之相關聯的用戶端密碼 (如可能)。

**注意**  
為了讓使用者使用 Amazon Cognito 登入資料登入，同時取得暫時性登入資料以使用 IAM 角色的許可，請使用 [Amazon Cognito 聯合身分](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html)。對於每個 API 資源端點 HTTP 方法，將授權類型 `Method Execution` 設定為 `AWS_IAM`。

我們會在本節中說明如何建立使用者集區、如何整合 API Gateway API 與使用者集區，以及如何呼叫與使用者集區整合的 API。

**Topics**
+ [

# 為 REST API 建立 Amazon Cognito 使用者集區
](apigateway-create-cognito-user-pool.md)
+ [

# 整合 REST API 與 Amazon Cognito 使用者集區
](apigateway-enable-cognito-user-pool.md)
+ [

# 呼叫與 Amazon Cognito 使用者集區整合的 REST API
](apigateway-invoke-api-integrated-with-cognito-user-pool.md)
+ [

# 使用 API Gateway 主控台為 REST API 設定跨帳戶的 Amazon Cognito 授權方
](apigateway-cross-account-cognito-authorizer.md)
+ [

# 使用 為 REST API 建立 Amazon Cognito 授權方 CloudFormation
](apigateway-cognito-authorizer-cfn.md)

# 為 REST API 建立 Amazon Cognito 使用者集區
<a name="apigateway-create-cognito-user-pool"></a>

整合您的 API 和使用者集區之前，您必須先在 Amazon Cognito 中建立使用者集區。您的使用者集區組態必須遵循所有 [Amazon Cognito 的資源配額](https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html)。所有使用者定義的 Amazon Cognito 變數 (例如群組、使用者和角色) 僅可使用英數字元。如需如何建立使用者集區的說明，請參閱《Amazon Cognito 開發人員指南》**中的[教學課程：建立使用者集區](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-user-pool.html)。

請記下使用者集區 ID、用戶端 ID 和任何用戶端密碼。用戶端必須將這些資訊提供給 Amazon Cognito 以讓使用者註冊使用者集區、登入使用者集區，以及取得要包含在請求中的身分或存取字符，來呼叫以使用者集區設定的 API 方法。此外，當您在 API Gateway 中將使用者集區設定為授權方時，必須指定使用者集區名稱，如下所述。

如果您使用存取字符授權 API 方法呼叫，請務必設定應用程式與使用者集區整合，以設定您想要的指定資源伺服器自訂範圍。如需將字符用於 Amazon Cognito 使用者集區的詳細資訊，請參閱[將字符用於使用者集區](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)。如需資源伺服器的詳細資訊，請參閱[為您的使用者集區定義資源伺服器](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-define-resource-servers.html)。

請記下已設定的資源伺服器識別符和自訂範圍名稱。您需要它們來建構 **OAuth Scopes (OAuth 範圍)** 的存取範圍完整名稱，這是由 `COGNITO_USER_POOLS` 授權方使用。

![\[Amazon Cognito 使用者集區資源伺服器和範圍\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/cognito-user-pool-custom-scopes-new-console.png)


# 整合 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` 授權者最多可以使用 1,000 個使用者集區。此限制無法提高。

**重要**  
執行下列任何程序之後，您需要部署或重新部署您的 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. (選用) 在**權杖驗證**欄位中輸入規則表達式，以驗證身分權杖的 `aud` (對象) 欄位，再透過 Amazon Cognito 授權請求。請注意，當使用存取字符時，由於存取字符不包含該 `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`，則無法使用點表示法。例如，下列映射表達式會將宣告的[標準欄位](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) `sub` 和 `email` 傳送到後端：

      ```
      {
      	"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 Scopes (OAuth 範圍)** 選項，API Gateway 會將提供的字符視為身分字符，並使用使用者集區中的身分來驗證宣告的身分。否則，API Gateway 會將提供的字符視為存取字符，並根據方法中宣告的授權範圍來驗證字符中宣告的存取範圍。

除了使用 API Gateway 主控台之外，您也可以指定 OpenAPI 定義檔並將 API 定義匯入 API Gateway，在方法中啟用 Amazon Cognito 使用者集區。

**使用 OpenAPI 定義檔匯入 COGNITO\$1USER\$1POOLS 授權方**

1. 為您的 API 建立 (或匯出) OpenAPI 定義檔。

1. 指定 `COGNITO_USER_POOLS` 授權方 (`MyUserPool`) JSON 定義，做為 OpenAPI 3.0 的 `securitySchemes` 部分或 Open API 2.0 的 `securityDefinitions` 部分，如下所示：

------
#### [ 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)。

# 呼叫與 Amazon Cognito 使用者集區整合的 REST API
<a name="apigateway-invoke-api-integrated-with-cognito-user-pool"></a>

若要呼叫已設定使用者集區授權方的方法，用戶端必須執行下列操作：
+ 讓使用者以使用者集區註冊。
+ 讓使用者登入使用者集區。
+ 從使用者集區取得已登入使用者的[身分或存取字符](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)。
+ 在 `Authorization` 標頭 (或您在建立授權方時指定的另一個標頭) 中包含字符。

您可以使用 [AWS Amplify]() 來執行這些任務。如需詳細資訊，請參閱[將 Amazon Cognito 與 Web 和行動應用程式整合](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-integrate-apps.html)。
+ 如果是 Android 版，請參閱 [Android 版 Amplify 入門](https://docs.amplify.aws/android/build-a-backend/auth/)。
+ 若要使用 iOS，請參閱 [iOS 版 Amplify 入門](https://docs.amplify.aws/swift/build-a-backend/auth/)。
+ 若要使用 JavaScript，請參閱 [JavaScript 版 Amplify 入門](https://docs.amplify.aws/javascript/build-a-backend/auth/)。

# 使用 API Gateway 主控台為 REST API 設定跨帳戶的 Amazon Cognito 授權方
<a name="apigateway-cross-account-cognito-authorizer"></a>

您現在可以使用來自不同 AWS 帳戶的 Amazon Cognito 使用者集區做為您的 API 授權方。Amazon Cognito 使用者集區可以使用承載字符身分驗證政策，例如 OAuth 或 SAML。這可讓您輕鬆集中管理並跨多個 API Gateway API 共用一個中央 Amazon Cognito 使用者集區授權方。

在本節中，我們示範如何使用 Amazon API Gateway 主控台設定跨帳戶的 Amazon Cognito 使用者集區。

這些指示假設您在一個 AWS 帳戶中已有 API Gateway API，而另一個帳戶中已有 Amazon Cognito 使用者集區。

## 為 REST API 設定跨帳戶 Amazon Cognito 授權方
<a name="apigateway-configure-cross-account-cognito-authorizer"></a>

在您 API 所在的帳戶中，登入 Amazon API Gateway 主控台，然後執行下列操作：

1. 在 API Gateway 中建立新的 API 或選取現有的 API。

1. 在主導覽窗格中，選擇**授權方**。

1. 選擇**建立授權方**。

1. 若要設定新的授權方使用使用者集區，請執行下列操作：

   1.  針對**授權方名稱**，輸入名稱。

   1. 針對**授權方類型**，選取 **Cognito**。

   1. 針對 **Cognito 使用者集區**，輸入您在第二個帳戶中擁有之使用者集區的完整 ARN。
**注意**  
在 Amazon Cognito 主控台中，您可以在 **General Settings (一般設定)** 窗格的 **Pool ARN (集區 ARN)** 欄位中找到適用於您使用者集區的 ARN。

   1.  針對**權杖來源**，輸入 **Authorization** 作為標頭名稱，以在使用者成功登入時，傳遞 Amazon Cognito 傳回的身分或存取權杖。

   1. (選用) 在**權杖驗證**欄位中輸入規則表達式，以驗證身分權杖的 `aud` (對象) 欄位，再透過 Amazon Cognito 授權請求。請注意，當使用存取字符時，由於存取字符不包含該 `aud` 字段，所以此驗證拒絕該請求。

   1. 選擇**建立授權方**。

# 使用 為 REST API 建立 Amazon Cognito 授權方 CloudFormation
<a name="apigateway-cognito-authorizer-cfn"></a>

您可以使用 CloudFormation 建立 Amazon Cognito 使用者集區和 Amazon Cognito 授權方。範本範例 CloudFormation 會執行下列動作：
+ 建立 Amazon Cognito 使用者集區。用戶端必須先將使用者登入使用者集區，並取得[身分或存取字符](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)。如果您使用存取字符授權 API 方法呼叫，請務必設定應用程式與使用者集區整合，以設定您想要的指定資源伺服器自訂範圍。
+ 使用 `GET` 方法建立 API Gateway API。
+ 建立使用 `Authorization` 標頭作為字符來源的 Amazon Cognito 授權方。

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      AccountRecoverySetting:
        RecoveryMechanisms:
          - Name: verified_phone_number
            Priority: 1
          - Name: verified_email
            Priority: 2
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: true
      EmailVerificationMessage: The verification code to your new account is {####}
      EmailVerificationSubject: Verify your new account
      SmsVerificationMessage: The verification code to your new account is {####}
      VerificationMessageTemplate:
        DefaultEmailOption: CONFIRM_WITH_CODE
        EmailMessage: The verification code to your new account is {####}
        EmailSubject: Verify your new account
        SmsMessage: The verification code to your new account is {####}
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
  CogAuthorizer:
    Type: AWS::ApiGateway::Authorizer
    Properties:
      Name: CognitoAuthorizer
      RestApiId:
        Ref: Api
      Type: COGNITO_USER_POOLS
      IdentitySource: method.request.header.Authorization
      ProviderARNs:
        - Fn::GetAtt:
            - UserPool
            - Arn
  Api:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: MyCogAuthApi
  ApiDeployment:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId:
        Ref: Api
    DependsOn:
      - CogAuthorizer
      - ApiGET
  ApiDeploymentStageprod:
    Type: AWS::ApiGateway::Stage
    Properties:
      RestApiId:
        Ref: Api
      DeploymentId:
        Ref: ApiDeployment
      StageName: prod
  ApiGET:
    Type: AWS::ApiGateway::Method
    Properties:
      HttpMethod: GET
      ResourceId:
        Fn::GetAtt:
          - Api
          - RootResourceId
      RestApiId:
        Ref: Api
      AuthorizationType: COGNITO_USER_POOLS
      AuthorizerId:
        Ref: CogAuthorizer
      Integration:
        IntegrationHttpMethod: GET
        Type: HTTP_PROXY
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
Outputs:
  ApiEndpoint:
    Value:
      Fn::Join:
        - ""
        - - https://
          - Ref: Api
          - .execute-api.
          - Ref: AWS::Region
          - "."
          - Ref: AWS::URLSuffix
          - /
          - Ref: ApiDeploymentStageprod
          - /
```