set-cookie header Is removed by AWS HTTP API Gateway - amazon-web-services

I writing a serverless website using Amazon Web Services S3, Lambda, and the HTTP API Gateway, not the REST API Gateway. I am trying to set a cookie with one of my lambda functions and it works when I hit the lambda function directly using the lambda function url, but when I hit the url using the HTTP API Gateway, the Set-Cookie header is stripped off. The body, and all other custom headers are present, but the set-cookie header is just gone.
I've tried with and without the domain=***.com in the header and that doesn't make a difference.
I've tried messing with CORS and enabling Access-Control-Allow-Credentials. I've set Access-Control-Allow-Origin to the correct domain name. I've tried both set-cookie and * for Access-Control-Allow-Headers and Access-Control-Expose-Headers. Although I don't think CORS really matters because I'm using Postman and my understanding is it doesn't require CORS.
Does the HTTP API Gateway just not support setting cookies? It would be great if that was documented somewhere.

I forgot that I was using CloudFront. By default CloudFront does not forward cookies to or from the origin, so I had to set the CloudFront caching policy to allow that. More information here: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Cookies.html

Related

AWS API Gateway - lambda integration missing authorization header

My API includes various GET, POST and DELETE endpoints set up in AWS API Gateway. Each endpoint is integrated with Lambda and calls its own Lambda python function.
I have set up authorization manually (not through AWS authorizers): I call the endpoints with a bearer token in the "Authorization" header, and the Lambda functions access event["headers"]["Authorization"] to obtain the token. This works fine for POST and DELETE endpoints. However, when calling GET endpoints, the "Authorization" header is missing from the event["headers"] object (only other headers added by AWS are present).
I have tried calling the GET endpoints through various methods. Also worth mentioning that this is not a case sensitivity issue - the token I provide is not found anywhere in the events object.
All my endpoints are configured like this in API Gateway:
Method Request:
Integration Request:
Does API Gateway or Lambda remove the "Authorization" automatically for GET calls?
As you've mentioned that you use CloudFront in front of your API gateway, I believe I know what the problem is.
By default, CloudFront strips away params and headers from the request before forwarding it to origin. You need to modify your cache behaviour to forward the Authorization header to origin.
Go to your CloudFront distribution, and edit the behaviour for that distribution. Then, scroll down to 'Cache key and origin requests'.
You need to create a new cache policy that forwards the Authorization header, like so:

AWS Cloudfront Error "IncompleteSignatureException" when accessing API Gateway Origin/Behavior

