Skip to main content
emnode / learn
Compliance

Require authentication on data and API services

One capability across API Gateway, AppSync, MSK, ElastiCache and DMS: make sure every data and API service proves who is calling before it answers, rather than trusting the network or a shared secret.

13 min·10 sections·AWS

Last reviewed

Remediates AWS Security Hub: APIGateway.8AppSync.5DMS.11ElastiCache.6MSK.6

Requiring authentication: the basics

What does it mean for a service to authenticate its callers?

Authentication is the question who are you, answered before a service does anything. Several AWS services let you skip that question, and each does so in its own shape: an API Gateway route with authorizationType set to NONE, an AppSync GraphQL API guarded only by a shared API key, an MSK Kafka cluster that accepts unauthenticated clients, a pre-6.0 ElastiCache Redis replication group with no AUTH token, a DMS MongoDB endpoint with AuthType set to no. Different services, different fields, one weakness: the service answers without knowing who asked.

AWS Security Hub turns each of these into its own control, so one estate can fail several at once. APIGateway.8 covers routes with no authorization type; AppSync.5 covers GraphQL APIs on API-key auth; MSK.6 covers clusters with unauthenticated access enabled; ElastiCache.6 covers older Redis groups without an AUTH token; DMS.11 covers MongoDB migration endpoints with authentication off. They read as separate findings, but they are one capability: require the caller to prove identity, with a mechanism tied to a real principal rather than to possession of a string or to network reachability.

The trap that runs through all of them is conflating network position with authentication. Network reachability controls who can knock on the door; authentication controls who is allowed in. A cluster that is only reachable inside a VPC still answers anyone inside that VPC, and a peering connection, a new VPN route or a compromised host turns reachability into access. These controls exist because reachability and identity get confused constantly, and the gap only surfaces after someone has already walked through.

In this lesson you will learn how AWS services express unauthenticated access across APIs, GraphQL, streaming, caching and migration, how to find every service answering anonymous callers, and how to require authentication without dropping the live producers, consumers and clients that depend on them. The Controls this lesson covers section lists every Security Hub control in this capability, each linking to a deep page with the exact check and a copy-and-paste fix.

Fun fact

The cluster that was internal only

A common pattern in incident reviews: a team stands up a data service, an MSK cluster or a Redis cache, with no authentication because it is only reachable inside the VPC, so it is fine. Months later a peering connection, a new VPN route or a compromised application host inside the same VPC gives an attacker network reachability, and because the service never required a credential, reachability was all they needed. The team genuinely believed network isolation was authentication. It is not. Network reachability controls who can knock; authentication controls who gets in. This whole capability exists because those two things get conflated constantly, and the gap only ever surfaces after someone has already walked through.

Finding unauthenticated services across an estate

Priya is the security lead at a scale-up preparing for its first SOC 2 audit. Security Hub shows authentication failures spread across API Gateway, AppSync and MSK in services that shipped before the team's current guardrails.

Rather than work the findings one by one, she starts with the front doors most exposed to the internet, the HTTP API routes, so she can separate the deliberately public ones from the data routes that should never have been open.

List every route on an HTTP API with its authorization type. A data route set to NONE is the APIGateway.8 failure; a deliberate public health check is the rare exception.

$ aws apigatewayv2 get-routes --api-id a1b2c3d4e5 --query 'Items[].{Route:RouteKey,Auth:AuthorizationType}' --output table
------------------------------------------------
| GET /partners/{id}/orders | NONE |
| POST /partners/{id}/webhook | NONE |
| GET /health | NONE |
| GET /partners/{id}/profile | JWT |
------------------------------------------------
# Two data routes are open; /health is an intentional public exception to document.

An inventory of routes by authorization type. NONE on a data route is the finding; classify each before changing anything.

How AWS decides a service is unauthenticateddeep dive

Most controls in this group resolve to a single field that names the auth mechanism, or its absence. APIGateway.8 reads each route's AuthorizationType and fails on NONE; the passing values are AWS_IAM, JWT and CUSTOM. AppSync.5 fails any GraphQL API whose auth modes include API_KEY, passing only when every mode is one of AMAZON_COGNITO_USER_POOLS, AWS_IAM, OPENID_CONNECT or AWS_LAMBDA. MSK.6 fails any cluster with Unauthenticated.Enabled set to true, even alongside IAM or SASL/SCRAM. ElastiCache.6 fails a Redis OSS replication group below version 6.0 with no AuthToken. DMS.11 fails a MongoDB endpoint whose AuthType is no rather than SCRAM-SHA-1 or MONGODB-CR.

Two subtleties bite during remediation. First, enabling a strong mechanism does not disable a weak one: an MSK cluster can have IAM on and still accept anonymous connections on the unauthenticated listener, and an AppSync API can have Cognito as primary while keeping API_KEY as an additional provider. The finding clears only when the insecure mode is explicitly removed, not merely supplemented. Second, some mechanisms have prerequisites: ElastiCache AUTH requires in-transit encryption first, because the token travels with the connection.

