9

I have setup a CloudFront Distribution with an API Gateway as one of the origins and this API Gateway is configured with an AWS IAM authorizer.

When CloudFront url is invoked with Authorization headers, it returns a 403 error.

{
    "message": "Missing Authentication Token"
} 

However, when the API Gateway url is invoked instead of CloudFront url with the same Authorization headers, it worked.

I've also tried invoking the endpoint without any authorizer via CloudFront url and it worked. Any idea on how to solve this issue.

Shamal Perera
  • 1,611
  • 1
  • 18
  • 21

2 Answers2

9

When provisioning a CloudFront distribution, remember that CloudFront removes most headers from the request by default.

This is done to optimize the cache hit ratio while preventing your origin server from making decisions based on those headers that would not be appropriate for different requests based on other variations (or absence) of those headers, which CloudFront would then serve from cache, inappropriately.

You'll need to whitelist the Authorization header for forwarding to the origin.

Note also that when provisioning API Gateway behind a CloudFront distribution that you control, you'll probably want to deploy your API endpoint as regional and not edge-optimized.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • Where in Cloudfront can I whitelist the `Authorization` header? – user3871 Oct 16 '18 at 03:29
  • @Growler, it looks like [you found the solution](https://stackoverflow.com/a/52827916/1695906). – Michael - sqlbot Oct 16 '18 at 11:00
  • Adding ```Authorization``` does not seems to solve the issue. API Gateway - XXXX.execute-api.region.amazonaws.com/test - ( This works ) Origin Domain Name - XXXX.execute-api.region.amazonaws.com Origin Path - /test still getting {"message":"Missing Authentication Token"} – Rutul Patel Jul 09 '19 at 21:27
  • @RutulPatel be sure you have "Error Caching Minimum TTL" set to 0 for the HTTP status code being returned, and then verify that your response is not coming from the cache -- the response headers should include `X-Cache: Miss from CloudFront` https://stackoverflow.com/a/35541525/1695906 – Michael - sqlbot Jul 09 '19 at 21:57
  • Currently it's X-Cache →Error from cloudfront – Rutul Patel Jul 10 '19 at 11:49
  • My mistake @RutulPatel, the "X-Cache: Miss..." message may only be applicable to successful responses (HTTP status code < 400)... but the Error Caching Minimum TTLs definitely need to be set to 0. You should probably post this as its own question, if you haven't already. – Michael - sqlbot Jul 10 '19 at 12:56
1

Please see below, in case if anyone is facing this issue when using API Gateway as a secondary origin - behavior instead of default behavior for the Cloudfront Distribution i.e.

  • forwarding all paths like /api/* requests to API Gateway
  • serving the remaining paths with an s3 or other default resource like an Application load balancer

I was using AWS CDK to define and deploy AWS API Gateway as a secondary behavior and faced the same issue and I did everything including

  • forwarding headers and query params
  • enabling all http request methods
  • Setting the API gateway as regional

My configuration for the deployment is as follows:

            originConfigs: [{
            customOriginSource: {
                domainName: clientAppBucket.bucketWebsiteDomainName,
                originProtocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY
            },
            behaviors: [{
                isDefaultBehavior: true,
                compress: true
            }]
        },
        {
            customOriginSource: { domainName: `${api.restApiId}.execute-api.${this.region}.amazonaws.com/prod` },
            behaviors: [
                {
                    pathPattern: "/api/*",
                    allowedMethods: cloudfront.CloudFrontAllowedMethods.ALL,
                    defaultTtl: cdk.Duration.seconds(0),
                    forwardedValues: {
                        queryString: true,
                        headers: ["Authorization"],
                    },
                },
            ],
        }]

The problem was that Cloudfront prepends the path that we are using as a custom behavior with each request i.e. when we call domain.com/api/something, It will not call ${api.restApiId}.execute-api.${this.region}.amazonaws.com/prod/something. Instead it will call ${api.restApiId}.execute-api.${this.region}.amazonaws.com/prod/api/something.

Therefore, either the stage name of the default API Gateway URL which is usually prod should be equal to the behavior path which we specify i.e /path/* or /api/* or /backend/* etc -> /prod/* or we should have a /path/ as a resource at the top level of RestApi and nest all the resources under it

Aravind Samala
  • 139
  • 1
  • 5