Tarek Cheikh
Founder & AWS Security Expert
Amazon API Gateway is the front door to your cloud applications, handling authentication, request routing, throttling, and protocol transformation for REST, HTTP, and WebSocket APIs. As the first component that processes inbound traffic, API Gateway is also the first target for attackers -- injection attempts, credential stuffing, enumeration attacks, and volumetric abuse all arrive here before reaching your backend services.
In 2025, the OWASP API Security Top 10 highlighted Broken Authentication, Broken Object Level Authorization, and Unrestricted Resource Consumption as the most exploited API vulnerabilities. AWS Security Hub data shows that a significant number of API Gateway deployments still lack WAF protection, have execution logging disabled, or expose routes without any authorization type configured. Each of these gaps represents a direct path for attackers to exfiltrate data, abuse compute resources, or pivot deeper into your environment.
This guide covers 12 essential Amazon API Gateway security best practices, each with real AWS CLI commands, verification procedures, and references to Security Hub control IDs. Whether you are running REST APIs, HTTP APIs, or WebSocket APIs, these controls form a comprehensive defense-in-depth strategy for your API layer.
Without logging, you are operating blind. Execution logging captures detailed records of every request processed by API Gateway, including integration backend responses, Lambda authorizer responses, and AWS integration request IDs. Access logging gives you structured, customizable logs for analytics, anomaly detection, and compliance audits. Security Hub flags this as [APIGateway.1] for REST/WebSocket APIs and [APIGateway.9] for HTTP APIs.
First, ensure the API Gateway service has permission to write to CloudWatch by creating a service-linked role. Then enable both execution and access logging on each stage.
# Create a CloudWatch log group for access logs
aws logs create-log-group \
--log-group-name "/aws/apigateway/my-api-access-logs"
# Enable execution logging (ERROR or INFO level) on a REST API stage
aws apigateway update-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--patch-operations \
op=replace,path=/*/*/logging/loglevel,value=INFO \
op=replace,path=/*/*/logging/dataTrace,value=false
# Enable access logging on a REST API stage
aws apigateway update-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--patch-operations \
op=replace,path=/accessLogSettings/destinationArn,value=arn:aws:logs:us-east-1:123456789012:log-group:/aws/apigateway/my-api-access-logs \
op=replace,path=/accessLogSettings/format,value='{"requestId":"$context.requestId","ip":"$context.identity.sourceIp","caller":"$context.identity.caller","user":"$context.identity.user","requestTime":"$context.requestTime","httpMethod":"$context.httpMethod","resourcePath":"$context.resourcePath","status":"$context.status","protocol":"$context.protocol","responseLength":"$context.responseLength"}'
# Verify logging configuration on a stage
aws apigateway get-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--query '{ExecutionLog: methodSettings."*/*".loggingLevel, AccessLog: accessLogSettings}'
Security Hub Controls: [APIGateway.1] REST and WebSocket API execution logging should be enabled. [APIGateway.9] Access logging should be configured for API Gateway V2 Stages.
Every API route that lacks an authorization type is publicly accessible to the entire internet. This is one of the most common API Gateway misconfigurations. Security Hub control [APIGateway.8] specifically checks that API Gateway routes specify an authorization type. You have four options: IAM authorization, Cognito user pools, Lambda authorizers, or JWT authorizers (HTTP APIs).
# Set IAM authorization on a REST API method
aws apigateway update-method \
--rest-api-id abc123def4 \
--resource-id xyz789 \
--http-method GET \
--patch-operations op=replace,path=/authorizationType,value=AWS_IAM
# Create a Cognito authorizer for a REST API
aws apigateway create-authorizer \
--rest-api-id abc123def4 \
--name "CognitoAuth" \
--type COGNITO_USER_POOLS \
--provider-arns arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_ExamplePool \
--identity-source "method.request.header.Authorization"
# Attach the Cognito authorizer to a method
aws apigateway update-method \
--rest-api-id abc123def4 \
--resource-id xyz789 \
--http-method GET \
--patch-operations \
op=replace,path=/authorizationType,value=COGNITO_USER_POOLS \
op=replace,path=/authorizerId,value=auth123
# List all methods and their authorization types for a REST API
aws apigateway get-resources \
--rest-api-id abc123def4 \
--query "items[].{Path: path, Methods: resourceMethods}"
Security Hub Control: [APIGateway.8] API Gateway routes should specify an authorization type.
Lambda authorizers (formerly custom authorizers) give you full control over authentication and authorization logic. Use a REQUEST-type Lambda authorizer to inspect headers, query strings, stage variables, and context variables. This approach supports third-party identity providers, custom token formats, multi-tenant authorization, and fine-grained access control based on Cognito groups or claims.
# Create a REQUEST-type Lambda authorizer
aws apigateway create-authorizer \
--rest-api-id abc123def4 \
--name "CustomLambdaAuth" \
--type REQUEST \
--authorizer-uri "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:my-authorizer/invocations" \
--authorizer-result-ttl-in-seconds 300 \
--identity-source "method.request.header.Authorization,context.accountId"
# Grant API Gateway permission to invoke the Lambda authorizer
aws lambda add-permission \
--function-name my-authorizer \
--statement-id apigateway-invoke \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-east-1:123456789012:abc123def4/authorizers/auth456"
Best Practices: Always use REQUEST-type authorizers instead of TOKEN-type, as they provide access to the full request context. Enable authorizer result caching (TTL of 300 seconds is a good default) to reduce Lambda invocations and latency. Return explicit Deny policies for unauthorized requests rather than raising exceptions.
AWS WAF inspects HTTP requests before they reach your API logic, blocking SQL injection, XSS, bot traffic, and volumetric abuse at the edge. Without WAF, malicious payloads pass directly to your Lambda functions or backend integrations. Note that WAF integration is available for REST APIs only -- HTTP APIs do not support WAF directly and must be fronted by CloudFront with WAF for equivalent protection.
# Create a WAF web ACL for API Gateway (regional scope)
aws wafv2 create-web-acl \
--name "api-gateway-waf" \
--scope REGIONAL \
--default-action Allow={} \
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=ApiGatewayWAF \
--rules '[
{
"Name": "AWSManagedRulesCommonRuleSet",
"Priority": 1,
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesCommonRuleSet"
}
},
"OverrideAction": {"None": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "CommonRuleSet"
}
}
]' \
--region us-east-1
# Associate WAF web ACL with the API Gateway stage
aws wafv2 associate-web-acl \
--web-acl-arn arn:aws:wafv2:us-east-1:123456789012:regional/webacl/api-gateway-waf/example-id \
--resource-arn arn:aws:apigateway:us-east-1::/restapis/abc123def4/stages/prod
# Check which WAF web ACL is associated with an API stage
aws wafv2 get-web-acl-for-resource \
--resource-arn arn:aws:apigateway:us-east-1::/restapis/abc123def4/stages/prod
Security Hub Control: [APIGateway.4] API Gateway should be associated with a WAF Web ACL. For recommended WAF rule groups, see our WAF security card.
Mutual TLS adds certificate-based client authentication on top of standard TLS encryption. Instead of relying solely on API keys or tokens, the client must present a valid X.509 certificate signed by a trusted Certificate Authority. This is essential for B2B integrations, service-to-service communication, and any scenario requiring strong non-repudiation. mTLS is available for both REST APIs and HTTP APIs at no additional cost.
# Upload your CA certificate bundle (truststore) to S3
aws s3 cp truststore.pem s3://my-bucket/truststore.pem
# Create or update a custom domain name with mutual TLS enabled
aws apigatewayv2 create-domain-name \
--domain-name api.example.com \
--domain-name-configurations CertificateArn=arn:aws:acm:us-east-1:123456789012:certificate/example-cert-id,EndpointType=REGIONAL,SecurityPolicy=TLS_1_2 \
--mutual-tls-authentication TruststoreUri=s3://my-bucket/truststore.pem
# For REST APIs, use the v1 API
aws apigateway create-domain-name \
--domain-name api.example.com \
--regional-certificate-arn arn:aws:acm:us-east-1:123456789012:certificate/example-cert-id \
--security-policy TLS_1_2 \
--mutual-tls-authentication truststoreUri=s3://my-bucket/truststore.pem \
--endpoint-configuration types=REGIONAL
Important: mTLS requires a Regional custom domain name -- it cannot be used with the default API Gateway endpoint. Use AWS Certificate Manager Private CA (ACM PCA) for issuing client certificates in production environments.
Resource policies are JSON-based access policies attached to an API that control whether a specified principal (AWS account, IP range, or VPC endpoint) can invoke the API. They act as a perimeter control, evaluated before your authorizer logic runs. Use resource policies to restrict access by source IP, AWS account, or VPC endpoint.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:123456789012:abc123def4/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": ["203.0.113.0/24", "198.51.100.0/24"]
}
}
},
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:123456789012:abc123def4/*"
}
]
}
# Apply a resource policy to a REST API
aws apigateway update-rest-api \
--rest-api-id abc123def4 \
--patch-operations op=replace,path=/policy,value='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":"*","Action":"execute-api:Invoke","Resource":"arn:aws:execute-api:us-east-1:123456789012:abc123def4/*","Condition":{"StringEquals":{"aws:SourceVpce":"vpce-0123456789abcdef0"}}}]}'
# After updating the resource policy, redeploy the API
aws apigateway create-deployment \
--rest-api-id abc123def4 \
--stage-name prod
Evaluation order: WAF rules are evaluated first, then resource policies, then authentication/authorization. A deny at any layer blocks the request.
Private APIs are only accessible from within your VPC through interface VPC endpoints (AWS PrivateLink). They never traverse the public internet, eliminating an entire class of network-based attacks. Use private APIs for internal microservice communication, backend-for-frontend patterns, and any API that should not be publicly reachable.
# Create a VPC endpoint for API Gateway
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0123456789abcdef0 \
--service-name com.amazonaws.us-east-1.execute-api \
--vpc-endpoint-type Interface \
--subnet-ids subnet-0123456789abcdef0 subnet-0123456789abcdef1 \
--security-group-ids sg-0123456789abcdef0 \
--private-dns-enabled
# Create a private REST API
aws apigateway create-rest-api \
--name "private-api" \
--endpoint-configuration types=PRIVATE,vpcEndpointIds=vpce-0123456789abcdef0
# Attach a resource policy restricting access to the VPC endpoint
aws apigateway update-rest-api \
--rest-api-id priv123 \
--patch-operations op=replace,path=/policy,value='{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Principal":"*","Action":"execute-api:Invoke","Resource":"arn:aws:execute-api:us-east-1:123456789012:priv123/*","Condition":{"StringNotEquals":{"aws:SourceVpce":"vpce-0123456789abcdef0"}}},{"Effect":"Allow","Principal":"*","Action":"execute-api:Invoke","Resource":"arn:aws:execute-api:us-east-1:123456789012:priv123/*"}]}'
Tip: Restrict the VPC endpoint security group to allow inbound HTTPS (port 443) only from the CIDR ranges of your application subnets.
API Gateway provides account-level throttling (10,000 RPS default with 5,000 burst) and stage/method-level throttling. Without explicit throttling, a single abusive client can consume your entire account quota, causing denial of service for all your APIs. Usage plans with API keys allow you to set per-client rate limits and quotas.
# Set stage-level throttling
aws apigateway update-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--patch-operations \
op=replace,path=/*/*/throttling/rateLimit,value=1000 \
op=replace,path=/*/*/throttling/burstLimit,value=500
# Create a usage plan with throttling and quota
aws apigateway create-usage-plan \
--name "Standard" \
--throttle burstLimit=200,rateLimit=100 \
--quota limit=10000,period=DAY \
--api-stages apiId=abc123def4,stage=prod
# Create an API key and associate it with the usage plan
aws apigateway create-api-key \
--name "partner-key" \
--enabled
aws apigateway create-usage-plan-key \
--usage-plan-id plan123 \
--key-id key456 \
--key-type API_KEY
Important: API keys are not a security mechanism for authentication -- they are identifiers for usage tracking and throttling. Always combine API keys with a proper authorizer (IAM, Cognito, or Lambda).
API Gateway supports TLS security policies that determine the minimum TLS version and cipher suites used for HTTPS connections. Enforce TLS 1.2 as the minimum to prevent downgrade attacks. For backend authentication, configure API Gateway to present a client certificate when calling your integration endpoints, allowing your backends to verify that requests originate from API Gateway.
# Set TLS 1.2 security policy on a custom domain name
aws apigateway update-domain-name \
--domain-name api.example.com \
--patch-operations op=replace,path=/securityPolicy,value=TLS_1_2
# Generate a client certificate for backend authentication
aws apigateway generate-client-certificate \
--description "Backend auth certificate for prod stage"
# Associate the client certificate with a stage
aws apigateway update-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--patch-operations op=replace,path=/clientCertificateId,value=cert789
# Check the security policy on a custom domain
aws apigateway get-domain-name \
--domain-name api.example.com \
--query "securityPolicy"
# Verify client certificate is configured on a stage
aws apigateway get-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--query "clientCertificateId"
Security Hub Controls: [APIGateway.2] API Gateway REST API stages should be configured to use SSL certificates for backend authentication.
Request validation allows API Gateway to reject malformed requests before they reach your backend, reducing the attack surface for injection and fuzzing attacks. You can validate request bodies against JSON Schema models, required headers, and required query string parameters. This shifts input validation to the API layer, providing defense in depth.
# Create a request validator
aws apigateway create-request-validator \
--rest-api-id abc123def4 \
--name "validate-body-and-params" \
--validate-request-body \
--validate-request-parameters
# Create a model for request body validation
aws apigateway create-model \
--rest-api-id abc123def4 \
--name "CreateUserModel" \
--content-type "application/json" \
--schema '{
"type": "object",
"required": ["email", "name"],
"properties": {
"email": {"type": "string", "format": "email"},
"name": {"type": "string", "minLength": 1, "maxLength": 100}
},
"additionalProperties": false
}'
# Apply the validator and model to a method
aws apigateway update-method \
--rest-api-id abc123def4 \
--resource-id xyz789 \
--http-method POST \
--patch-operations \
op=replace,path=/requestValidatorId,value=validator123 \
op=replace,path=/requestModels/application~1json,value=CreateUserModel
Tip: Set additionalProperties: false in your JSON Schema models to prevent unexpected fields from being passed through to your backend.
X-Ray tracing provides end-to-end visibility into API requests as they flow from API Gateway through Lambda functions, DynamoDB tables, and other downstream services. While primarily a performance tool, X-Ray is invaluable for security incident investigation -- you can trace a suspicious request from ingestion through every backend service it touched.
# Enable X-Ray tracing on a REST API stage
aws apigateway update-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--patch-operations op=replace,path=/tracingEnabled,value=true
# Verify X-Ray tracing is enabled
aws apigateway get-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--query "tracingEnabled"
Security Hub Control: [APIGateway.3] API Gateway REST API stages should have AWS X-Ray tracing enabled.
If you enable API response caching on your REST API stages, the cached data is stored in a dedicated cache cluster. By default, this cached data is not encrypted at rest. Enabling cache encryption ensures that sensitive response data is protected even if the underlying cache infrastructure is compromised. This is especially critical for APIs that return PII, financial data, or authentication tokens.
# Enable caching with encryption on a stage
aws apigateway update-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--patch-operations \
op=replace,path=/*/*/caching/enabled,value=true \
op=replace,path=/*/*/caching/dataEncrypted,value=true \
op=replace,path=/*/*/caching/ttlInSeconds,value=300
# Verify cache encryption is enabled
aws apigateway get-stage \
--rest-api-id abc123def4 \
--stage-name prod \
--query "methodSettings."*/*".{CachingEnabled: cachingEnabled, CacheEncrypted: cacheDataEncrypted}"
Security Hub Control: [APIGateway.5] API Gateway REST API cache data should be encrypted at rest.
These are the most frequently observed API Gateway security issues across production environments:
authorizationType: NONE exposes endpoints to the public internet. Every route must have an authorizer configured.https://{api-id}.execute-api.{region}.amazonaws.com endpoint bypasses mTLS. Disable it using aws apigateway update-rest-api --patch-operations op=replace,path=/disableExecuteApiEndpoint,value=true."Principal": "*" and no conditions allow access from any AWS account or IP address. Always scope resource policies with IP, VPC endpoint, or account conditions.Access-Control-Allow-Origin: * allows any website to make authenticated requests to your API. Always restrict CORS to your specific domains.| Best Practice | Security Hub Control | Severity | API Type |
|---|---|---|---|
| Enable execution logging | [APIGateway.1] | Medium | REST, WebSocket |
| Enable access logging (V2) | [APIGateway.9] | Medium | HTTP |
| Enforce authorization on all routes | [APIGateway.8] | Medium | HTTP |
| Configure SSL certificates for backend auth | [APIGateway.2] | Medium | REST |
| Enable X-Ray tracing | [APIGateway.3] | Low | REST |
| Associate WAF web ACL | [APIGateway.4] | Medium | REST |
| Encrypt cache data at rest | [APIGateway.5] | Medium | REST |
| Use HTTPS for private integrations | [APIGateway.10] | Medium | HTTP |
| Enable mutual TLS | -- | High (recommended) | REST, HTTP |
| Apply resource policies | -- | High (recommended) | REST |
| Configure throttling and usage plans | -- | Medium (recommended) | REST |
| Enable request validation | -- | Medium (recommended) | REST |
For a concise overview of API Gateway security controls, see our API Gateway security card. For WAF configuration details referenced in this guide, review our AWS WAF Security Best Practices guide. To learn more about securing Lambda authorizer functions, see the AWS Lambda Security Best Practices guide.
This article is just the start. Get the full picture with our free whitepaper - 8 chapters covering IAM, S3, VPC, monitoring, agentic AI security, compliance, and a prioritized action plan with 50+ CLI commands.
Comprehensive guide to securing web applications with AWS WAF. Covers managed rules, Bot Control, Fraud Control (ATP/ACFP), CAPTCHA/Challenge actions, rate-based rules, Shield Advanced integration, and centralized WAF management with Firewall Manager.
Comprehensive guide to securing AWS Lambda functions. Covers execution role least privilege, Function URL authentication, VPC placement, code signing, environment variable encryption, Secrets Manager integration, and SnapStart security considerations.
Comprehensive guide to securing AWS Virtual Private Cloud. Covers Security Groups, NACLs, VPC Flow Logs, VPC Endpoints, Block Public Access, Encryption Controls, Network Firewall, Transit Gateway, and GuardDuty threat detection.