loesak
loesak

Reputation: 1613

CloudFront is removing Access-Control-* headers from my Origin

I have a CloudFront distribution with a custom origin to an APIGateway that forwards calls to a Lambda which is my API code. I have a separate CloudFront distribution for my static single-page website. My website is not working because it is getting CORS errors when calling my API on a separate subdomain. It is my Lambda that is currently responsible for sending back CORS headers.

Looking into it, it seems CloudFront is removing CORS headers from the responses from the APIGateway and I cannot figure out how to get it to allow the headers. I can make the same call directly to my APIGateway and I get the correct response headers.

Request:

OPTIONS https://api.mywebsite.com/some/endpoint

User-Agent: ...snip...
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Referer: https://www.mywebsite.com/
Origin: https://www.mywebsite.com
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

APIGateway Response:

200 OK

Date: Fri, 27 Jan 2023 03:47:55 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
x-amzn-RequestId: ...snip...
X-XSS-Protection: 1; mode=block
Access-Control-Allow-Origin: https://www.mywebsite.com
Access-Control-Allow-Headers: authorization
X-Frame-Options: DENY
x-amz-apigw-id: ...snip...
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Expires: 0
X-Content-Type-Options: nosniff
Access-Control-Allow-Methods: GET
Pragma: no-cache
Access-Control-Max-Age: 3600

CloudFront Response:

200 OK

Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Date: Fri, 27 Jan 2023 03:51:58 GMT
x-amzn-RequestId: ...snip...
X-XSS-Protection: 1; mode=block
Accept-Patch: 
Access-Control-Allow-Origin: https://www.cicerone.development.loesoft.com
Allow: GET,HEAD,OPTIONS
X-Frame-Options: DENY
x-amz-apigw-id: ...snip...
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Expires: 0
X-Content-Type-Options: nosniff
Pragma: no-cache
X-Cache: Miss from cloudfront
Via: 1.1 ...snip....cloudfront.net (CloudFront)
X-Amz-Cf-Pop: DFW56-P2
X-Amz-Cf-Id: ...snip...

The browser is rejecting the desired GET call because the PreFlight call didn't have the expected information. I suspect this is because of the missing one or more of the Access-Control-* headers.

I've tried configuring CloudFront a few different ways with no success. Original configuration, the default (only) behavior had a Cache policy and no assigned Origin Request policy or Response Headers policy. I tried adding the managed "All Viewer" managed Origin Request policy which should be sending all inbound request headers to my APIGateway. I did this just in case any headers were being removed in this case. This made no difference. I then added a Response Headers policy that set generic values for the various CORS headers and made sure the "override origin" flag was off so that the "Access-Control-*" headers coming from my origin would be used. This also did not solve the issue. I've tried various different configurations for all the policies but I'm not having much luck.

Additionally, if I have my UI bypass CloudFront and access my API directly, the API calls from the browser work w/o issue.

Is there a way to configure CloudFront to solve my CORS issue or even just to not filter any headers coming from the my origin?

Thank you in advance.

Upvotes: 3

Views: 1217

Answers (1)

loesak
loesak

Reputation: 1613

The issue turned out to be 2 parted. First, without an assigned Origin Request policy, CF was stripping many of the CORS headers before sending the request to the origin. This was causing the appropriate CORS response headers to not be generated by my backend Lambda. Next, adding the AllViewer Origin Request policy resulted in all responses returning 403 but never actually getting to my backend Lambda. It appears that setting this will cause the Host header to be sent with the down stream request, and APIGateway was rejecting the call.

I ended up creating my own Origin Request policy that included all the viewer headers except the Host header and then my downstream Lambda started getting the headers and returning the correct response headers that were then being echoed back by CF.

I did not need a Response Headers policy in place for this to work.

Upvotes: 1

Related Questions