Security Hub evaluates these through AWS Config. Some checks are change-triggered and clear within minutes; others are periodic. The control-plane change is immediate, so confirm by querying the service directly rather than waiting on the report. The durable version of this capability is preventive: a pipeline gate that rejects an API route without an authorizer, an IaC guardrail that blocks API_KEY on AppSync or the unauthenticated listener on MSK, so anonymous access can only exist as a deliberate, reviewed exception.

What is the impact of leaving services unauthenticated?

The direct impact is unauthorised access to whatever the service holds or fronts. An open API route or GraphQL endpoint accepts any request that reaches it; an unauthenticated MSK cluster lets any network-reachable client read, publish or delete topics; an unprotected Redis cache hands its session tokens and cached records to anyone who connects; an unauthenticated DMS endpoint exposes the production data in flight during a migration. With no identity check there is also no audit trail tying the access to anyone, which is exactly the capability you need most when you suspect a leak.

The second-order impact is integrity and availability, not just confidentiality. Unauthenticated access is rarely read-only: an anonymous client can publish forged events that poison every downstream consumer, overwrite cache entries, or run a destructive command. A forged payment event or a deleted topic is a data-integrity and availability incident that is expensive and slow to unwind, well beyond the confidentiality breach.

On the compliance side, every modern framework, SOC 2, ISO 27001, HIPAA, PCI DSS and FedRAMP, treats authentication on data and API services as table stakes, and cyber-insurance questionnaires routinely ask whether data services enforce it. An unauthenticated service is a clean, demonstrable failure with no nuance to argue: the service either requires identity or it does not. A single such finding can hold up an audit sign-off or an insurance renewal far out of proportion to the minutes it takes to close.

How do you require authentication safely?

Work the capability as one loop rather than chasing individual findings. The order matters: confirm an authenticated path exists and clients use it before you remove the unauthenticated one, so you do not drop a live producer, consumer or client.

1. Inventory every service answering anonymous callers

Across services, list the ones with authentication off: API routes with AuthorizationType NONE, AppSync APIs using API_KEY, MSK clusters with the unauthenticated listener enabled, pre-6.0 Redis groups with no AuthToken, DMS MongoDB endpoints with AuthType no. Rank by exposure, public and internet-facing first, and by the data behind each service. Capture what each one fronts, because that decides which fixes are urgent.

2. Separate genuine public endpoints from defaults

Most unauthenticated access is unintended. A deliberately public health check that returns no data, or a webhook that verifies a provider signature inside the handler, is a legitimate exception to document and suppress with a written justification. Everything that fronts business data needs authentication. Choose the mechanism by caller: IAM SigV4 for service-to-service, a JWT or Cognito authorizer for user-facing apps, IAM or SASL/SCRAM for Kafka clients.

3. Migrate gracefully, then remove the insecure mode

Do not hard-cut. Add the authenticated mechanism alongside the open one, deploy clients to use it, watch the unauthenticated path's usage fall to zero in metrics, then remove it: delete the AppSync API key, set MSK Unauthenticated.Enabled to false, enforce the Redis AUTH token with SET after ROTATE, attach the API authorizer and redeploy the stage. The finding clears only when the insecure mode is gone, so verify each removal against the real triggers before closing the ticket.

4. Prevent it shipping again

Closing existing services is one-off; stopping new ones is the durable fix. Add a deploy-time gate that rejects an API route without an authorizer, an IaC guardrail that blocks API_KEY on AppSync and the unauthenticated listener on MSK, and provisioning defaults that require a named auth method. Keep the relevant AWS Config rules enabled for detection. The goal is that an unauthenticated data or API service can only exist as a deliberate, reviewed exception.

# Attach a JWT authorizer to an open API route, then redeploy the stage to enforce it.
aws apigatewayv2 update-route --api-id a1b2c3d4e5 \
  --route-id r7h8j9 --authorization-type JWT --authorizer-id auth9z8y
aws apigatewayv2 create-deployment --api-id a1b2c3d4e5 --stage-name '$default'

# Disable the unauthenticated listener on an MSK cluster while keeping IAM auth.
ARN=arn:aws:kafka:us-east-1:111122223333:cluster/orders-stream-prod/abc123
VERSION=$(aws kafka describe-cluster-v2 --cluster-arn $ARN \
  --query 'ClusterInfo.CurrentVersion' --output text)
aws kafka update-security --cluster-arn $ARN --current-version $VERSION \
  --client-authentication '{"Sasl":{"Iam":{"Enabled":true}},"Unauthenticated":{"Enabled":false}}'

# Once clients send the new credential, remove the AppSync API key to clear the finding.
aws appsync delete-api-key --api-id abcd1234efgh5678ijkl --id da2-examplekeyid12345

Quick quiz

Question 1 of 5

Security Hub shows authentication failures across API Gateway, AppSync and MSK. What is the most efficient way to think about them?

You can now treat service authentication as one capability rather than a scatter of findings: inventory the services answering anonymous callers across API Gateway, AppSync, MSK, ElastiCache and DMS, separate the deliberate public endpoints, migrate clients to an authenticated mechanism, then remove the insecure mode and enforce auth-by-default in provisioning. The Controls this lesson covers section below links every control in this group to its deep page and fix.

Back to the library

Controls this lesson covers

One capability, many AWS Security Hub controls. This lesson is the shared playbook; each control below keeps its own deep page with the exact check, severity and a copy-and-paste fix.