

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

# 使用 API Gateway 中的 JWT 授權方來控制對 HTTP API 的存取
<a name="http-api-jwt-authorizer"></a>

您可以使用 JSON Web Tokens (JWT) 做為 [OpenID Connect (OIDC)](https://openid.net/specs/openid-connect-core-1_0.html) 和 [OAuth 2.0](https://oauth.net/2/) 框架的一部分來限制用戶端存取您的 API。

如果您為 API 的路由設定 JWT 授權方，API Gateway 會驗證用戶端使用 API 請求提交的 JWT。API Gateway 會根據字符驗證，並選擇性地根據字符中的範圍，來允許或拒絕請求。如果您設定某個路由的範圍，字符至少必須包含其中一個路由的範圍。

您可以為 API 的每個路由設定不同的授權方，或為多個路由使用相同的授權方。

**注意**  
將 JWT 存取字符與其他類型的 JWT (如 OpenID Connect ID 字符) 加以區分並無標準機制。除非您需要 API 授權的 ID 字符，否則建議您將路由設定為需要授權範圍。您也可以將 JWT 授權方設定為僅在發行 JWT 存取字符時要求身分提供者使用的發行者或對象。

## 使用 JWT 授權方來授予 API 請求權限
<a name="http-api-jwt-authorizer.evaluation"></a>

API Gateway 使用下列一般工作流程來授權請求對設定為使用 JWT 授權方的路由。

1. 檢查權杖的 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-prop-authorizer-identitysource](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-prop-authorizer-identitysource)。`identitySource` 只能包含字符，或字首加上 `Bearer` 的字符。

1. 解碼字符

1. 使用從發行者的 `jwks_uri` 獲取的公開金鑰檢查字符的演算法和簽章。目前只支援以 RSA 為基礎的演算法。API Gateway 可以快取公有金鑰兩小時。最佳作法是，當您輪換金鑰時，允許寬限期，在此期間，舊金鑰和新金鑰都有效。