I am struggeling to get my AWS cloudfront/apigateway setup right. I have a cloudfront with two origins pointing to the same ApiGateway but of different routes. /* as default should be routed to /dev/react and /api/* should be routed to /dev/api/ on the Apigateway. /dev/react is a SSR Lambda rendering a react web page and /dev/api are my API Lambdas. The API Lambdas are protected by the Cognito Authorizer for which I am sending the Authorization header on every request.
This works very well when I serve everything on the ApiGateway domain, no Auth errors or such, but when I try to serve/access it via the cloudfront I can load the react app, via the default behaviour, but when the react app calls the API endpoints I get a IncompleteSignatureException.
I tried forwarding the Host header and other things, but cannot get it to work.
I found this ApiGateway403Erros page where the expl. is A request with an "Authorization" header is sent to an API resource path that doesn't exist., but I can pin point what that means for my scenario?
Is my routing bad? Am i missing an alias domain on the ApiGateway? What makes cloudfront not "finding" the resources on this path?
Any hints would be very much appreciated.

How to serve compressed content without caching in AWS Cloudfront with API Gateway origin?

I'm using Cloudfront distribution with Regional API Gateway origin. For endpoints, for which I can't use caching, I still need the response body to be compressed, if request includes "Accept-Encoding" header.
That's such a trivial requirement, and I think I have tried everything:
"Fake" caching policy with TTL=0 doesn't allow compression to be turned on.
API Gateway compression doesn't work without Accept-Encoding header passed, and Cloudfront never allows to pass it.
Origin request policy doesn't allow to pass custom Accept-Encoding header.
Origin request policy with "All viewer headers" doesn't work, because API Gateway doesn't like the Host header. Setting up custom domain is not working together with Cloudfront using same domain.
Origin doesn't allow to add custom Accept-Encoding header.
Well, after trying everything, I already expect that's not possible for a reason. But I don't understand why.
Please, explain me, what's so bad in compressing non-cached responses?
Or is there a chance I can do this?
UPD
Cloufront functions are not allowed with origin requests
In Lambda#Edge functions Accept-Encoding is read-only.

aws api gateway and lambda cors configuration HTTP api

I have an aws lambda setup using nodejs to basically receive a request with query parameters, trigger another https request and then send the response back.
Configuration for this otherwise is essentially default.
I have then added a trigger to this lambda in the form of an api gateway HTTP api (not REST api).
I have managed to get the api itself to work however I am getting blocked with the usual CORS issues. (i verified the path with Moesif CORS and origin changer to make sure everything else works and it does).
My CORS configuration in the api gateway is basically set to have
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Expose-Headers: No Expose Headers are allowed
Access-Control-Max-Age: 0 seconds
Access-Control-Allow-Credentials: No
I keep finding different pages explaining how to enable cors and so on but mostly seem to be either for an old version of the configuration or for REST api's which look to be quite different.
As it stands, I get this error so i never am allowed to use my api:
Access to fetch at 'https://path.to.my.api?query1=a' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I would want to either allow all origins or disable CORS completely for this really.
Disclaimer: I am quite new to the whole aws infrastructure so some terminology related to it might still be not yet understood.
Edit 1:
After some more digging. I have realised that the call that is failing with the cors error is the first of the two calls happening.
That is to say, this is the call that is ending up on my google domain (which normally would redirect temporarily to my aws gateway - this was setup following instrctions on aws to make a "synthetic record" on the domain settings to return a 302 to the execute-api.eu-central-1.amazonaws.com url), not the call that returns the actual data.
Edit 2:
I have tried adding a route in my api gateway for OPTIONS on the same path, pointed to my lambda which returns the appropriate headers when triggered, however this doesn't seem to get called at all in this case. So i imagine api gateway is trying to handle it on its own but failing somehow

CORS configuration in AWS API Gateway

I am using AWS API Gateway and Lambda Function for one of my applications.
When I send a POST request to API Gateway, it results in an error:
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8888' is therefore not allowed
access. The response had HTTP status code 400
I enabled CORS in the API Gateway console and added 'Access-Control-Allow-Origin' to "Access-Control-Allow-Headers" and clicked "Enable CORS and replace existing CORS Header" button. It was a success.
But when I reloaded the page, I found 'Access-Control-Allow-Headers' header was not present in "Access-Control-Allow-Headers".
I don't know why AWS is not allowing me to edit "Access-Control-Allow-Headers".
I enabled CORS in the API Gateway console and added 'Access-Control-Allow-Origin' to "Access-Control-Allow-Headers" and clicked "Enable CORS and replace existing CORS Header" button. It was a success.
OK, these are two entirely separate headers. Access-Control-Allow-Origin is a response header which must be sent in response to both preflight OPTIONS requests and the actual POST/GET requests. Access-Control-Allow-Headers is a separate response header which is only sent in response to a preflight OPTIONS request.
Can you provide a screenshot showing exactly what you entered where?
I just enabled CORS for two of my APIs in AWS Gateway.
Even after enabling CORS in Gateway API CORS settings, I had faced CORS problem due to these reasons.
CORS Settings: That's the starting point. In CORS settings on API Gateway allow CORS for you origin.
Till you debug CORS issue, you may keep the least restrictive setting as shown below.
Access-Control-Allow-Origin=*
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
(you may even add all headers here during debugging)
Access-Control-Max-Age=0
Access-Control-Expose-Headers, Access-Control-Allow-Headers may be left as default.
Null Origin: For local development, I was running my front-end application directly from the file system without a web-server. AWS CORS setting do not support null origin. I then hosted my local application on nodejs http-server. Now the application has origin localhost. And CORS setting worked fine on one of my APIs.
API path must match. For the second API, I still faced the CORS issue. Despite have the same settings as other API and hosted on a web server. The problem here was that this API had integration at the root and for this case, API must end with /. It was very annoying that I was focusing only on CORS setting where the problem was somewhere else.
If CORS settings do not work for you, you may want to implement root OPTION and return proper CORS headers.