How to enable CORS in AWS API Gateway - amazon-web-services

I'm trying to enable CORS with Amazon's API gateway and Lambda, but I keep getting the error.
Access to XMLHttpRequest at 'https://<url>' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I've followed https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html and added this to lambda expression:
statusCode : statusCode,
body: responseBody,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
}
I've also gone to the API gateway and clicked the enable CORS button. If I look at the OPTIONS in the API gateway it says the
Access-Control-Allow-Headers
is present
If I run a test on the API gateway I can see the headers returned by the lambda expression and the expected headers are all there, but I'm still getting the same error message.
edit:
Logwatch isn't printing anything so I'm assuming that it's not even making it to my lambda function.
I can hit the API successfully from POSTMAN and it has the CORS headers
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: OPTIONS,POST,GET
Here are the response headers I'm getting when I try in chrome.
content-length: 35
content-type: application/json
date: Sun, 03 May 2020 01:51:15 GMT
status: 400
x-amz-apigw-id: L7p_IEbuoAMFeaA=
x-amzn-errortype: BadRequestException
x-amzn-requestid: 7ed06b7d-951f-4774-9bfa-62f307ee5974

The problem is that I was POSTing the data incorrectly from my UI so it was failing model validation. After I disabled body validation it started working properly.
See this question:
AWS API Gateway - CORS + POST not working

Related

AWS S3 PUT Example using REST API

The AWS S3 PUT REST API docs are lacking a clear example of the Authorization string in the Request Syntax.
Request Syntax
PUT /Key+ HTTP/1.1
Host: Bucket.s3.amazonaws.com
x-amz-acl: ACL
Cache-Control: CacheControl
Content-Disposition: ContentDisposition
Content-Encoding: ContentEncoding
Content-Language: ContentLanguage
Content-Length: ContentLength
Content-MD5: ContentMD5
Content-Type: ContentType
Expires: Expires
x-amz-grant-full-control: GrantFullControl
x-amz-grant-read: GrantRead
x-amz-grant-read-acp: GrantReadACP
x-amz-grant-write-acp: GrantWriteACP
x-amz-server-side-encryption: ServerSideEncryption
x-amz-storage-class: StorageClass
x-amz-website-redirect-location: WebsiteRedirectLocation
x-amz-server-side-encryption-customer-algorithm: SSECustomerAlgorithm
x-amz-server-side-encryption-customer-key: SSECustomerKey
x-amz-server-side-encryption-customer-key-MD5: SSECustomerKeyMD5
x-amz-server-side-encryption-aws-kms-key-id: SSEKMSKeyId
x-amz-server-side-encryption-context: SSEKMSEncryptionContext
x-amz-request-payer: RequestPayer
x-amz-tagging: Tagging
x-amz-object-lock-mode: ObjectLockMode
x-amz-object-lock-retain-until-date: ObjectLockRetainUntilDate
x-amz-object-lock-legal-hold: ObjectLockLegalHoldStatus
Body
The docs show this request example further on...
PUT /my-image.jpg HTTP/1.1
Host: myBucket.s3.<Region>.amazonaws.com
Date: Wed, 12 Oct 2009 17:50:00 GMT
Authorization: authorization string
Content-Type: text/plain
Content-Length: 11434
x-amz-meta-author: Janet
Expect: 100-continue
[11434 bytes of object data]
But again, the doc does not have an example format for Auth String. I tried AccessKeyID Secret but that didn't work. I dont' even see logical parameters in the request syntax to pass the two parts of the credential (AccessKeyID and Secret) anywhere in the examples!
Does anyone have a simple example of how to use PUT to add a .json file to S3 using the REST API? Preferrably a screenshot of PostMan setup to better explain where values go (in URL vs. as headers).
From the AWS docs here, it appears it is not possible to create a PUT request to an S3 bucket using REST API alone:
For authenticated requests, unless you are using the AWS SDKs, you have to write code to calculate signatures that provide authentication information in your requests.
This is a new concept to me. I've used token requests and sending keys in headers before when authenticating via REST API's. It sounds like a more secure method of auth.

