API Gateway REST API Authorizers Enabled
Overview
This check verifies that your Amazon API Gateway REST APIs have proper authorization controls. It ensures that either an API-level authorizer exists or all resource methods have authorization configured (not set to NONE). This prevents unauthenticated access to your API endpoints.
Risk
Without proper authorization on your API Gateway methods:
- Data exposure: Attackers can access sensitive data through unprotected endpoints
- Unauthorized actions: Malicious users can invoke backend operations without authentication
- Cost overruns: Unprotected APIs can be abused, generating unexpected charges from traffic spikes
- Service disruption: Abuse of open endpoints can lead to throttling or denial of service
Remediation Steps
Prerequisites
- AWS account access with permissions to modify API Gateway configurations
- Knowledge of which authorization method fits your use case (Cognito, Lambda authorizer, or IAM)
AWS Console Method
- Sign in to the AWS Management Console
- Navigate to API Gateway
- Select your REST API from the list
- In the left navigation, click Authorizers
- Click Create authorizer and choose one of the following:
Option A: Cognito User Pool Authorizer (best for user-facing apps)
- Name: Enter a descriptive name (e.g.,
my-cognito-authorizer) - Type: Select Cognito
- Cognito user pool: Select your existing user pool
- Token source: Enter
Authorization - Click Create authorizer
Option B: Lambda Authorizer (best for custom authentication logic)
- Name: Enter a descriptive name (e.g.,
my-lambda-authorizer) - Type: Select Lambda
- Lambda function: Select your authorizer function
- Lambda invoke role: Leave blank (API Gateway will use resource-based policy)
- Token source: Enter
Authorization - Click Create authorizer
- After creating the authorizer, go to Resources in the left navigation
- For each method (GET, POST, etc.) that shows
Auth: NONE:- Click on the method
- Click Method request
- Under Authorization, select your newly created authorizer
- Click the checkmark to save
- Click Deploy API and select your deployment stage
AWS CLI (optional)
List your REST APIs:
aws apigateway get-rest-apis --region us-east-1
Check existing authorizers for an API:
aws apigateway get-authorizers \
--rest-api-id <your-api-id> \
--region us-east-1
Create a Cognito User Pool authorizer:
aws apigateway create-authorizer \
--rest-api-id <your-api-id> \
--name my-cognito-authorizer \
--type COGNITO_USER_POOLS \
--provider-arns arn:aws:cognito-idp:us-east-1:<account-id>:userpool/<pool-id> \
--identity-source 'method.request.header.Authorization' \
--region us-east-1
Create a Lambda authorizer:
aws apigateway create-authorizer \
--rest-api-id <your-api-id> \
--name my-lambda-authorizer \
--type TOKEN \
--authorizer-uri 'arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:<account-id>:function:<function-name>/invocations' \
--identity-source 'method.request.header.Authorization' \
--authorizer-result-ttl-in-seconds 300 \
--region us-east-1
Apply the authorizer to a method:
aws apigateway update-method \
--rest-api-id <your-api-id> \
--resource-id <resource-id> \
--http-method GET \
--patch-operations op=replace,path=/authorizationType,value=CUSTOM op=replace,path=/authorizerId,value=<authorizer-id> \
--region us-east-1
Deploy the API to apply changes:
aws apigateway create-deployment \
--rest-api-id <your-api-id> \
--stage-name prod \
--region us-east-1
CloudFormation (optional)
AWSTemplateFormatVersion: '2010-09-09'
Description: API Gateway REST API with Cognito Authorizer
Parameters:
UserPoolArn:
Type: String
Description: ARN of the Cognito User Pool for authorization
Resources:
MyRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: my-secure-api
Description: REST API with authorization enabled
CognitoAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: cognito-authorizer
Type: COGNITO_USER_POOLS
RestApiId: !Ref MyRestApi
IdentitySource: method.request.header.Authorization
ProviderARNs:
- !Ref UserPoolArn
MyResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref MyRestApi
ParentId: !GetAtt MyRestApi.RootResourceId
PathPart: secure-resource
MyMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref MyRestApi
ResourceId: !Ref MyResource
HttpMethod: GET
AuthorizationType: COGNITO_USER_POOLS
AuthorizerId: !Ref CognitoAuthorizer
Integration:
Type: MOCK
RequestTemplates:
application/json: '{"statusCode": 200}'
IntegrationResponses:
- StatusCode: 200
MethodResponses:
- StatusCode: 200
ApiDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: MyMethod
Properties:
RestApiId: !Ref MyRestApi
ApiStage:
Type: AWS::ApiGateway::Stage
Properties:
RestApiId: !Ref MyRestApi
DeploymentId: !Ref ApiDeployment
StageName: prod
Outputs:
ApiEndpoint:
Description: API Gateway endpoint URL
Value: !Sub 'https://${MyRestApi}.execute-api.${AWS::Region}.amazonaws.com/prod'
Deploy the template:
aws cloudformation deploy \
--template-file api-gateway-authorizer.yaml \
--stack-name api-gateway-authorizer-stack \
--parameter-overrides UserPoolArn=arn:aws:cognito-idp:us-east-1:<account-id>:userpool/<pool-id> \
--region us-east-1
Terraform (optional)
resource "aws_api_gateway_rest_api" "secure_api" {
name = "my-secure-api"
description = "REST API with authorization enabled"
}
resource "aws_api_gateway_authorizer" "cognito" {
name = "cognito-authorizer"
rest_api_id = aws_api_gateway_rest_api.secure_api.id
type = "COGNITO_USER_POOLS"
provider_arns = [var.cognito_user_pool_arn]
identity_source = "method.request.header.Authorization"
}
resource "aws_api_gateway_resource" "secure_resource" {
rest_api_id = aws_api_gateway_rest_api.secure_api.id
parent_id = aws_api_gateway_rest_api.secure_api.root_resource_id
path_part = "secure-resource"
}
resource "aws_api_gateway_method" "secure_method" {
rest_api_id = aws_api_gateway_rest_api.secure_api.id
resource_id = aws_api_gateway_resource.secure_resource.id
http_method = "GET"
authorization = "COGNITO_USER_POOLS"
authorizer_id = aws_api_gateway_authorizer.cognito.id
}
resource "aws_api_gateway_deployment" "deployment" {
rest_api_id = aws_api_gateway_rest_api.secure_api.id
depends_on = [aws_api_gateway_method.secure_method]
lifecycle {
create_before_destroy = true
}
}
resource "aws_api_gateway_stage" "prod" {
rest_api_id = aws_api_gateway_rest_api.secure_api.id
deployment_id = aws_api_gateway_deployment.deployment.id
stage_name = "prod"
}
variable "cognito_user_pool_arn" {
description = "ARN of the Cognito User Pool"
type = string
}
output "api_endpoint" {
value = aws_api_gateway_stage.prod.invoke_url
}
For a Lambda authorizer instead:
resource "aws_api_gateway_authorizer" "lambda" {
name = "lambda-authorizer"
rest_api_id = aws_api_gateway_rest_api.secure_api.id
type = "TOKEN"
authorizer_uri = aws_lambda_function.authorizer.invoke_arn
authorizer_credentials = aws_iam_role.invocation_role.arn
identity_source = "method.request.header.Authorization"
authorizer_result_ttl_in_seconds = 300
}
Verification
After configuring authorization, verify it is working:
- Go to API Gateway in the AWS Console
- Select your REST API
- Click Authorizers and confirm your authorizer shows as created
- Click Resources and verify each method shows your authorizer (not
Auth: NONE) - Test by calling an endpoint without a valid token - it should return a 401 Unauthorized response
CLI verification commands
List all authorizers for your API:
aws apigateway get-authorizers \
--rest-api-id <your-api-id> \
--region us-east-1
Expected output shows your authorizer:
{
"items": [
{
"id": "abc123",
"name": "my-cognito-authorizer",
"type": "COGNITO_USER_POOLS",
"providerARNs": [
"arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_xxxxx"
],
"identitySource": "method.request.header.Authorization"
}
]
}
Check a specific method's authorization setting:
aws apigateway get-method \
--rest-api-id <your-api-id> \
--resource-id <resource-id> \
--http-method GET \
--region us-east-1
Verify authorizationType is not NONE:
{
"httpMethod": "GET",
"authorizationType": "COGNITO_USER_POOLS",
"authorizerId": "abc123"
}
Additional Resources
- Use API Gateway Lambda Authorizers
- Use Amazon Cognito User Pools as Authorizer
- Control Access to REST APIs Using IAM Permissions
- API Gateway Resource Policies
Notes
- Authorizer types: Choose based on your use case:
- Cognito User Pools: Best for applications with user sign-up/sign-in flows
- Lambda authorizer: Best for custom authentication logic (e.g., validating third-party tokens)
- IAM: Best for service-to-service communication using AWS credentials
- Token caching: Lambda authorizers cache results by default (300 seconds). Adjust
authorizerResultTtlInSecondsbased on your security needs - Deployment required: After changing authorizers, you must deploy the API for changes to take effect
- Defense in depth: Consider combining authorizers with AWS WAF, throttling, and resource policies for additional protection
- Testing: Always test your API after adding authorization to ensure legitimate requests still work