Upload to Google Cloud Storage using Signed URL returned origin not allowed on Safari only - safari

Using the Node.js library to generate signed URL and have no problem uploading files from Chrome on local machine and production. But CORS issue appears when sending the PUT request from Safari, both desktop (v13.0.5) and iOS, so far no issue with Chrome on Mac. It says Origin https://website.com is not allowed by Acess-Control-Allow-Origin
I am pretty sure it is somewhere related to Safari sending the request. I have double checked my API to generate the url it has all proper params (matched content type with client) also it does work on Chrome as well. The PUT request is sent using fetch().
Have tried to update GCS cors config using gsutil but safari still complain origin not allowed, even now it does not work on Chrome without wildcard on origin and responseHeader. Someone mentioned on the internet Chrome fine with wildcard but Safari expects headers/origin to be explicit but can't figure out what are required headers. Have tried different variations for responseHeader such as Acess-Control-Allow-Origin, origin, Origin, x-goog-resumable.
[
{
"origin": ["https://website.com"],
"responseHeader": ["Content-Length", "Content-Type", "Date", "Server", "Transfer-Encoding", "X-GUploader-UploadID", "X-Google-Trace"],
"method": ["GET", "HEAD", "POST", "PUT"],
"maxAgeSeconds": 3000
}
]
I have other project that run same setup and has no problem, the only difference probably the #google-cloud/storage npm version and using version: 'v4' when generating getSignedUrl().
Found few on the internet saying to use https://bucket.storage.googleapis instead of https://storage.googleapis/bucket still no avail.

Related

Meteor cache issue with Chromium browsers

I currently have an application running on an old version of Meteor (1.10.1).
And I'm getting an error that seems to be a cache error.
When I upload some pictures with a specific user.
I have a request to S3 that fails with a CORS error, however the return code is 200.
console output
ERROR 200
There is no specific common point between the images except that these two images are images that have already been uploaded with the same account in the past.
However, when I clear the cache on Chrome for example, I can upload the picture again. But I still get the error on browsers whose cache has not been cleared.
BUT if I connect to the same account with two different computers, the error is the same no matter which computer I am on.
Could this be related to how Meteor handles a cache with S3?
I checked the CORS settings on my S3, everything seems to be in order and everything works correctly for 95% of the users.
I also tried with the CORS rules at the most flexible.
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"PUT",
"POST",
"GET",
"HEAD"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 10000
}
]
I also checked if there were similarities in the formats, in the sizes, etc...
It just seems that this is a photo that has already been uploaded earlier.
That's why I think it's a cache problem.
started to answer to you on your exact question then I changed my mind and deleted so I re-write in a different perspective.
Please read this: https://www.reddit.com/r/aws/comments/eh6vx1/s3_vs_cloudfront_costs/ There are 9 comments there and some refer to exact price comparison.
Now that the cost risk is addressed let me get into technicals. With AWS, S3 is storage and Cloudfront is the actual CDN that you are supposed to use.
When you create a Cloudfront domain in front your S3, Cloudfront takes care of the CORS and all the rest of security and cacheing. Ideally, you would create a subdomain to your domain and point it to your Cloudfront domain so that the origin of your website and the origin of your CDN are the same (no CORS troubles).
This discussion in the Meteor forum should help you with the setup of Cloudfront: https://forums.meteor.com/t/s3-file-upload-is-slingshot-still-usable-alternatives/54123/10
As far as I know, there are no Meteor specifics that affect cache. It is all related to the website/webapp CSP which in Meteor is done in general via a browser policy that runs server-side.

I want to add the ID in the API [duplicate]

