Cross-Origin Resource Sharing (CORS) errors are among the most common issues developers encounter when building modern web applications. They can be particularly frustrating because the browser often reports a generic CORS error even when the real problem lies elsewhere.
In cloud-native architectures built with AWS Lambda and API Gateway, CORS-related problems frequently appear after authentication tokens expire, making applications seem unstable despite functioning correctly on the backend.
This guide explains how CORS works, why these errors occur, and how to properly configure AWS API Gateway to avoid unexpected failures.
What Is CORS?
CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls whether a web application hosted on one domain can access resources from another domain.
For example:
Frontend
https://app.example.com
API
https://api.example.com
Since the frontend and API reside on different origins, the browser requires the API to explicitly permit access through special HTTP headers.
Typical CORS headers include:
Access-Control-Allow-Origin
Access-Control-Allow-Headers
Access-Control-Allow-Methods
Without these headers, the browser blocks access to the response.
Understanding the Symptoms
A common scenario involves an application that works correctly for several hours and then suddenly begins displaying CORS errors.
Browser developer tools may show messages similar to:
CORS Missing Allow Origin
Status code: 401
The response body may contain:
{
"message": "The incoming token has expired"
}
At first glance, it appears that CORS has failed.
In reality, the application is returning a legitimate authentication error, but the browser cannot read the response because the required CORS headers are missing.
Why the Error Appears Only Sometimes
This behavior often occurs when:
- A user authenticates successfully.
- The API returns HTTP 200 responses.
- CORS headers are present.
- The authentication token eventually expires.
- The API returns HTTP 401 Unauthorized.
- The error response does not include CORS headers.
- The browser blocks access to the response.
The result is a misleading CORS error even though the real issue is token expiration.
AWS API Gateway and CORS
AWS API Gateway supports CORS configuration, but the implementation differs depending on the API type.
REST API
For REST APIs, CORS settings are typically configured on individual resources and methods.
HTTP API
For HTTP APIs, CORS is configured globally at the API level.
Understanding which API type is being used is critical when troubleshooting.
Identifying the Root Cause
A typical investigation reveals:
Successful Requests
200 OK
Access-Control-Allow-Origin: *
Failed Requests
401 Unauthorized
Missing:
Access-Control-Allow-Origin
Because the browser does not receive the required CORS headers, it blocks access to the response.
Configuring CORS in API Gateway
When using a REST API, developers can enable CORS from the API Gateway console.
The configuration generally includes:
Allowed Origins
*
or
https://your-domain.com
Allowed Headers
Content-Type
Authorization
X-Api-Key
Allowed Methods
GET
POST
PUT
DELETE
OPTIONS
The Often-Missed Configuration
One of the most frequently overlooked settings involves Gateway Responses.
When enabling CORS, developers should also configure:
Default 4XX
Handles client errors such as:
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
Default 5XX
Handles server-side failures such as:
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
Without enabling these responses, API Gateway may not attach CORS headers to error messages.
Deploying the Changes
Saving the configuration is not enough.
After modifying CORS settings:
- Open API Gateway.
- Select the API.
- Choose Deploy API.
- Deploy to the desired stage.
Failing to redeploy is a common reason changes appear ineffective.
Improving Reliability with Lambda
Even when API Gateway is configured correctly, it is considered best practice to include CORS headers directly in Lambda responses.
Example:
{
"statusCode": 401,
"headers": {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type,Authorization",
"Access-Control-Allow-Methods": "OPTIONS,GET,POST,PUT,DELETE"
},
"body": "{\"message\":\"Token expired\"}"
}
This ensures consistent behavior regardless of how the request is processed.
Recommended Troubleshooting Checklist
When facing CORS issues in AWS:
Verify the actual HTTP status code
Look beyond the browser error message.
Check response headers
Confirm that:
Access-Control-Allow-Origin
is present.
Review authentication
Determine whether:
- JWT tokens expired
- Cognito sessions expired
- Custom authorizers rejected the request
Configure Gateway Responses
Enable:
- Default 4XX
- Default 5XX
Redeploy the API
Always deploy after configuration changes.
Include CORS headers in Lambda
Handle both success and error responses consistently.
Best Practices for Production Environments
While using:
Access-Control-Allow-Origin: *
is acceptable during development, production systems should restrict access to approved domains.
Example:
Access-Control-Allow-Origin: https://app.company.com
Additional recommendations include:
- Monitoring authorization failures
- Logging authentication events
- Using short-lived access tokens with refresh mechanisms
- Testing all error paths
- Validating preflight OPTIONS requests
Conclusion
CORS errors in AWS API Gateway applications are often symptoms rather than root causes. In many cases, the backend is functioning correctly, but error responses such as HTTP 401 Unauthorized are returned without the necessary CORS headers.
By properly configuring API Gateway Gateway Responses, redeploying changes, and ensuring Lambda functions include CORS headers for both successful and failed requests, developers can eliminate many of the most common and confusing browser-side errors.
Understanding the relationship between authentication, API Gateway responses, and browser security policies is the key to building reliable serverless applications on AWS.


