So I have an API deployed on a cloud service. For testing purposes I use various HTTP clients like Postman, Paw and RestClient to send request to my API and they all work just fine. But when I send an AJAX request from Browser either with jQuery, reqwset or any other, I get the following error:
XMLHttpRequest cannot load
{https://url/to/my/api/on/google-app-engine}. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8000' is therefore not allowed
access
So Why does an HTTP client work but browser throws an error? Is there any risk if I enable CORS on the server?
This is because of the “same origin” policy of web browsers. This prevents a script on one website to make requests on another website on your behalf.
Enabling CORS is safe as long as you trust the allowed client, which is probably not the case if the client is at localhost (since you have no control on localhost in general).
Special case: if there's no way for a client to perform changes on the server's domain, then it's safe to enable CORS in general.
Related
I'm working on an Angular web application. I need to make a POST request with a XML body to a server I don't have control over. The request needs an Authorization header. I tried the following:
Send the request directly: It only works when the application is served on http://localhost. Otherwise, the browser shows the following error: Access to XMLHttpRequest at 'server.com' from origin 'my-server.com' 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..
Use a browser extension that adds the missing header to responses: Unsafe, because the extension adds Access-Control-Allow-Origin: * to responses from all domains and that header allows requests from any domain.
Disable browser security: I ran Chrome using this command: chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security. Works when the application is running on a HTTPS server. However, it's unsafe, for the same reasons stated for the previous approach.
Use a third-party proxy: Works for a few requests, but the server blocks the proxy IP because the requests of all clients pass through the same proxy.
My project requires to bypass browser security without compromising security for non-related domains. My project also requires a different IP to be sent to the server by each client. That's required so that if a client overuses the feature, it won't affect other clients.
Is there a way I can add Access-Control-Allow-Origin: my-server.com to all responses or add the header only for a specific server? Is there a way I can redirect each request to a different IP so that the server won't block all my clients? Are there any other workarounds?
For protection of end users browsers block requests to other servers. Yes, you can have a cors browser extension but that is a temporary solution.
You need to set up an endpoint on your server 'my-server.com' to consume your web application post requests. From there you can communicate with the server you don't own and set up your proper auth headers ect.
Chrome is throwing
XMLHttpRequest cannot load
http://127.0.0.1:8006/test
No 'Access-Control-Allow-Origin' header is present on the requested
resource.
Origin 'http://xxx.yyy.com' is therefore not allowed access.
The response had an HTTP status code 401.
I am opening a popup with HTTP and making a request to a local HTTP server created by Java.
It's working fine in all machines except in some different machine, the browser throws the above mentioned error.
As per my understanding, getting this error in HTTP to HTTP is a bit strange.
It's not strange at all – 127.0.0.1:8006 and xxx.yyy.com are different origins, and the Java server is not sending the Access-Control-Allow-Origin header that would tell the broswer it's okay.
More details at https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Basically, the Java server needs to add the Access-Control-Allow-Origin header with either an allowed CORS origin or a wildcard (which would allow any origin):
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: http://xxx.yyy.com (including the protocol, since http and https are different origins in the browser's eyes)
You have to add headers in server side where you are calling that URL for web service implementation. This will help you to understand, how the headers are added in java.
For e.g:
.header("Access-Control-Allow-Origin", "*")
If still you want to avoid the cross origin error. In this case, I suggest you to use this extension with chrome: Chrome extension for cors.
This will help you to avoid cross origin error in browser only in your machine for the development purpose.
Situation:
I have a production web server, let's say https://example.com, configured with CORS with limited set of allowed origins. The set does NOT include localhost origins.
On localhost, developers develop a page/module/whatever that needs to call the production web server via AJAX (even during development). To do that, they run Chrome with CLI arguments --disable-web-security --user-data-dir=chromeNoCors so that Chrome would send AJAX without Origin header.
The problem is that only GET requests are sent without the header. POST requests still contain the header, therefore the production server compares the header value (http://localhost:5678) with allowed set of origins and forbids access to requested resource.
Question:
Is it possible to somehow prevent sending of Origin HTTP header altogether?
I'm aware that there's a workaround to solve this situation by allowing "localhost" (or some specific host that developers will have to add to their /etc/hosts) to the set of allowed origins on production server but I'd like not to do this if possible.
if you guys use chrome try this extension
https://chrome.google.com/webstore/detail/requestly-redirect-url-mo/mdnleldcmiljblolnjhpnblkcekpdkpa
you can modify requests on the fly,even headers
I recommend that you setup a simple "proxy server" (short node.js or python script would suffice). Have this server forward all requests to your remote API server but delete the information about the origin in headers. This is a matter of simple regular expression.
This is simple solution that will be portable to different servers. On AJAX side, all you need is to change the hostname to localhost or IP of your testing proxy server.
I am trying to GET liststatus from the Webhdfs rest api, but getting the following error.
XMLHttpRequest cannot load http://<IP>:50070/webhdfs/v1/?op=LISTSTATUS. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
It loads successfully when I try to access through curl. But it fails when I try to get it using AngularJS $http.get.
Is there any way to enable Cross domain access in Hadoop core-site.xml or somewhere else?
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:
Check it in Firefox browser it may work or else ..
I believe this might likely be that Chrome does not support localhost to go through the Access-Control-Allow-Origin -- see Chrome issue
To have Chrome send Access-Control-Allow-Origin in the header, just alias your localhost in your /etc/hosts file to some other domain, like:
127.0.0.1 localhost yourdomain.com
Then if you'd access your script using yourdomain.com instead of localhost, the call should succeed.
(or)
That's problem of the server. You have to setup response headers on server side.
As far as I understand CORS cannot exactly protect you in the way that you can really be sure who the caller is. Because the caller can send any ORIGIN header he wants. Actually I read somewhere you cannot set the origin header via javascript as it is a restricted header - but I'm not quite sure of that. Anyway.. if you were to implement your own HttpClient you could easily forge your origin header and therefore consume services which you are not supposed to consume.
Secondly if no Origin header is specified the request works as well. For example I use Google Chrome's Postman Extension and it doesn't send any origin headers. In fact if you try to add one manually it doesn't send it over the wire.
Therefore...
...question 1 is: Should my application deny requests without any Origin header? And...
...question 2: How exactly does make CORS my REST service more secure?
There are browsers supporting CORS and not supporting CORS. (We are at the early stage of CORS, the implementations of the CORS specification across browsers are not consistent).
Not supporting CORS means when the browser detects a cross-origin request, the request is blocked and not sent to the server.
Supporting CORS means the browser applies the CORS policy: appends the Origin header before sending requests to the server and after receiving the response, the browser checks the Access-Control-Allow-Origin the decide whether to discard the response.
The same-origin policy is intended to reduce the risks of XSS attacks, this attack mostly happens on browsers, not likely to happen in HttpClient. The CORS policy is for relaxing the same-origin policy so that if you are the owner of both sites, you can leverage this policy to allow communications between your 2 sites.
Tip Supporting CORS means that the browser has to apply the
cross-origin security policy after it has contacted the server and has
obtained the response header, meaning that the request is made even if
the response is discarded because the required header is missing or
specified a different domain. This is a very different approach from
browsers that don’t implement CORS and that simply block the request,
never contacting the server.
Extracted from this book
The point of CORS is to prevent (or allow) Javascript running on a different domain from sending AJAX requests to your API and using the user's authenticated session cookie.
CORS cannot replace proper authentication; all does is prevent the browser from acting as a confused deputy against your existing authentication scheme.