How to whitelist Authorization header in CloudFront custom Origin Request Policy?

I have created the following CloudFront Origin Request Policy:

enter image description here

I need Authorization header (without Authorization header the AntiForgeryToken header is not forwarded) but I do not understand why CloudFront does not allow adding Authorization header to the policy?

I get the following error:

400 The parameter Headers contains Authorization that is not allowed.

I have followed this document and added Authorization header to Cache Policy, but still don't get the AntiForgeryToken in my requests...

If I use the legacy cache policy (instead of creating my own custom policy) then I am able to Whitelist Authorization header but don't know why I am not able to do it in my own custom policy?

enter image description here


It is possible to use the Origin Request Policy to forward all headers (use the Managed-AllViewer) which includes Authorization. As stated above, this does cause a conflict with API Gateway because the HOST header doesn't match the request (request is coming from CloudFront, HOST is from the user) and so API Gateway will return a 403. In order to deal with that, you can deploy a Lambda@Edge function to rewrite the HOST header to match CloudFront. API Gateway will then accept the request.

To do that, create a Lambda function in US-EAST-1 (must be here for replication purposes, add edgelambda.amazonaws.com to the trusted entities on the Lambda's role, and then add a CloudFront trigger to the Lambda function for origin-requests and specify the distribution you want to use it.

enter image description here

Here's a sample Lambda@Edge function in Node.JS to perform that task:

'use strict';

exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;

  /* Set host header to API GW domain*/
  request.headers['host'] = [{ key: 'host', value: request.origin.custom.domainName }];
  console.log('successfully executed Lambda at Edge')
  callback(null, request);
};

This caught me out too, with both the query string and headers such as Authorization.

However, the docs state that to pass the headers to the origin it must be used as a cache key:

Cache key settings specify the values in viewer requests that CloudFront includes in the cache key. The values can include URL query strings, HTTP headers, and cookies. The values that you include in the cache key are automatically included in requests that CloudFront sends to the origin, known as origin requests.

and

Note: You can't use an origin request policy to forward the Authorization header. The header must be a part of the cache key to prevent the cache from satisfying unauthorized requests. CloudFront returns an HTTP 400 error if you try to create an origin request policy that forwards the Authorization header.

Additionally, note that in relation to the Origin Request Policy Managed-AllViewer, the issue looks to be the forwarding of the Host header to API Gateway; see https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/571#issuecomment-792051286 i.e. we can't use the Managed-AllViewer for API Gateway origins.

See

  1. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html
  2. https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-authorization-header/

As part of a CDK cloudfront.Distribution() construct:

const apiCachePolicy = new cloudfront.CachePolicy(this, 'ApiCachePolicy', {
        headerBehavior: cloudfront.CacheHeaderBehavior.allowList('authorization'),
        queryStringBehavior: cloudfront.CacheQueryStringBehavior.all(),
        cookieBehavior: cloudfront.CacheCookieBehavior.none(),
        minTtl: Duration.minutes(0),
        maxTtl: Duration.minutes(1),
        defaultTtl: Duration.minutes(0),
        enableAcceptEncodingGzip: true,
        enableAcceptEncodingBrotli: true,
    });