Reputation: 71
EDIT
I've found out through the comments that I was querying the general S3 api instead of the specific buckets api. Doing that from a browser does not work and I got the error I reported here. In order to "fix" that, I simply switched to using the specific buckets API.
I used the same configurations, but instead I called the s3.upload method as in:
const uploadFile = (file) => {
const uploadParams = { ACL: "public-read", Bucket: config.bucketName, Key: file.name, Body: file };
s3.upload(uploadParams, function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Location);
// setProfilePic(data.location)
}
})
}
I want to upload a file to S3 from my React app. I am using the "official" aws-sdk module, from following this tutorial: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/s3-example-creating-buckets.html#s3-example-creating-buckets-scenario
The problem is that I am getting a CORS error right in my first attempt to print my buckets:
import AWS from 'aws-sdk'
const config = {
bucketName: 'train-my-game',
dirName: 'profile', /* optional */
region: 'us-east-2',
accessKeyId: proccess.env.ACCESS_KEY,
secretAccessKey: proccess.env.SECRET,
}
AWS.config.update({ region: config.region, accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey });
const s3 = new AWS.S3({ apiVersion: '2006-03-01' });
const printBuckets = () => {
s3.listBuckets(function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Buckets);
}
});
}
printBuckets()
This fails with the error:
Access to XMLHttpRequest at 'https://s3.us-east-2.amazonaws.com/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
In the AWS, my bucket is configured with the following permission XML for the CORS configuration:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Does anyone know how to fix this?
Thank you
Upvotes: 4
Views: 9276
Reputation: 78573
To put objects to a bucket, list objects in a bucket, retrieve bucket policies etc. you need to enable CORS on the target S3 bucket. Read the CORS documentation or see the example at awslabs/aws-js-s3-explorer.
You will not be able to invoke ListBuckets, however. The reason is that the ListBuckets call is made to an S3 service endpoint (s3.amazonzaws.com), not to an S3 bucket endpoint (bucket.s3.amazonaws.com) and you cannot enable CORS on the S3 service endpoint. So, ListBuckets will never work in a regular browser. Some browsers allow you to suppress CORS, but it's not normal browser operation. Obviously, if your app were to run outside of the browser, e.g. as a CLI or in Electron, then ListBuckets would work fine.
Upvotes: 4
Reputation: 659
Cross-Origin-Resource-Sharing (CORS) is the mechanism that prevents a web app from running client-side code which makes requests to another web app. Imagine if Facebook could run some javascript and read the email you have in Gmail (because you're already logged in).
To address this, all browsers block javascript from one server from accessing any HTTP resources at any other url/ip unless that URL or IP explicitly allows (trusts) the site that javascript originate from.
In the case of many of the AWS SDK's you must explicitly configure what CORS headers you would like to send when interfacing with your AWS (S3 in this case) Resources.
See: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/cors.html
Replace the AllowedOrigin "example.org" with the FQDN of the server serving your react application.
Upvotes: 1
Reputation: 13
If you’d like to send Authorization headers, your server had better be configured to allow it. Set your server up so it responds to an OPTIONS request at that url with an Access-Control-Allow-Headers: Authorization header.
Upvotes: 0