How do I troubleshoot "Unauthorized" errors when running GraphQL requests in AWS AppSync?

5 minute read

I receive "Unauthorized" errors when I run GraphQL requests with AWS AppSync. How do I troubleshoot these errors?

Short description

There are two types of unauthorized errors that are defined by the HTTP status code that's returned in the response:

  • 401 Unauthorized: The request is denied by either AWS AppSync or the authorization mode because the credentials are missing or invalid.
  • 200 OK response with an Unauthorized type error: The request is denied because of an issue at or beyond the resolver level.

To determine the cause of the unauthorized error, try to reproduce the issue in a web browser. Then, use the browser's network tools to capture the HTTP request and response messages. Analyze the messages to determine where the error occurred. To analyze them offline, save the messages in an HTTP Archive (HAR) file.


401 Unauthorized response

For a 401 Unauthorized response, check the network request that sends the GraphQL payload to confirm that:

  • The Authorization or x-api-key header is present and contains the correct credentials for the authorization mode that the operation or field requires. If the header doesn't have the correct credentials, then the authorization mode rejects the request.
  • For JSON Web Tokens (JWT), the Authorization header doesn't include the text "Bearer" (from the GitHub website).
  • The JWT is from the correct Amazon Cognito user pool or OIDC provider.
  • The credentials are valid and not expired.

200 OK response

To get more details on what causes Unauthorized errors for a 200 OK response, turn on Amazon CloudWatch logs on the AWS AppSync API. As a best practice for troubleshooting, set the field-level logging to All, and include verbose content.

Requests that receive a 200 OK response with error type Unauthorized and message Not Authorized to access X on type Y are denied by logic in the Apache Velocity Template Language (VTL) resolver mapping templates. To resolve this issue, complete the following troubleshooting steps for the authorization mode that you use.

Amazon Cognito and OIDC authorization

Compare the user's token claims, such as groups, email_verified, and client ID or audience, with the authorization checks in the VTL resolver mapping templates. You can use the third-party tool (from AuthO) to check the token claims. If you're using AWS Amplify, then verify that the token claims support the authorization rule requirements on the model schema type.

For example, the following resolver mapping template for Amplify checks the data that's passed from the preliminary authorization check that AWS AppSync does.

#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($$groupRole.claim), []) )
      #if( $groupsInToken.contains($groupRole.entity) )
        #if( $groupRole.isAuthorizedOnAllFields )
          #set( $isAuthorized = true )

Also, if you're using Amplify, verify that the authorization rules on the schema allow create, read, update, or delete operations.

IAM authorization

Review the policies that are applied to the AWS Identity and Access Management (IAM) user or role that signs the request to AWS AppSync. Verify that appsync:GraphQL is granted in the Action block for each of the fields that the user accesses.

  "Version": "2012-10-17",
  "Statement": [
      "Effect": "Allow",
      "Action": [
      "Resource": [

Note: Replace graphql-api-id with the ID of your GraphQL API and field-1 and field-2 with your fields.

If you're using Amplify to generate the resolver mapping templates, then verify the following:

  • The role session name that the IAM credentials are issued with equals CognitoIdentityCredentials.
  • The IAM credentials are the same as the auth or unauth role that Amplify generates.

If the role session name doesn't match the string, then access to the field or operation is denied.

Lambda authorization

  • Check any custom logic that you wrote in the Lambda function code where isAuthorized is issued to make sure that it's set to true.
  • Make sure that the deniedFields array doesn't contain the requested field or operation.
  • Check the CloudWatch logs, or add debugging statements, to verify the logic flow for determining user authorization.

Using multiple authorization modes

When your AWS AppSync API has multiple authorization modes, the API uses the default authorization mode that's set. For a type or field that requires one of the other authorization modes, you must also set an authorization directive for that mode. For more information see, Using multiple authorization types with AWS AppSync GraphQL APIs.

For example, an AWS AppSync API has API_KEY set as the default authorization mode and has AMAZON_COGNITO_USER_POOLS as an additional authorization mode. If you want to use both modes, then you must set the @aws_api_key and @aws_cognito_user_pools authorization directives.

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

Note: The default API_KEY authorization mode rejects requests for the following reasons:

  • An Amazon Cognito JWT is sent in the request header.
  • The directives are missing on the GraphQL schema.

AWS OFFICIALUpdated 8 months ago