在 API Gateway 中使用 JWT 授权方控制对 HTTP API 的访问 - Amazon API Gateway

在 API Gateway 中使用 JWT 授权方控制对 HTTP API 的访问

您可以使用 JSON Web 令牌 (JWT) 作为 OpenID Connect (OIDC)OAuth 2.0 框架的一部分来限制客户端对您的 API 的访问。

如果您为 API 的路由配置 JWT 授权方,API Gateway 将验证客户端通过 API 请求提交的 JWT。API Gateway 根据令牌中的令牌验证和(可选)作用域来允许或拒绝请求。如果为路由配置作用域,则令牌必须至少包含路由的作用域之一。

您可以为 API 的每个路由配置不同的授权方,也可以为多个路由使用同一个授权方。

注意

没有标准的机制可以将 JWT 访问令牌与其他类型的 JWT(如 OpenID Connect ID 令牌)区分开来。除非您需要 ID 令牌进行 API 授权,否则我们建议您将路由配置为需要授权范围。您还可以将 JWT 授权方配置为需要相应的发布者或受众(身份提供商仅在发布 JWT 访问令牌时才使用他们)。

使用 JWT 授权方授权 API 请求

API Gateway 使用以下常规工作流程向配置为使用 JWT 授权方的路由授权请求。

  1. 检查 identitySource 是否有令牌。identitySource 只能包含令牌或前缀为 Bearer 的令牌。

  2. 对令牌解码。

  3. 使用从发布者的 jwks_uri 中提取的公有密钥检查令牌的算法和签名。目前仅支持基于 RSA 的算法。API Gateway 可以将公有密钥缓存两个小时。最佳实践是,在轮换密钥时,留出一段宽限期,在此期间旧密钥和新密钥均有效。

  4. 验证声明。API Gateway 评估以下令牌声明:

    • kid – 令牌必须具有与签署令牌的 jwks_uri 中的键匹配的标头声明。

    • iss – 必须匹配为授权方配置的 issuer

    • audclient_id – 必须匹配为授权方配置的其中一个 audience 条目。API Gateway 只有在 aud 不存在时才验证 client_id。当 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 集成发送的负载的更多信息,请参阅针对 API Gateway 中的 HTTP API 创建 AWS Lambda 代理集成

创建 JWT 授权方

在创建 JWT 授权方之前,必须向身份提供商注册客户端应用程序。您必须还创建了 HTTP API。有关创建 HTTP API 的示例,请参阅 创建 HTTP API

使用控制台创建 JWT 授权方

以下步骤说明如何使用控制台创建 JWT 授权方。

使用控制台创建 JWT 授权方
  1. 通过以下网址登录到 Amazon API Gateway 控制台:https://console.aws.amazon.com/apigateway

  2. 选择 HTTP API。

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

  4. 选择管理授权方选项卡。

  5. 选择创建

  6. 对于授权方类型,选择 JWT

  7. 配置您的 JWT 授权方,并指定用于定义令牌来源的身份来源

  8. 选择创建

使用 AWS CLI 创建 JWT 授权方

以下 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
使用 AWS CloudFormation 创建 JWT 授权方

以下 AWS CloudFormation 模板通过将 Amazon Cognito 用作身份提供者的 JWT 授权方创建 HTTP API。

AWS CloudFormation 模板的输出是 Amazon Cognito 托管用户界面的 URL,客户可以在其中注册并登录来接收 JWT。客户端登录后,会使用 URL 中的访问令牌将客户端重定向到您的 HTTP API。要使用访问令牌调用 API,请将 URL 中的 # 更改为 ?,来使用该令牌作为查询字符串参数。

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. 通过以下网址登录到 Amazon API Gateway 控制台:https://console.aws.amazon.com/apigateway

  2. 选择 HTTP API。

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

  4. 选择一个方法,然后从下拉菜单中选择您的授权方,然后选择附加授权方

使用 AWS CLI 更新路由来使用 JWT 授权方

以下命令使用 AWS CLI 更新路由来使用 JWT 授权方。

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