使用 JWT 授權者控制對 HTTP API 的存取 - Amazon API Gateway

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

使用 JWT 授權者控制對 HTTP API 的存取

您可以使用 JSON Web Tokens (JWT) 做為 OpenID Connect (OIDC)OAuth 2.0 框架的一部分來限制用戶端存取您的 API。

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

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

注意

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

使用 JWT 授權者授權 API 請求

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

  1. 檢查權杖的 identitySourceidentitySource 只能包含字符,或字首加上 Bearer 的字符。

  2. 解碼字符

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

  4. 驗證宣告。API Gateway 會評估下列權杖宣告:

    • kid – 權杖必須有符合簽署權杖之 jwks_uri 中金鑰的標頭宣告。

    • iss – 必須符合為授權方設定的 issuer

    • audclient_id – 必須符合為授權方設定的其中一個 audience 項目。只有在不存在的情況下client_idaud會驗證 API Gateway。當audclient_id都存在時,API Gateway 會評估aud

    • exp – 必須在目前時間 (以 UTC 表示) 之後。

    • nbf – 必須在目前時間 (以 UTC 表示) 之前。

    • iat – 必須在目前時間 (以 UTC 表示) 之前。

    • scopescp – 權杖至少必須包含路由的 authorizationScopes 的其中一個範圍。

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

驗證 JWT 後,API Gateway 會將字符中的宣告傳遞給 API 路由的整合。後端資源 (例如 Lambda 函數) 可以存取 JWT 宣告。例如,如果 JWT 包含身分宣告 emailID,則可在 $event.requestContext.authorizer.jwt.claims.emailID 中供 Lambda 整合使用。如需 API Gateway 傳送至 Lambda 整合之承載的詳細資訊,請參閱為 HTTP API 建立 AWS Lambda 代理伺服器整合

建立一個 JWT 授權器

建立 JWT 授權方之前,您必須向身分提供者註冊用戶端應用程式。您還必須建立一個 HTTP API。如需建立 HTTP API 的範例,請參閱創建一個 HTTP API

使用控制台創建 JWT 授權者

下面的步驟演示了如何使用控制台創建 JWT 授權者。

若要使用主控台建立 JWT 授權者
  1. 在以下網址登入 API Gateway 主控台:https://console.aws.amazon.com/apigateway

  2. 選擇一個 HTTP API。

  3. 在主導覽窗格中,選擇 [授權]。

  4. 選擇 [管理授權者] 索引標籤。

  5. 選擇建立

  6. 針對「授權者」類型,選擇「J WT」。

  7. 設定您的 JWT 授權者,並指定定義權杖來源的身分識別來源。

  8. 選擇建立

使用建立 JWT 授權者 AWS CLI

下面的 AWS CLI 命令創建一個 JWT 授權者。對於 jwt-configuration,為您的身分提供者指定 AudienceIssuer。如果您使用 Amazon Cognito 做為身分識別提供者,則IssuerUrlhttps://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

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

AWS CloudFormation 範本的輸出是 Amazon Cognito 託管使用者介面的 URL,用戶端可以在其中註冊並登入以接收 JWT。客戶端登錄後,客戶端將使用 URL 中的訪問令牌重定向到您的 HTTP API。要使用訪問令牌調用 API,請將 URL # 中的更改為 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 授權者

您可以使用控制台 AWS CLI、或 AWS SDK 更新路由以使用 JWT 授權者。

使用控制台更新路由以使用 JWT 授權者

下面的步驟演示了如何更新路由使用控制台使用 JWT 授權者。

若要使用主控台建立 JWT 授權者
  1. 在以下網址登入 API Gateway 主控台:https://console.aws.amazon.com/apigateway

  2. 選擇一個 HTTP API。

  3. 在主導覽窗格中,選擇 [授權]。

  4. 選擇方法,然後從下拉式功能表中選取您的授權者,然後選擇 [附加授權者]。

更新路由以使用 JWT 授權者 AWS CLI

下面的命令更新使用 JWT 授權者的路由。 AWS CLI

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