CORS impossible on AWS Lambda HTTP API Gateway Integration

An AWS Lamba function (NodeJS) returning 3 HTTP headers: aaa, Access-Control-Allow-Origin and bbb was created:
exports.handler = async (event) => {
const response = {
statusCode: 200,
headers: { "aaa":"aaa", "Access-Control-Allow-Origin":"*", "bbb":"bbb" },
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
The function is integrated into a HTTP API (not REST API). In the HTTP API Gateway Configuration, Section "Configure CORS", the HTTP header "Access-Control-Allow-Origin" was set to "*". Please see the screenshot:
Gateway Config
The command "curl -i https://xxxxxxxxxx.execute-api.eu-central-1.amazonaws.com" proves that the HTTP Header Access-Control-Allow-Origin is explicitly removed, because only HTTP headers aaa and bbb are returned:
HTTP/2 200
date: Tue, 14 Apr 2020 11:01:58 GMT
content-type: text/plain; charset=utf-8
content-length: 20
aaa: aaa
bbb: bbb
apigw-requestid: K-S2EjVWliAEJKw=
Why on earth is this header still not present, even after "Configure CORS" was done?
(I'm googling now for more than two days in order to find a solution and it makes me go nuts)
As per Configuring CORS for an HTTP API -
If you configure CORS for an API, API Gateway ignores CORS headers
returned from your backend integration.
That's why the CORS headers from your Lambda (integration) are being ignored. This is one of the differences between the new HTTP APIs from the original REST APIs. In case of these APIs -
For a CORS request, API Gateway adds the configured CORS headers to
the response from an integration.
When you do a simple curl, that is not actual doing a cross-origin request. Hence, you don't see the CORS headers that would be set by the HTTP API. To verify if a CORS request works, I passed an Origin header in the below request and I can see the CORS headers along with my custom headers from Lambda -
$ curl -v -X GET https://$API_ID.execute-api.$AWS_REGION.amazonaws.com -H "Origin: https://www.example.com"
< HTTP/2 200
< date: Tue, 14 Apr 2020 18:02:26 GMT
< content-type: text/plain; charset=utf-8
< content-length: 18
< aaa: aaa
< bbb: bbb
< access-control-allow-origin: https://www.example.com
< access-control-expose-headers: date, x-api-id
Below is a snippet of my CORS configuration on the API. I added Access-Control-Allow-Origin value as https://www.example.com and passed this as a part of the Origin header in my curl request. Such a request would qualify as CORS.
For POST/PUT requests, you'll need to white list the content-type header.
Putting the wildcard doesn't do the trick for some reason, you need to explicitly whitelist it.
For Googlers:
If your OPTIONS preflights succeed but no Access-Control- headers present, and if you are testing using CURL, take extra attention to spell required headers for a preflight:
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Origin: https://theaws.blog
If wrongly spelt, OPTIONS succeeds with 204 No Content, but no Access-Control- headers thus render the preflight result invalid.
Also check you have enough scope for the parameters, as long as your requested method and headers are a subset of the parameter, you will get Access-Control- headers. If not, you will get 204 No Content instead, which I would say it's not very informative!

How to solve Cross-Origin Read Blocking (CORB) issue with an AWS lambda gateway?

I was trying to make my react app running on my localhost to talk to the AWS. I have enabled CORS and the OPTIONS on the API.
Chrome gives this error now
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://xxxxxx.execute-api.us-east-2.amazonaws.com/default/xxxxxx with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
I inspected the network tab and the options call is going through and the OPTIONS is sending this in the response header
access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
access-control-allow-methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
access-control-allow-origin: *
How can I fix this CORB issue and get my first lambda function done?
I had to figure it out. I needed to do these two things to get it working
1. Enable CORS on the Amazon API gateway for your API
This will create an OPTIONS http method handler and you can allow posts from your website by setting the right value for access-control-allow-origin header.
2. Make sure your POST method handling is sending the right parameters when sending the response
import json
from botocore.vendored import requests
API_URL = "https://aladdin.mammoth.io/api/v1/user-registrations"
def lambda_handler(event, context):
if event['httpMethod'] == 'POST':
data = json.loads(event['body'])
# YOUR CODE HERE
return {
'statusCode': 200,
'body': json.dumps({}),
'headers': {
'access-control-allow-headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
'access-control-allow-methods': 'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT',
'access-control-allow-origin': '*'
}
}
return {
'statusCode': 200,
'body': json.dumps({})
}
CORB is a Chromium specific protection and is not directly related to your CORS setup on the AWS side.
Does your server return the headers required by CORB ? X-Content-Type-Options: nosniff and a correct Content-Type ?
You can learn more about CORB on the Chromium web page at https://www.chromium.org/Home/chromium-security/corb-for-developers
I fixed this for image files by updating the Content-Type metadata under Properties in S3 - image/jpeg for JPEG files and image/png for PNG files.
My application uploads image files via multer-s3 and it seems it applies Content-Type: 'application/x-www-form-urlencoded'. It has a contentType option with content-type auto-detect feature - this should prevent improper headers and fix the CORB issue.
It seems the latest Chrome 76 version update includes listening to remote file URL headers, specifically Content-Type. CORB was not an issue for other browsers such as Firefox, Safari, and in-app browsers e.g. Instagram.

CORS access error for PUT method, api on aws hosted on elastic beanstalk

I've deployed an api on AWS API Gateway using http custom integration
I've enabled CORS as seen below:
(source: upload.cat)
For both GET and PUT methods, I am getting the following error:
"url from origin [my origin] has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource"
Code:
fetch(url, {
method: 'POST',
mode: "cors",
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token' //copied from screenshot above
},
body: JSON.stringify(data)
})
.then(response => console.log('Success:', response))
.catch(error => console.error('Error:', error));
}
Access-Control-Allow-Headers are set in the server, you should remove it from your code. It won't make any difference if you put it in your request.
Is your API Gateway method protected by Lambda Authorizer or configured to use an API Key? If so, request might be rejected by one of them and response won't include Access-Control-Allow-Origin header so browser's preflight check will be failed.
You also need to check what response is being returned by API method integration. In case of Proxy Lambda, response should include Access-Control-Allow-Origin header.
Take a look at integration response documentation.

CORS defeats AWS LAMBDA :(

I've been reading a lot on CORS/Lambda/AWS API Gateway configuration, including AWS's setup help:
http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html
And this great article:
https://serverless.com/framework/docs/providers/aws/events/apigateway/
However, CORS is still defeating my API Gateway / Lambda function and I can't figure it out. Would love some help.
The meat of it seems to be that API Gateway proxies the request onto Lambda and you need to set "Access-Control-Allow-Origin": "*" headers in your Lambda function in addition to enabling CORS in the API Gateway, which I've done. I am getting a 200 response and can see the header being sent back correctly from my Lambda function. However, Chrome/FF still give me a CORS error. Any idea why?
Here are my request headers:
Host: myawshost.execute-api.us-west-2.amazonaws.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: application/json, text/javascript
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Origin: null
DNT: 1
Connection: keep-alive
And the 200 response headers:
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 74
Content-Type: application/json
Date: Fri, 23 Dec 2016 08:35:02 GMT
...
That all looks nice and successful right? But yet, I get no JSON back from Lambda and this error message in console:
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://myawshost.execute-api.us-west-2.amazonaws.com/prod/view?id=272. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). (unknown)"
But Access-Control-Allow-Origin is not missing! I can see it there in the response.
Any thoughts?
I've also spent quite some time researching this, and what made it work for me was returning the following in the lambda handler (Python):
return {
'statusCode': status_code,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': status_message if status_code == 200 else 'Failure'
}
Hello, i fixed that problem by setting cors and requested headers in
Api Gateway
first i set the headers i will want in my Method Request after
that i want to include them in the enable CORS menu
after that dont forget to deploy the api to public the new changes in
the api
I hope it will fix it
Regards