如何排查在 AWS AppSync 中运行 GraphQL 请求时出现的“Unauthorized(未授权)”错误问题?

2 分钟阅读
0

当我使用 AWS AppSync 运行 GraphQL 请求时,我收到了“Unauthorized(未授权)”错误。如何对这些错误进行问题排查?

简短描述

响应中返回的 HTTP 状态代码定义了两种未授权错误:

  • 401 Unauthorized(401 未授权):由于凭证缺失或无效,AWS AppSync 或授权模式拒绝了该请求。
  • 200 OK 响应,但出现 Unauthorized(未授权)类型错误:因问题处于或超出解析程序级别而拒绝了该请求。

要确定出现未授权错误的原因,请尝试在 Web 浏览器中重现该问题。然后,使用浏览器的网络工具捕获 HTTP 请求和响应消息,并对其进行分析以确定错误发生的位置。要进行离线分析,请以 HTTP 归档(HAR)文件格式保存消息

解决方法

401 Unauthorized(401 未授权)响应

对于 401 Unauthorized(401 未授权)响应,请检查发送 GraphQL 有效负载的网络请求,以确认:

  • 存在 Authorizationx-api-key 标头,其中包含操作或字段所需的授权模式的正确凭证。如果标头没有正确的凭证,则授权模式会拒绝该请求。
  • 对于 JSON Web 令牌(JWT),授权标头不包含文本“持有者”(来自 GitHub 网站)。
  • JWT 来自正确的 Amazon Cognito 用户群体或 OIDC 提供商。
  • 凭证有效且未过期。

200 OK 响应

对于 200 OK 响应,要详细了解导致出现“Unauthorized(未授权)”错误的原因,请启用 AWS AppSync API 上的 Amazon CloudWatch Logs。作为故障排除的最佳实践,将字段级日志记录设置为 All(全部),并包含详细内容。

在 Apache Velocity Template Language(VTL)解析程序映射模板中的逻辑拒绝接收错误类型为“Unauthorized(未授权)”以及错误消息为“Not Authorized to access X on type Y(未获得访问 Y 类别 X 的授权)”的 200 OK 响应请求。要解决此问题,请针对您使用的授权模式完成以下问题排查步骤。

Amazon Cognito 和 OIDC 授权

对比用户的令牌索取(如群组、email_verified、客户端 ID 或受众)与 VTL 解析程序映射模板中的授权检查。您可以使用第三方工具 jwt.io(来自 AuthO)来检查令牌索取。如果您使用的是 AWS Amplify,请验证令牌索取是否支持模型架构类型的授权规则要求。

例如,以下用于 Amplify 的解析程序映射模板会检查从 AWS AppSync 执行的初步授权检查中传递的数据。

#if( $util.authType() == "User Pool Authorization" )
  #if( !$isAuthorized )
    #set( $staticGroupRoles = [{"claim":"cognito:groups","entity":"Admin","allowedFields":xxxxx,yyyyy}] )
    #foreach( $groupRole in $staticGroupRoles )
      #set( $groupsInToken = $util.defaultIfNull($ctx.identity.claims.get($groupRole.claim), []) )
      #if( $groupsInToken.contains($groupRole.entity) )
        #if( $groupRole.isAuthorizedOnAllFields )
          #set( $isAuthorized = true )
          #break
        #else
          $util.qr($allowedFields.addAll($groupRole.allowedFields))
        #end
      #end
    #end
  #end
#end

此外,如果您使用的是 Amplify,请验证架构上的授权规则是否允许执行创建、读取、更新或删除操作

IAM 授权

查看适用于签署 AWS AppSync 请求的 AWS Identity and Access Management(IAM)用户或角色的策略。验证 Action(操作)块中是否为用户访问的每个字段授予 appsync:GraphQL

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "appsync:GraphQL"
      ],
      "Resource": [
        "arn:aws:appsync:us-east-1:111122223333:apis/graphql-api-id/types/Query/fields/field-1",
        "arn:aws:appsync:us-east-1:111122223333:apis/graphql-api-id/types/Mutation/fields/field-2"
      ]
    }
  ]
}

**注意:**将 graphql-api-id 替换为 GraphQL API 的 ID,并将 field-1field-2 替换为您的字段

如果您使用 Amplify 生成解析程序映射模板,请验证以下内容:

  • 颁发 IAM 凭证的角色会话名称等于 CognitoIdentityCredentials
  • IAM 凭证与 Amplify 生成的授权或未授权角色相同。

如果角色会话名称与字符串不匹配,则会拒绝对该字段或操作的访问权限。

Lambda 授权

  • 检查您在发出 isAuthorized 的 Lambda 函数代码中编写的任何自定义逻辑,以确保其设置为 true
  • 确保 deniedFields 数组不包含请求的字段或操作。
  • 检查 CloudWatch 日志或添加调试语句,以验证用于确定用户授权的逻辑流

使用多种授权模式

当您的 AWS AppSync API 具有多种授权模式时,该 API 将使用设置的默认授权模式。对于需要其他授权模式之一的类型或字段,还必须为该模式设置授权指令。有关更多信息,请参阅为 AWS AppSync GraphQL API 使用多种授权类型

例如,AWS AppSync API 将 API_KEY 设置为默认授权模式,并将 AMAZON_COGNITO_USER_POOLS 设置为其他授权模式。如果要同时使用这两种模式,则必须设置 @aws_api_key@aws_cognito_user_pools 授权指令。

type Post @aws_api_key @aws_cognito_user_pools {
 id: ID!
 author: String
 title: String
}

**注意:**默认 API_KEY 授权模式会拒绝请求,原因如下所示:

  • 在请求标头中发送 Amazon Cognito JWT。
  • GraphQL 架构中缺少这些指令。

AWS 官方
AWS 官方已更新 2 年前