How do I troubleshoot HTTP 403 errors from API Gateway?
When I call my Amazon API Gateway API, I get a 403 error.
Short description
When a client can't access a valid URL, you get an HTTP 403 response code. The server understands the request, but the server can't fulfill the request because of client-side issues.
API Gateway APIs can return 403 responses for the following reasons:
Issue | Response header | Error message | Root cause |
Access denied | "x-amzn-errortype" = "AccessDeniedException" | "User is not authorized to access this resource with an explicit deny" | The caller isn't authorized to access an API that uses an API Gateway Lambda authorizer. |
Access denied | "x-amzn-errortype" = "AccessDeniedException" | "User: <user-arn> is not authorized to perform: execute-api:Invoke on resource: <api-resource-arn> with an explicit deny" | The caller isn't authorized to access an API that uses AWS Identity and Access Management (IAM) authorization. Or, the API has an attached resource policy that explicitly denies access to the caller. For more information, see IAM authentication and resource policy. |
Access denied | "x-amzn-errortype" = "AccessDeniedException" | "User: anonymous is not authorized to perform: execute-api:Invoke on resource:<api-resource-arn>" | The caller isn't authorized to access an API that uses IAM authorization. Or, the API has an attached resource policy that doesn't explicitly allow the caller to invoke the API. For more information, see IAM authentication and resource policy. |
Access denied | "x-amzn-errortype" = "AccessDeniedException" | "The security token included in the request is invalid." | The caller used IAM keys that aren't valid to access an API that uses IAM authorization. |
Missing authentication token | "x-amzn-errortype" = "MissingAuthenticationTokenException" | "Missing Authentication Token" | An authentication token wasn't found in the request. |
Authentication token expired | "x-amzn-errortype" = "InvalidSignatureException" | "Signature expired" | The authentication token in the request is expired. |
API key isn't valid | "x-amzn-errortype" = "ForbiddenException" | "Forbidden" | The caller used an API key against a method that requires an API key, but the API key isn't correct. Or, the API key isn't associated to a usage plan that's associated to the stage. Or, the API key is turned off or doesn't exist. |
Signature isn't valid | "x-amzn-errortype" = "InvalidSignatureException" | "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method." | The signature in the request doesn't match the signature on the server when the caller accesses an API that uses IAM authorization. |
AWS WAF filtered | "x-amzn-errortype" = "ForbiddenException" | "Forbidden" | Web application firewall filtering blocks the request when AWS WAF is activated in the API. |
Resource path doesn't exist | "x-amzn-errortype" = "MissingAuthenticationTokenException" | "Missing Authentication Token" | A request with no "Authorization" header is sent to an API resource path that doesn't exist. For more information, see How do I troubleshoot API Gateway REST API endpoint 403 "Missing Authentication Token" errors? |
Resource path doesn't exist | "x-amzn-errortype" = "IncompleteSignatureException" | "Authorization header requires 'Credential' parameter. Authorization header requires 'Signature' parameter. Authorization header requires 'SignedHeaders' parameter. Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header. Authorization=allow" | A request with an "Authorization" header is sent to an API resource path that doesn't exist. |
Incorrectly uses public DNS names to invoke a private API | "x-amzn-errortype" = "ForbiddenException" | "Forbidden" | You incorrectly used public DNS names to invoke a private API from within an Amazon Virtual Private Cloud (Amazon VPC). For example: the "Host" or "x-apigw-api-id" header is missing in the request. For more information, see Invoke a private API using endpoint-specific public DNS hostnames. |
Uses the default execute-api endpoint to invoke a REST API that has a custom domain name | "x-amzn-errortype" = "ForbiddenException" | "Forbidden" | The caller uses the default execute-api endpoint to invoke a REST API after you deactivate the default endpoint. For more information, see Disable the default endpoint for REST APIs |
Uses a client certificate that's not valid to invoke an API Gateway custom domain name that requires mutual TLS | "x-amzn-errortype" = "ForbiddenException" | "Forbidden" | The custom domain name's truststore doesn't issue the client certificate that's in the API request, or the certificate isn't valid. For more information, see How do I troubleshoot HTTP 403 Forbidden errors from an API Gateway custom domain name that requires mutual TLS? |
Invoking a custom domain name without a base path mapping | "x-amzn-errortype" = "ForbiddenException" | "Forbidden" | The caller invokes a custom domain and doesn't map a base path to an API. For more information, see Custom domain name for REST APIs in API Gateway. |
Invoking an API with custom domain turned on when the domain URL includes the stage | "x-amzn-errortype" = "MissingAuthenticationTokenException" | "Missing Authentication Token" | An API mapping specifies an API, a stage, and an optional path to use for the mapping. So, when an API's stage is mapped to a custom domain, you no longer need to include the stage in the URL. For more information, see Map API stages to a custom domain name for REST APIs. |
Stage in request URL is not valid | "x-amzn-errortype" = "ForbiddenException" | "Forbidden" | The caller's request URL includes a stage that doesn't exist. For more information, see Invoke REST APIs in API Gateway. |
Resolution
Identify the cause of the error
If the 403 error is reported from other resources such as in the following examples, then there might be another cause for the error:
- If the error is reported in a web browser, then an incorrect proxy setting might not allow HTTP access.
- If another AWS Service is in front of the API, such as Amazon CloudFront, then the service can reject the request.
To identify the cause of the error, set up Amazon CloudWatch access logging for your API. Then, view your API's log events in CloudWatch to determine if requests reach the API.
Note: HTTP APIs don't support execution logging.
To troubleshoot 403 errors returned by a custom domain name that requires mutual TLS and invokes an HTTP API, complete the following steps:
- Create a new API mapping to test the REST API invocation for your custom domain name.
- To identify the cause of the errors, view your REST API's log events in CloudWatch.
- After you identify and resolve the error, reroute the API mapping to your HTTP API.
Confirm that the requested resource exists in the API definition
Note: If you receive errors when you run AWS Command Line Interface (AWS CLI) commands, then see Troubleshoot AWS CLI errors. Also, make sure that you're using the most recent AWS CLI version.
Use either the API Gateway console or the AWS CLI to verify the following configurations:
- You deployed the API with the latest API definition.
- The requested resource exists in the API definition.
Use curl to get request and response details
If you can reproduce the error, then use the curl -v command to get more details between the client and the API:
curl -X HTTP_VERB -v https://{api_id}.execute-api.{region}.amazonaws.com/{stage_name}/{resource_name}
Verify that the request header is correct
If the error is the result of an API key that's not valid, then verify that the "x-api-key" header was sent in the request. If the header isn't included or isn't correct, then update the request header.
Verify that the DNS setting on interface Amazon VPC endpoints is correctly set
Note: The following tasks apply for APIs that you invoke from an Amazon VPC that has only an interface VPC endpoint.
Verify that the interface endpoint's DNS setting is correctly set based on the type of API that you use.
To invoke a Regional API from inside an Amazon VPC, deactivate private DNS names on the interface endpoint. A public DNS can then resolve the endpoint's hostname. For more information, see Create a private API.
To use the API's private DNS name to invoke a private API from inside an Amazon VPC, activate the private DNS names on the endpoint. The Amazon VPC local subnet resources can then resolve the interface endpoint's hostname.
Note: If you use either of the following options to invoke the private API, then you don't need to set up the private API's public DNS name or an Amazon Route 53 alias.
Review the API's resource policy
Review your API's resource policy to verify the following configurations:
- For APIs that you invoke from an Amazon VPC with an interface VPC endpoint: The API's resource policy grants the Amazon VPC or the interface endpoint access to the API.
- The resource policy's resource specifications and formatting are correct.
Note: When you save a resource policy, the resource specifications aren't validated. For examples, see API Gateway resource policy examples. - The caller is allowed to invoke the API endpoint by the authentication type that you defined for the API. For more information, see How API Gateway resource policies affect authorization workflow.
Review HTTP request and response messages
Reproduce the error in a web browser. Use the browser's network tools to capture the HTTP request and response messages, and analyze them to determine where the error occurred.
Note: For offline analysis, save the messages in an HTTP Archive (HAR) file.
Related information
How do I allow only specific IP addresses to access my API Gateway REST API?
How do I troubleshoot issues when connecting to an API Gateway private API endpoint?
How do I turn on CloudWatch Logs for troubleshooting my API Gateway REST API or WebSocket API?
Curl project on the curl website
Relevant content
- asked a year agolg...
- asked 2 years agolg...
- asked 5 months agolg...
- AWS OFFICIALUpdated 4 months ago
- AWS OFFICIALUpdated a year ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 2 months ago