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:
Related
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
I have created an API using AWS api gateway which contains a mock endpoint /test.
In my response, I get the headers x-amzn-RequestId and x-amz-apigw-id. In case of an error, e.g. using a non existing endpoint /test2, I also get the x-amazn-ErrorType header.
I don't want these aws headers to be in my api response. How can these be removed?
Add CloudFront in front of your API Gateway. Then add a Lambda#Edge function for either origin response or viewer response to remove these attributes from the array.
I have such a configuration of a serverless application: Route53, CloudFront, S3Bucket, APIGateway, Lambda.
The frontend makes a call to the Lambda function via the API. Accordingly, the URL from the API is practically freely available.
An attacker can get it and call many times the Lambda function directly.
How to Make, URL from API causing Lambda accessible only in case of a call from a particular domain?
That is, I need to configure the APIGateway so that it responds only to a specific Origin header. How to do it?
Sounds like what you want is a Custom Authorizer. You create an aws lambda that checks the appropriate headers and then allow/reject the request. The result is then cached as well.
However, you'll want to setup some sort of authentication like AWS Cognito as well to verify who is calling your API.
The solution turned out to be quite simple. In the Request Method of my API, I added Request Validator -> Validate query string parameters and headers, and HTTP Request Header - "Origin" in which I specified the required domain (https://example.com).
Also did Enable CORS and added "Origin" to Access-Control-Allow-Headers, and Access-Control-Allow-Origin specified``https://example.com
And when I called the API from the client, I passed Access-Control-Request-Headers: Origin (although maybe it was not necessary).
As a result: the API that calls the Lambda function, when called directly (from the browser or using curl) produces: {"message": "Missing required request parameters: [Origin]"}.
When called from another, not allowed domain, it gives: "The 'Access-Control-Allow-Origin' header has a value https://example.com that is not equal to the supplied origin".
But when called from https: //example.com API is triggered and the Lambda function is started, which was required.
We have an Angular SPA front end, which communicates through an AWS API Gateway to a .Net Web API hosted in a Lambda function. This configuration mandates that our API Gateway uses proxy intgeration with the Lambda.
Generally, this works well. We have enabled CORS in our API, and normal requests and responses flow as expected.
However, when something happens that breaks the API Gateway or .Net Lambda Wrapper, such as exceeding the Gateway's (non-configurable) 30-second timeout, or exceeding Lambda's max response size, the response message from the API Gateway does not contain a CORS header. As a result, regardless of the actual error, our front end registers a CORS error.
Is there some way to configure the API Gateway to always return a default CORS header?
Please note that this is happening outside of our code - there is nothing I can do inside of the C# lambda function, as this relates to errors happening above that level.
Yes, you can set it at AWS API Gateway Level
Login to AWS Console, Open API Gateway Service, Select your desired gateway.
On the left-hand side panel, select "Gateway Responses" (this will appear under your selected gateway)
now on the right-hand side, select "Default 5XX"
Add Default Headers for Cors like Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin
Save the changes and re-deploy the gateway.
Please refer this image to navigate to the desired section
Hope it helps.
I'm a bit confused by how API Gateway and CloudFront work together. Ultimately, I want to be able to have a custom header and value be considered part of my cache key. I know this can be done by whitelisting (if I'm using CloudFront).
So when I make the following request:
GET /pagesRead/4
Some-Header: fizz
This returns, for instance, '29 pages'
Then there's a post that updates id 4 to '45 pages'
If I make this request
GET /pagesRead/4
Some-Header: buzz
It will now return '45 pages'
But I'm using API Gateway, which obviously has it's own CloudFront behind the scenes. Is there a way I can configure API Gateway to use its 'behind-the-scenes' CloudFront to whitelist my custom header? Does this even need to be done?
According to this documentation: AWS-API-Gatway, It seems like I can just enable API caching in API Gateway, and it will consider my headers as part of the cache key.
Am I understanding this correctly? If all I want is for my headers to be a part of the cache key, what's the difference between 'Enabling API Caching' in API Gateway and adding a CloudFront instance on top of API Gateway and white-listing in CloudFront?
UPDATE:
I've added a header like this in API Gateway:
But on GET, I am getting stale data from the cache.
GET /pagesRead/4 test-header: buzz
The difference is that API Gateway doesn't actually use the CloudFront cache. CloudFront does provide some front-end services for all API Gateway APIs edge-optimized API endpoints¹, but caching does not appear to be one of them, based on the following:
API Gateway enables caching by creating a dedicated cache instance.
...and...
You should not use the X-Cache header from the CloudFront response to determine if your API is being served from your API Gateway cache instance.
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-caching.html
It is possible to cascade an Edge Optimized API Gateway endpoint behind a CloudFront distribution that you create, but it's not without certain inconveniences. Latency increases somewhat, since you're passing through more systems. Given that configuration, the CloudFront-Is-*-Viewer and CloudFront-Viewer-Country headers, and probably any notion of the client IP will be invalid, because the API Gateway deployment will see attributes of the additional CloudFront distribution that is in front of it, rather than of the real client. X-Forwarded-For will still be right, but will have to be handled with care, because it will contain one extra hop that will have to be correctly handled.
For an application where you want to put API Gateway behind your own CloudFront distribution, use one of the new Regional endpoints to deploy your API stage.
it will consider my headers as part of the cache key.
You do have to configure the cache key explicitly, based on the document you cited, but yes, the API Gateway cache will then cache responses based on the value of that header, and other attributes in the cache key.
¹ edge optimized endpoints. API Gateway now has two different kinds of endpoints. The original design is now called edge-optimized, and the new option is called regional. Regional endpoints do not use front-end services from CloudFront, and may offer lower latency when accessed from EC2 within the same AWS region. All existing endpoints were categorized as edge-optimized when the new regional capability was rolled out. With a regional endpoint, the CloudFront-* headers are not present in the request, unless you use your own CloudFront distribution and whitelist those headers for forwarding to the origin.
When you enable caching in API Gateway,
You can also optionally add,
RequestPath
QueryStringParameters
Http Headers
E.g.,
http://example.com/api/{feature}/?queryparam=queryanswer [ with header customheader=value1 ]
Above url gives you option to cache based on,
Just the URL without PathParameters: http://example.com/api/
Optionally include PathParameter: http://example.com/api/{feature}/
Optionally include QueryStrings: http://example.com/api/{feature}/?queryparam=queryanswer
Optionally include Http Headers: You can either include regular header like User-Agent or Custom headers
Whatever the caching mode you have in API-Gateway, you can also have it under CloudFront as well.
Also to clear up the cache, in your http response send Cache-Control: max-age=0
Hope it helps.