Skip to content

AppSync GraphQL APIs should not use API key authentication

API keys are static, long-lived credentials embedded in client applications. They provide no identity context, cannot enforce fine-grained authorization, and are trivially shared or leaked through source control, client-side code, or network inspection. A compromised API key grants unauthorized access to your entire GraphQL schema until manually rotated.

Stronger alternatives like AWS IAM, Cognito User Pools, OpenID Connect, or Lambda authorizers tie requests to specific identities, support token expiration, and enable per-resolver authorization logic. Removing API key authentication eliminates an entire class of credential exposure risk from your API surface.

Retrofit consideration

Switching authentication types requires updating all existing API clients. Applications currently passing an x-api-key header must be migrated to sign requests with IAM credentials, supply Cognito/OIDC tokens, or use a Lambda authorizer flow.

Implementation

Choose the approach that matches how you manage Terraform.

If you use terraform-aws-modules/appsync/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.

module "appsync" {
  source  = "terraform-aws-modules/appsync/aws"
  version = ">=3.0.0"

  authentication_type = "AWS_IAM"
  log_field_log_level = "ERROR"
  logging_enabled     = true
  name                = "pofix-abc123"
  schema              = "type Query { hello: String }"
}

Use AWS provider resources directly. See docs for the resources involved: aws_appsync_graphql_api.

resource "aws_appsync_graphql_api" "this" {
  authentication_type = "AWS_IAM"

  log_config {
    cloudwatch_logs_role_arn = "arn:aws:iam::123456789012:role/example-role"
    field_log_level          = "ERROR"
  }

  name = "pofix-abc123"
}

What this control checks

In the aws_appsync_graphql_api resource, authentication_type controls the primary auth method. The control fails when it is set to "API_KEY". Accepted values are "AWS_IAM", "AMAZON_COGNITO_USER_POOLS", "OPENID_CONNECT", and "AWS_LAMBDA".

Each additional_authentication_provider block has its own authentication_type argument, and the same check applies. If any additional provider sets authentication_type = "API_KEY", the control fails.

When using "AMAZON_COGNITO_USER_POOLS", a user_pool_config block with user_pool_id is required. For "OPENID_CONNECT", an openid_connect_config block with issuer is required. For "AWS_LAMBDA", a lambda_authorizer_config block with authorizer_uri is required.

Common pitfalls

  • Additional authentication providers also checked

    Setting the primary authentication_type to "AWS_IAM" but adding an additional_authentication_provider block with authentication_type = "API_KEY" still fails the control. Both primary and additional providers must avoid API key auth.

  • API key lifecycle confusion

    Change auth type without removing the aws_appsync_api_key Terraform resource and the API key object persists in AWS even though key auth is disabled. Terraform won't create an aws_appsync_api_key automatically when authentication_type is "API_KEY", but it won't delete one you've already declared either. Remove stale key resources explicitly when migrating auth types.

  • Resolver-level @aws_api_key directive in schema

    Even with a non-API-key primary auth type, GraphQL schemas can include @aws_api_key directives on individual resolvers when API_KEY is an additional provider. Strip API_KEY from all authentication providers without updating the schema and you'll hit resolver authorization errors.

Audit evidence

AWS Config rule evaluation results showing all aws_appsync_graphql_api resources as compliant confirm no API key authentication is in use. The AppSync console Settings page for each API shows the configured authorization mode and any additional providers; screenshots work as point-in-time evidence.

CloudTrail UpdateGraphqlApi and CreateGraphqlApi events include the authenticationType and additionalAuthenticationProviders fields, giving auditors a historical record of auth configuration changes. A CSPM compliance scan listing all AppSync APIs and their auth types is acceptable supplementary evidence.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: appsync_graphql_api_authentication_without_api_key

  • AWS Config Managed Rule: APPSYNC_AUTHORIZATION_CHECK

  • Powerpipe Control: aws_compliance.control.appsync_graphql_api_authentication_without_api_key

  • Prowler Check: appsync_graphql_api_no_api_key_authentication

  • AWS Security Hub Control: AppSync.5

Last reviewed: 2026-03-08