I am working on an app using Vue js.
According to my setting I need to pass to a variable to my URL when setting change.
<!-- language: lang-js -->
$.get('http://172.16.1.157:8002/firstcolumn/' + c1v + '/' + c1b, function (data) {
// some code...
});
But when my app hit on URL, it shows the following message.
Failed to load http://172.16.1.157:8002/firstcolumn/2017-03-01/2017-10-26: Redirect from 'http://172.16.1.157:8002/firstcolumn/2017-03-01/2017-10-26' to 'http://172.16.1.157:8002/firstcolumn/2017-03-01/2017-10-26/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
In addition to what awd mentioned about getting the person responsible for the server to reconfigure (an impractical solution for local development) I use a change-origin chrome plugin like this:
Moesif Orign & CORS Changer (use to be free but now wants a work email address >_>)
Allow CORS: Access-Control-Allow-Origin
You can make your local dev server (ex: localhost:8080) to appear to be coming from 172.16.1.157:8002 or any other domain.
In case the 2nd plugin link breaks in the future or the plugin writer decides to capitalize off the fame of this thread, open your browser's
plugin marketplace and search "allow cors", there's going to be a
bunch of them.
Thanks all, I solved by this extension on chrome.
Allow CORS: Access-Control-Allow-Origin
If you have control over your server, you can use PHP:
<?PHP
header('Access-Control-Allow-Origin: *');
?>
Ask the person maintaining the server at http://172.16.1.157:8002/ to add your hostname to Access-Control-Allow-Origin hosts, the server should return a header similar to the following with the response-
Access-Control-Allow-Origin: yourhostname:port
Using npm:
To allow cross-origin requests install 'cors':
npm i cors
Add this in the server-side:
let cors = require("cors");
app.use(cors());
When you have this problem with Chrome, you don't need an Extension.
Start Chrome from the Console:
chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
Maybe you have to close all Tabs in Chrome and restart it.
I will assume that you're a front-end developer only and that you don't have access to the backend of the application (regarding the tags of the question).
Short answer on how to properly solve this in your case? You can't, you'll need somebody else.
What is this about?
You need to understand that CORS is a security thing, it's not just here to annoy you just for fun.
It's purpose is to mainly prevent the usage of a (malicious) HTTP call from a non-whitelisted frontend to your backend with some critical mutation.
You could give a look to this YouTube video or any other one really, but I recommend a visual video because text-based explanation can be quite hard to understand.
You also need to understand that if you use Postman or any other tool to try your API call, you will not get the CORS issue. The reason being that those tools are not Web frontends but rather some server-based tools.
Hence, don't be surprised if something is working there but not in your Vue app, the context is different.
Now, how to solve this?
Depending of the framework used by your backend team, the syntax may be quite different but overall, you'll need to tell them to provide something like Access-Control-Allow-Origin: http://localhost:3000 (or any other port you'll be using).
PS: Using Access-Control-Allow-Origin: * would be quite risky because it would allow anybody to access it, hence why a stricter rule is recommended.
If you're using a service, like an API to send SMS, payment, some Google console or something else really, you'll need to allow your localhost in the dashboard of the service. Ask for credentials to your manager or Tech Lead.
If you have access to the backend, you could it yourself as shown here (ExpressJS in this example): https://flaviocopes.com/cors/
How to hack it in a dirty way?
If you're in a damn hurry and want to get something really dirty, you could use a lot of various hacks a listed in the other answers, here's a quick list:
use any extension who is able to create a middleware and forward the request to the backend (it will work because it's not directly coming from your frontend)
force your browser to disable CORS, not sure how this would actually solve the issue
use a proxy, if you're using Nuxt2, #nuxtjs/proxy is a popular one but any kind of proxy (even a real backend will do the job)
any other hack related somehow to the 3 listed above...
At the end, solving the CORS issue can be done quite fast and easily. You only need to communicate with your team or find something on your side (if you have access to the backend/admin dashboard of some service).
I heavily do recommend trying get it right from the beginning because it's related to security and that it may be forgotten down the road...
The approved answer to this question is not valid.
You need to set headers on your server-side code
app.use((req,res,next)=>{
res.setHeader('Access-Control-Allow-Origin','*');
res.setHeader('Access-Control-Allow-Methods','GET,POST,PUT,PATCH,DELETE');
res.setHeader('Access-Control-Allow-Methods','Content-Type','Authorization');
next();
})
You can also try a chrome extension to add these headers automatically.
Hello If I understood it right you are doing an XMLHttpRequest to a different domain than your page is on. So the browser is blocking it as it usually allows a request in the same origin for security reasons. You need to do something different when you want to do a cross-domain request. A tutorial about how to achieve that is Using CORS.
When you are using postman they are not restricted by this policy. Quoted from Cross-Origin XMLHttpRequest:
Regular web pages can use the XMLHttpRequest object to send and receive data from remote servers, but they're limited by the same origin policy. Extensions aren't so limited. An extension can talk to remote servers outside of its origin, as long as it first requests cross-origin permissions.
To add the CORS authorization to the header using Apache, simply add the following line inside either the <Directory>, <Location>, <Files> or <VirtualHost> sections of your server config (usually located in a *.conf file, such as httpd.conf or apache.conf), or within a .htaccess file:
Header set Access-Control-Allow-Origin "*"
And then restart apache.
Altering headers requires the use of mod_headers. Mod_headers is enabled by default in Apache, however, you may want to ensure it's enabled.
I had the same problem in my Vue.js and SpringBoot projects. If somebody work with spring you can add this code:
#Bean
public FilterRegistrationBean simpleCorsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// *** URL below needs to match the Vue client URL and port ***
config.setAllowedOrigins(Collections.singletonList("http://localhost:8080"));
config.setAllowedMethods(Collections.singletonList("*"));
config.setAllowedHeaders(Collections.singletonList("*"));
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
I found solution in this article Build a Simple CRUD App with Spring Boot and Vue.js
You are making a request to external domain 172.16.1.157:8002/ from your local development server that is why it is giving cross origin exception.
Either you have to allow headers Access-Control-Allow-Origin:* in both frontend and backend or alternatively use this extension cors header toggle - chrome extension unless you host backend and frontend on the same domain.
Try running this command in your terminal and then test it again.
curl -H "origin: originHost" -v "RequestedResource"
Eg:
If my originHost equals https://localhost:8081/ and my RequestedResource equals https://example.com/
My command would be as below:
curl -H "origin: https://localhost:8081/" -v "https://example.com/"
If you can notice the following line then it should work for you.
< access-control-allow-origin: *
Hope this helps.
Do specify #CrossOrigin(origins = "http://localhost:8081")
in Controller class.
You can solve this temporarily by using the Firefox add-on, CORS Everywhere. Just open Firefox, press Ctrl+Shift+A , search the add-on and add it!
You won't believe this,
Make sure to add "." at the end of the "url"
I got a similar error with this code:
fetch(https://itunes.apple.com/search?term=jack+johnson)
.then( response => {
return response.json();
})
.then(data => {
console.log(data.results);
}).catch(error => console.log('Request failed:', error))
The error I got:
Access to fetch at 'https://itunes.apple.com/search?term=jack+johnson'
from origin 'http://127.0.0.1:5500' 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.
But I realized after a lot of research that the problem was that I did not copy the
right URL address from the iTunes API documentation.
It should have been
https://itunes.apple.com/search?term=jack+johnson.
not
https://itunes.apple.com/search?term=jack+johnson
Notice the dot at the end
There is a huge explanation about why the dot is important quoting issues about DNS and character encoding but the truth is you probably do not care. Try adding the dot it might work for you too.
When I added the "." everything worked like a charm.
I hope it works for you too.
install:
npm i cors
Then include cors():
app.get("/list",cors(),(req,res) =>{
});
In addition to the Berke Kaan Cetinkaya's answer.
If you have control over your server, you can do the following in ExpressJs:
app.use(function(req, res, next) {
// update to match the domain you will make the request from
res.header("Access-Control-Allow-Origin", "YOUR-DOMAIN.TLD");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
https://enable-cors.org/server_expressjs.html
I tried this code,and that works for me.You can see the documentation in this link
var io = require("socket.io")(http, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
})
The reason that I came across this error was that I hadn't updated the path for different environments.
you have to customize security for your browser or allow permission through customizing security. (it is impractical for your local testing)
to know more about please go through the link.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
These errors may be caused due to follow reasons, ensure the following steps are followed. To connect the local host with the local virtual machine(host). Here, I'am connecting http://localhost:3001/ to the http://abc.test Steps to be followed:
1.We have to allow CORS, placing Access-Control-Allow-Origin: in header of request
may not work. Install a google extension which enables a CORS request.*
2.Make sure the credentials you provide in the request are valid.
3.Make sure the vagrant has been provisioned. Try vagrant up --provision this make the localhost connect to db of the homestead.
Try changing the content type of the header. header:{ 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8;application/json' }
this point is very important.
Another solution to this problem in a specific scenario :
If
AWS APIGW is your backend with authentication enabled and
authentication fails,
your browser may end up complaining about CORS even if CORS is enabled in APIGW. You also need to enable CORS for 4XX as follows
API:YourAPI > Resources > /YourResource > Actions > Enable CORS > Gateway Responses for yourAPI check Default 4XX
Authentication will still fail but it won't look like CORS is the root cause
$.get('https://172.16.1.157:8002/firstcolumn/' + c1v + '/' + c1b, function (data) {
// some code...
});
Just put "https" .

How to fix "Cross-Origin Read Blocking (CORB) blocked cross-origin response with MIME type application/json." issue?

I'm currently developing the frontend (VueJS) for a project and to test my login and register logics I'm using laravel as backend, though we'll be actually working with springboot for backend. I was coding in a desktop and everything was normal. So I just started to work with my laptop. I got the same project, everything is equal. When I use postman to make the requests, it works normally, but when I try to make them with the form from my website, I get that error.
I've looked everywhere but couldn't fix it. Nothing I tryed did work. And It seems that no one else had a similar problem.
Cross-Origin Read Blocking (CORB) blocked cross-origin response http://127.0.0.1:8000/api/login with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
Add proxy configuration in vue.config.js file
module.exports = {
devServer: {
proxy: 'http://localhost:4000'
}
}
This will tell the dev server to proxy any unknown requests (requests that did not match a static file) to http://localhost:4000.
here is a link to the doc for more detail

'XMLHttpRequest cannot load' Error on HTTP Requests from Dart client to local Dart docker server

I've lately been trying to build a Dart client that communicates with my Dart docker server. If I run this url (localhost:8080/id/6192449487634432) on any browser I get back a JSON that I've set up, however, if a use
HttpRequest
.getString ("http://localhost:8080/id/6192449487634432")
.then (print);
on the Dart client, I get this weird error
XMLHttpRequest cannot load http://localhost:8080/id/6192449487634432. No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin 'http://localhost:8081' is therefore not allowed access.
I've searched and some workarounds have been to build a PHP proxy (no thanks). I am new to web development in general and I definitely don't know what a proxy is or how to build one. Is there a clean solution I could use? I have a Redstone server and and AngularDart client.
This happens when your client app is served from a different server than your docker server. This is a browser issue, not specific to Dart. Luckily, the solution is easy.
Be sure to send CORS headers from your server, on every request. The easiest way to solve this is to add the following header:
Access-Control-Allow-Origin: *
I don't know the specifics of Redstone, but be sure to set the header key Access-Control-Allow-Origin and value * on GET, HEAD, and POST methods. Yes, you need to set this header on HEAD requests because sometimes the browser does a HEAD request to check if CORS is enabled.
Learn more about CORS at http://enable-cors.org/
As mentioned above setting the Access-Control-Allow-Origin header allows HTTP requests from the browser to go to other URLs than the origin the client was loaded from. Another option is to serve the Dart client from the same server as you are accessing.
Depending on your environment and whether you are using Dartium or a JavaScript browser
If you are using Dart on App Engine Managed VMs we have built-in support for this, so that requests for the client files are proxied to pub serve during development and served from the output from pub build when deployed. See A Client-Server Example.
If you are running a plain Dart server right now there is no canned solution for switching between pub serve and pub build. You can run pub build and serve the files out of the web/build directory.
We are working on making the solution provided for Dart on App Engine Managed VMs more generally available.
Particularly to redstone, you can solve the problem as follows. Add to your server-side code this snippet
// if not yet there
import 'package:redstone/server.dart' as app;
#app.Interceptor(r'/.*')
interceptor() {
app.chain.next(() {
app.response = app.response.change(headers: {
"Access-Control-Allow-Origin": "*"
});
});
}
you can read more on interceptors in the redstone wiki

CORS, Amazon S3, and Rails - Fails on IE 10 and Safari

IE 10 supports CORS.
Amazon S3 supports CORS.
We have direct-from-site-to-S3 uploading working in all browsers but IE 10 (not bothering with IE 9-). It works like this:
User picks a file (drag and drop or pick from file input)
(POST) We have to "sign" the request before it goes to S3 ($.post('/static/sign_asset', { ... }) which has a callback that fires perfectly all day long.
(POST) We then make the XHR to S3 with the file data and the data from the signing and such.
var xhr = new XMLHttpRequest();
// etc
var fd = new FormData();
// etc
xhr.open('POST', url, true);
xhr.send(fd);
The file uploads, everything works perfectly in all browsers except...
Problems start in IE 10:
Origin null not found in Access-Control-Allow-Origin header. and XMLHttpRequest: Network Error 0x80070005, Access is denied. No other browsers are showing this after we have set response.headers["Access-Control-Allow-Origin"] = "*" in the controller that sends the response. Even when we had this wrong, Chrome would show this error, but the request would still go through.
The file actually does get uploaded to S3, despite this error. Amazon S3 does it's 303 redirect thing - which is our verification that the file was successfully uploaded.
(GET) This is a redirect on a CORS Ajax request, so the "redirect" doesn't refresh the page it just comes back and hits our servers. IE 10 makes this request with a
Content-Type of multipart/form-data; boundary=---------------------------7dd2ce2201da
This is what causes Rails to bug out.
Started GET "/static/signed/asset/tsabat/83ee6840-7158-0130-c19b-28cfe912f6ff?bucket=s.cdpn.io&key=5%2Fauthor-tim_2.jpg&etag=%2260fb3876d516553ff6f3a018066b3250%22" for 127.0.0.1 at
2013-03-17 10:46:36 -0700
EOFError - bad content body:
(gem) rack-1.4.5/lib/rack/multipart/parser.rb:74:in `block in Rack::Multipart::Parser#fast_forward_to_first_boundary' (gem) rack-1.4.5/lib/rack/multipart/parser.rb:72:in `Rack::Multipart::Parser#fast_forward_to_first_boundary'
(gem) rack-1.4.5/lib/rack/multipart/parser.rb:72:in `Rack::Multipart::Parser#parse'
(gem) rack-1.4.5/lib/rack/multipart/parser.rb:15:in `Rack::Multipart.parse_multipart'
(gem) rack-1.4.5/lib/rack/multipart.rb:25:in `ActionDispatch::Request#parse_multipart'
(gem) rack-1.4.5/lib/rack/request.rb:336:in `ActionDispatch::Request#POST'
(gem) rack-1.4.5/lib/rack/request.rb:201:in `ActionDispatch::Request#POST'
Safari fails too (6.0.2)
Safari returns a 200 status code and Rails doesn't freak out about the redirect, but the xhr.status is wrong. xhr.readyState == 4, but xhr.status == 0. We were looking for 200 to make sure it worked OK. That is easy enough to fix, but still...
Chrome does fine (<dead image link removed>) - Doesn't appear to even set Content-Type
Firefox does fine (<dead image link removed>) - Content-Type application/json; charset=utf-8
There are example pages that show how well IE 10 handles CORS, but they don't deal with this redirect issue.
CodePen team member here. We figured this out...
We wanted to depend on the 303 redirect built into S3's POST functionality, but it proved to be problematic, as shown above. Instead we simply stopped using the S3 Form Field success_action_redirect and switched to success_action_status.
For posterity, don't depend on the S3's 303 redirect to work consistently across browsers for xhr requests. If you do, you'll spend your time fighting invalid headers, null origins, and dragons.