1. 驗證宣告。API Gateway 會評估下列權杖宣告：
   +  [https://datatracker.ietf.org/doc/html/rfc7517#section-4.5](https://datatracker.ietf.org/doc/html/rfc7517#section-4.5) – 權杖必須有符合簽署權杖之 `jwks_uri` 中金鑰的標頭宣告。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1) – 必須符合為授權方設定的 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration)。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3) 或 `client_id` – 必須符合為授權方設定的其中一個 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration) 項目。API Gateway 僅於 `aud` 不存在時驗證 `client_id`。當 `aud` 和 `client_id` 同時存在時，API Gateway 會評估 `aud`。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4) – 必須在目前時間 (以 UTC 表示) 之後。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5) – 必須在目前時間 (以 UTC 表示) 之前。
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6) – 必須在目前時間 (以 UTC 表示) 之前。
   + [https://datatracker.ietf.org/doc/html/rfc6749#section-3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) 或 `scp` – 權杖至少必須包含路由的 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid.html#apis-apiid-routes-routeid-prop-updaterouteinput-authorizationscopes](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid.html#apis-apiid-routes-routeid-prop-updaterouteinput-authorizationscopes) 的其中一個範圍。

如果上述任何步驟失敗，API Gateway 會拒絕 API 請求。

驗證 JWT 後，API Gateway 會將字符中的宣告傳遞給 API 路由的整合。後端資源 (例如 Lambda 函數) 可以存取 JWT 宣告。例如，如果 JWT 包含身分宣告 `emailID`，則可在 `$event.requestContext.authorizer.jwt.claims.emailID` 中供 Lambda 整合使用。如需 API Gateway 傳送至 Lambda 整合之承載的詳細資訊，請參閱[在 APIs AWS Lambda 代理整合](http-api-develop-integrations-lambda.md)。

## 建立一個 JWT 授權器
<a name="http-api-jwt-authorizer.create"></a>

建立 JWT 授權方之前，您必須向身分提供者註冊用戶端應用程式。您還必須建立一個 HTTP API。如需建立 HTTP API 的範例，請參閱[建立 HTTP API](http-api-develop.md#http-api-examples)。

### 使用主控台建立 JWT 授權方
<a name="http-api-jwt-authorizer.create.console"></a>

下列步驟顯示如何使用主控台建立 JWT 授權方。

**使用主控台建立 JWT 授權方**

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 選擇一個 HTTP API。

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

1. 選擇**管理授權方**標籤。

1. 選擇**建立**。

1. 對於**授權方類型**，選擇 **JWT**。

1. 設定您的 JWT 授權方，並指定定義字符來源的**身分來源**。

1. 選擇**建立**。

#### 使用 建立 JWT 授權方 AWS CLI
<a name="http-api-jwt-authorizer.create.cli"></a>

以下 [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-authorizer.html) 命令會建立 JWT 授權方。對於 `jwt-configuration`，為您的身分提供者指定 `Audience` 和 `Issuer`。如果您使用 Amazon Cognito 做為身分提供者，則 `IssuerUrl` 為 `https://cognito-idp.us-east-2.amazonaws.com/userPoolID`。

```
aws apigatewayv2 create-authorizer \
    --name authorizer-name \
    --api-id api-id \
    --authorizer-type JWT \
    --identity-source '$request.header.Authorization' \
    --jwt-configuration Audience=audience,Issuer=IssuerUrl
```

##### 使用 建立 JWT 授權方 AWS CloudFormation
<a name="http-api-jwt-cfn.create"></a>

下列 CloudFormation 範本會使用 Amazon Cognito 做為身分提供者的 JWT 授權方來建立 HTTP API。

 CloudFormation 範本的輸出是 Amazon Cognito 託管 UI 的 URL，用戶端可以在其中註冊和登入以接收 JWT。用戶端登入後，會使用 URL 中的存取字符重新導向至您的 HTTP API。若要使用存取字符調用 API，請將 URL 中的 `#` 變更為 `?`，以使用字符做為查詢字串參數。

##### 範本範例 CloudFormation
<a name="http-api-jwt-cfn-example"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: |
  Example HTTP API with a JWT authorizer. This template includes an Amazon Cognito user pool as the issuer for the JWT authorizer 
  and an Amazon Cognito app client as the audience for the authorizer. The outputs include a URL for an Amazon Cognito hosted UI where clients can 
  sign up and sign in to receive a JWT. After a client signs in, the client is redirected to your HTTP API with an access token 
  in the URL. To invoke the API with the access token, change the '#' in the URL to a '?' to use the token as a query string parameter.

Resources:
  MyAPI:
    Type: AWS::ApiGatewayV2::Api
    Properties: 
      Description: Example HTTP API
      Name: api-with-auth
      ProtocolType: HTTP
      Target: !GetAtt MyLambdaFunction.Arn
  DefaultRouteOverrides:
    Type: AWS::ApiGatewayV2::ApiGatewayManagedOverrides
    Properties: 
      ApiId: !Ref MyAPI
      Route: 
        AuthorizationType: JWT
        AuthorizerId: !Ref JWTAuthorizer
  JWTAuthorizer:
    Type: AWS::ApiGatewayV2::Authorizer
    Properties: 
      ApiId: !Ref MyAPI
      AuthorizerType: JWT
      IdentitySource: 
        - '$request.querystring.access_token'
      JwtConfiguration: 
        Audience: 
        - !Ref AppClient
        Issuer: !Sub https://cognito-idp.${AWS::Region}.amazonaws.com/${UserPool}
      Name: test-jwt-authorizer
  MyLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: nodejs18.x
      Role: !GetAtt FunctionExecutionRole.Arn
      Handler: index.handler
      Code:
        ZipFile: |
          exports.handler = async (event) => {
              const response = {
                  statusCode: 200,
                  body: JSON.stringify('Hello from the ' + event.routeKey + ' route!'),
              };
              return response;
          };
  APIInvokeLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref MyLambdaFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${MyAPI}/$default/$default
  FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17		 	 	 '
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: http-api-user-pool
      AutoVerifiedAttributes:
        - email
      Schema:
        - Name: name
          AttributeDataType: String
          Mutable: true
          Required: true
        - Name: email
          AttributeDataType: String
          Mutable: false
          Required: true
  AppClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      AllowedOAuthFlows: 
        - implicit
      AllowedOAuthScopes: 
        - aws.cognito.signin.user.admin
        - email
        - openid
        - profile
      AllowedOAuthFlowsUserPoolClient: true
      ClientName: api-app-client
      CallbackURLs:
        - !Sub https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com
      ExplicitAuthFlows:
        - ALLOW_USER_PASSWORD_AUTH
        - ALLOW_REFRESH_TOKEN_AUTH
      UserPoolId: !Ref UserPool
      SupportedIdentityProviders:
        - COGNITO 
  HostedUI:
    Type: AWS::Cognito::UserPoolDomain
    Properties: 
      Domain: !Join
        - '-'
        - - !Ref MyAPI
          - !Ref AppClient
      UserPoolId: !Ref UserPool
Outputs:
  SignupURL:
    Value: !Sub https://${HostedUI}.auth.${AWS::Region}.amazoncognito.com/login?client_id=${AppClient}&response_type=token&scope=email+profile&redirect_uri=https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com
```

## 更新路由以使用 JWT 授權方
<a name="http-api-jwt-authorizer.create.route"></a>

您可以使用 主控台 AWS CLI、 或 AWS 開發套件來更新路由，以使用 JWT 授權方。

### 使用主控台更新路由以使用 JWT 授權方
<a name="http-api-jwt-authorizer.create.route"></a>

下列步驟顯示如何使用主控台更新路由，以使用 JWT 授權方。

**使用主控台建立 JWT 授權方**

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 選擇一個 HTTP API。

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

1. 選擇一種方法，然後從下拉式選單中選取您的授權方，然後選擇**連接授權方**。

#### 使用 更新路由以使用 JWT 授權方 AWS CLI
<a name="http-api-jwt-authorizer.create.route"></a>

以下 [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) 命令會將路由更新為使用 JWT 授權方：

```
aws apigatewayv2 update-route \
   --api-id api-id  \
   --route-id route-id  \
   --authorization-type JWT \
   --authorizer-id authorizer-id \
   --authorization-scopes user.email
```