AWS Cloudfront POST request with signed cookies - angularjs

I have a problem for POST request to cloudfront with signed cookies using custom policy.
Recently I changed domain. Before that both GET and POST requests worked well. Now POST request doesn't work.
I think I set up every thing same as before.
Detail situation is like this.
1.GET request to Cloudfront (domain: https://cdn.myexampledomain.com) from https://myexampledomain.com still works fine.
2.I use S3 as origin and GET/POST requests directly to S3 works fine. No CORS problem.
3.However, preflight request to Cloudfront fails.
and I got this error in console.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://myexampledomain.com is therefore not allowed
access. The response had HTTP status code 403.
Funnier thing is when I click "replay XHR" in Chrome developer tool, POST request WORKS fine with signed Cookies and gets 201 Created response. This makes me crazy.
I tried CURL and POSTMAN to test POST request and both worked successfully as expected. This is not Chrome browser problem. Same happens in Safari, Firefox.
I am using AngularJS for client app. I suspected angular but GET/POST requests to S3 directly are fine. (and GET request to Cloudfront)
POST request body and cookie is like this.
Amazon S3 CORS is like follows.
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://myexampledomain.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
This is my custom policy. expireTime is set correctly.
{
"Statement": [
{
"Condition":{
"DateLessThan":{"AWS:EpochTime":expireTime}
}
}
]
}
and cloudfront behavior setting
I am spending two days for this problem. Any small help will be appreciated.

You can see in your OPTIONS response that CORS headers are not being set. That should be your first pointer.
Then look at your configurations of S3 and you can see that you are not setting CORS headers for OPTIONS request.
So add
<AllowedMethod>OPTIONS</AllowedMethod>
to your configurations, result:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://myexampledomain.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>OPTIONS</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
On your screenshot you can see that in cloudfront you have OPTIONS enabled already, so it should work now.
I am repalying to this because I have similar problem with ng-file-upload, not sending cookies with OPTIONS method and so my pre-flight is throwing error that it is unauthorized. When you fix your config, can you please post if you still get error so I know where the problem could be?

Related

Blocked by CORS policy: No 'Access-Control-Allow-Origin' header when calling Image from Amazon S3

I am trying to export the webpage to PDF and the page has images from our S3 server. When the PDF gets exported the images do not appear in the PDF.
When I inspect the Browser console I see the following errors.
Access to image at 'https://skreem2-dev.s3-us-west-2.amazonaws.com/influencers/large-virat-kohli-2retxr.jpg' from origin 'http://localhost:3001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have updated the S3 Buckets CORS policy to the following:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>http://localhost/</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>http://localhost:3001/</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
Any idea how I can render the images into a PDF and bypass this error?
I too have gone through the same issue. I have added the attribute crossorigin="anonymous" to the image tag in the HTML page, it fixed my issue when pulling images from the s3 bucket.

403 forbidden - Upload file to Amazon S3 bucket using Angularjs with pre signed URL

I'm trying to upload image/music file using presigned-url. But I'm getting 403 forbidden error. I've implemented using below document.
http://www.cheynewallace.com/uploading-to-s3-with-angularjs-and-pre-signed-urls/
$http.put($scope.uploadFileLocation["presigned-url-bkgd-img"],
document.getElementById('backgroundImage').files[0],
{ headers: {
'Content-Type': document.getElementById('backgroundImage').files[0].type }
})
.success(function (resp) {
//Finally, We're done
alert('Upload Done!' + resp);
})
.error(function (resp) {
alert("An Error Occurred Attaching Your File" + resp);
});
So the topic regarding the issue you are facing is called CORS, Cross-Origina Resource Sharing. This is good security on the part of Amazon Web Services. A malicious user could get access to your s3 bucket for uploading images without having to pay for it.
First, I would check if your application requires a user to be logged in, in other words does your application have the idea of a user logging in to use the application in general. If so, then you probably need to configure your project accordingly, for example grabbing that middleware that requires your user to be logged in to do anything and dropping it as an argument into your route request to /api/upload.
Second, check your AmazonS3 -> my-bucket-123 and click on the PERMISSIONS tab.
You may need to configure it like so:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="https://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>http://localhost:3000</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

How to validate if CORS is properly set on my S3 bucket?

I have this resource on available via cloudfront cdn
https://d2t70e97bm7kcz.cloudfront.net/app_pfsandbox01/staticapi/MenuTree.json
The S3 bucket is public and the file path is
https://s3.amazonaws.com/appsres/app_pfsandbox01/staticapi/MenuTree.json
The S3 bucket has the following CORS settings
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
I want the resources in this bucket to be used in several different apps (PWAs) with different domains without having to set up a specific CDN for each app/domain.
I need to know how to validate if this resource will be fetched from any app under any domain?
Thanks
Used https://apitester.com/
Crafted a custom OPTIONS request using
Access-Control-Request-Method: GET
Origin: https://dummydomain.com
Got a succesfull response:

react.js | how to get rid of cross-origin error in Codesandbox

IN FIREFOX: When I execute my code the typical error I should get is: "TypeError: Cannot read property 'setState' of undefined", instead I received a very weird cross-origin error.
Here is a screenshot of the error:
http://prntscr.com/iwipnb
Error A cross-origin error was thrown. React doesn't have access to
the actual error object in development. See https://reactjs.org/docs/cross-origin-errors.html for more information.
here is my code: https://codesandbox.io/s/4885l37xrw
How can I avoid the cross-origin error in Codesandbox in FIREFOX?
EDIT1: I know what is the code bug (bind(this)). I'm looking for the cross-origin error firefox problem. Thanks
It looks like you need to enable CORS on your S3 bucket that serves: https://s3-eu-west-1.amazonaws.com/codesandbox-downtime/downtime.json
To do so, just navigate to your bucket, then click the Permissions tab, then in the CORS box enter an XML document with the permissions you'd like. Sample permissions to allow any host to make a GET request:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>http://*</AllowedOrigin>
<AllowedOrigin>https://*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
I have my server setup to support CORS and it's still giving me this error.
It looks like an issue with ReactJS if there is an error while processing a response from the server. In my case it was happening while trying to parse invalid response into JSON.
You can use corsproxy to hit localhost API's from your local machines.
You first need to install the corsproxy npm package.
npm install -g corsproxy
run corsproxy command on terminal
It will run on http://localhost:1337
Now what you need to do is append your api call with the above url. Lets say you need to hit localhost:3000/customer to hit api.
So new url will be http://localhost:1337/localhost:3000/customer
This will remove CORS error.
Do comments your queries in comments.
Add this in API file constructor
public function __construct($config = 'rest'){
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
parent::__construct();
}
The cross origin error mentioned in your question, is an open issue(as of Dec 2019) in Codesandbox's github repository.
Reactjs website explains about this under Cross-origin Errors
Not to be confused with Cross Origin Resource Sharing

PUT to S3 with presigned url gives 403 error

I'm using Node to get an presignedRUL for S3 in order to PUT an image to an S3 bucket.
var aws = require('aws-sdk');
// Request presigned URL from S3
exports.S3presignedURL = function (req, res) {
var s3 = new aws.S3();
var params = {
Bucket: process.env.S3_BUCKET,
Key: '123456', //TODO: creat unique S3 key
//ACL:'public-read',
ContentType: req.body['Content-Type'], //'image/jpg'
};
s3.getSignedUrl('putObject', params, function(err, url) {
if(err) console.log(err);
res.json({url: url});
});
};
This successfully retrieves a presigned url of form...
https://[my-bucket-name].s3.amazonaws.com/1233456?AWSAccessKeyId=[My-ID]&Expires=1517063526&Signature=95eA00KkJnJAgxdzNNafGJ6GRLc%3D
(Do I have to include an expires header?)
Back on the client side (web app) I use angular to generate an HTTP request. I have used both $http and ngFileUpload, with similar lack of success. Here is my ngFileUpload code.
Upload.upload({
url: responce.data.url, //S3 upload url including bucket name
method: 'PUT',
'Content-Type': file.type, //I have tried putting the ContentTyep header all over
headers: {
//'x-amz-acl':'public-read',
'Content-Type': file.type,
},
data: {
file: file,
headers:{'Content-Type': file.type,}
},
})
However, seemingly regardless of how I format my header I always get a 403 error. In the XML of the error it says,
SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.
I don't think CORS is an issue. Originally I was getting some CORS errors but they looked different and I got them to go away with some changes to the S3 bucket CORS settings. I've tried a lot of trial and error setting of the headers for both the request for the presignedURL and PUT request to S3, but I can't seem to find the right combo.
I did notice that when I console.log the 403 response error, the field
config.headers:{Content-Type: undefined, __setXHR_: ƒ, Accept: "application/json, text/plain, */*"}
Is this saying that the Content-Type head isn't set? How can that be when I've set that header everywhere I can think possible? Anyways, been banging my head against the wall of this for a bit...
EDIT: as requested, my Current CORS. (I threw everything in to get rid of the CORS warnings I had earlier. I will pare it down to the essentials only after I get my uploads working.)
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedOrigin>http://localhost:9500</AllowedOrigin>
<AllowedOrigin>https://localhost:9500</AllowedOrigin>
<AllowedOrigin>http://www.example.com</AllowedOrigin>
<AllowedOrigin>https://www.example.com</AllowedOrigin>
<AllowedOrigin>http://lvh.me:9500</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<ExposeHeader>ETag</ExposeHeader>
<AllowedHeader>*</AllowedHeader>
<AllowedHeader>Content-Type</AllowedHeader>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Faced the same issue. Found out that the content-type that I used to create the pre-signed URL was not matching the content-type of the object I was sending to S3. I would suggest you add Expiration header when creating the pre-signed URL (I did too) and check in the console exactly what the content-type is being sent when you do a put to S3. Also, the data just needs to be the file, and not the struct you've created there.
I was having 403 errors with signature not matching and for the life of me could not figure out why. Reading some other examples one of them said it had to be run in us-east-1 because it was not supported in other regions. I was in us-east-2, switched and same exact code worked.
Try using us-east-1

Resources