I'm working on some Javascript that makes use of Firefox 3.5's ability to perform cross-domain XMLHttpRequests… But I'd like to fail gracefully if they aren't supported.
Apart from actually making a cross-domain request, is there any way to detect a browser's support for them?
For future reference, full CORS feature detection should look something like this:
//Detect browser support for CORS
if ('withCredentials' in new XMLHttpRequest()) {
/* supports cross-domain requests */
document.write("CORS supported (XHR)");
}
else if(typeof XDomainRequest !== "undefined"){
//Use IE-specific "CORS" code with XDR
document.write("CORS supported (XDR)");
}else{
//Time to retreat with a fallback or polyfill
document.write("No CORS Support!");
}
You can try this test live using JSBin and see the proper response in IE, Firefox, Chrome, Safari, and Opera.
There are some edge cases in non-browser environments that do support cross-domain XHR but not XHR2/CORS. This test does not account for those situations.
According to http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ you should be able to use:
if ('withCredentials' in new XMLHttpRequest()) {
/* supports cross-domain requests */
}
(Note: there is a comment on that page that Chrome 2 fails this test [although it does support cross-domain requests]. I tested Chrome 3 and the test is now passing.)
Keep in mind that just because the browser might support the cross-domain API does not mean the target server will allow the request to complete.
You might want to look at EasyXDM, which wraps cross-browser quirks and provides an easy-to-use API for communicating in client script between different domains using the best available mechanism for that browser (e.g. postMessage if available, other mechanisms if not).
Clearly that library has solved the browser-capabilities detection problem, so you can benefit from their experience. :-)
IE8 also has XDomainRequest object that can be used to retrieve RSS as text which can later be parsed into DOM.
Related
In Firefox, how do I do the equivalent of --disable-web-security in Chrome. This has been posted a lot, but never a true answer. Most are links to add-ons (some of which don't work in the latest Firefox or don't work at all) and "you just need to enable support on the server".
This is temporary to test. I know the security implications.
I can't turn on CORS on the server and I especially would never be able to allow localhost or similar.
A flag, or setting, or something would be a lot better than a plugin. I also tried: http://www-jo.se/f.pfleger/forcecors, but something must be wrong since my requests come back as completely empty, but same requests in Chrome come back fine.
Again, this is only for testing before pushing to prod which, then, would be on an allowable domain.
Almost everywhere you look, people refer to the about:config and the security.fileuri.strict_origin_policy. Sometimes also the network.http.refere.XOriginPolicy.
For me, none of these seem to have any effect.
This comment implies there is no built-in way in Firefox to do this (as of 2/8/14).
From this answer I've known a CORS Everywhere Firefox extension and it works for me. It creates MITM proxy intercepting headers to disable CORS.
You can find the extension at addons.mozilla.org or here.
Check out my addon that works with the latest Firefox version, with beautiful UI and support JS regex: https://addons.mozilla.org/en-US/firefox/addon/cross-domain-cors
Update: I just add Chrome extension for this https://chrome.google.com/webstore/detail/cross-domain-cors/mjhpgnbimicffchbodmgfnemoghjakai
The Chrome setting you refer to is to disable the same origin policy.
This was covered in this thread also:
Disable firefox same origin policy
about:config -> security.fileuri.strict_origin_policy -> false
I have not been able to find a Firefox option equivalent of --disable-web-security or an addon that does that for me. I really needed it for some testing scenarios where modifying the web server was not possible.
What did help was to use Fiddler to auto-modify web responses so that they have the correct headers and CORS is no longer an issue.
The steps are:
Open fiddler.
If on https go to menu Tools -> Options -> Https and tick the Capture & Decrypt https options
Go to menu Rules -> Customize rules. Modify the OnBeforeResponseFunction so that it looks like the following, then save:
static function OnBeforeResponse(oSession: Session) {
//....
oSession.oResponse.headers.Remove("Access-Control-Allow-Origin");
oSession.oResponse.headers.Add("Access-Control-Allow-Origin", "*");
//...
}
This will make every web response to have the Access-Control-Allow-Origin: * header.
This still won't work as the OPTIONS preflight will pass through and cause the request to block before our above rule gets the chance to modify the headers.
So to fix this, in the fiddler main window, on the right hand side there's an AutoResponder tab.
Add a new rule and response:
METHOD:OPTIONS https://yoursite.com/ with auto response: *CORSPreflightAllow
and tick the boxes: "Enable Rules" and "Unmatched requests passthrough".
See picture below for reference:
Best Firefox Addon to disable CORS as of September 2016: https://github.com/fredericlb/Force-CORS/releases
You can even configure it by Referrers (Website).
As of June 2022, Mozilla Firefox does allow you to natively change the CORS configuration. No extra addons are required. As per Mozilla docs you can change the CORS setting by changing the value of the key content.cors.disable
To do so first go to your browser and type about:config in your address bar as shown in the
Click on accept risk and continue, since you are on this stack overflow page we assume you are aware of the risks you are undertaking.
You will see a page with your user variables. On this page just search for key content.cors.disable as
You do not have to type in true or false values, just hit the toggle button at the far right of you in the screen and it will change values.
While the question mentions Chrome and Firefox, there are other software without cross domain security. I mention it for people who ignore that such software exists.
For example, PhantomJS is an engine for browser automation, it supports cross domain security deactivation.
phantomjs.exe --web-security=no script.js
See this other comment of mine: Userscript to bypass same-origin policy for accessing nested iframes
For anyone finding this question while using Nightwatch.js (1.3.4), there's an acceptInsecureCerts: true setting in the config file:
firefox: {
desiredCapabilities: {
browserName: 'firefox',
alwaysMatch: {
// Enable this if you encounter unexpected SSL certificate errors in Firefox
acceptInsecureCerts: true,
'moz:firefoxOptions': {
args: [
// '-headless',
// '-verbose'
],
}
}
}
},
I am working on a project which is written in javascript. I can see that for requesting, XMLHttpRequest object has been created.
It is working fine for "http" requests but fails for "https". Since I am debugging it in the Development environment, I just want to know how to ignore self-signed certificate in XmlHttpRequest objects?
While searching I have found this,
httpreq = new ActiveXObject("Msxml2.ServerXMLHTTP.3.0");
httpreq.setOption(2, 13056);
But the answer is not working for morden browsers like Microsoft edge, chorme...
I have also found this, and it clearly says the setOption() can be used for ignoring ssl certificates.
One difference I can see in my code is that I an creating the httpreq using:
httpreq = new xmlhttprequest();//This is for chorme and Firefox
So is there any way I can ignore self-signed certificates in XmlHttpRequest?
The Bad News:
There is no way to accomplish this with XmlHttpRequest directly. This is logical as SSL needs to be secure on the web as any ability to disable it would present a major security risk.
You are also right that setOption is not a standard/modern method under XmlHttpRequest.
The Good(ish) News:
What you can do is accomplish this via a trusted/properly configured proxy, with the example below as a Node/Express server configured to allow the insecure SSL connection:
$router.get("/", (oRequest, oResponse) => {
$nonStrictSSLRequest = require('request').defaults({strictSSL: false});
$nonStrictSSLRequest(
{ url: "https://192.168.1.2:8080/api/apiVer" },
function (err, oAPIResponse, sBody) {
oResponse.status(200).json(JSON.parse(sBody));
}
);
});
I had to do this to support RainMachine's (stupid HTTPS only) self signed certificates.
If you are developing on Chromium based browser, you can use flag --ignore-certificate-errors. Always pass also --user-data-dir to prevent affecting of your main secure profile. Use this only as last resort and only during local development, as this completely ignores all SSL errors. --ignore-certificate-errors is undocumented flag, which can be removed from chromium at any time.
Chromium Linux:
chromium-browser --ignore-certificate-errors --user-data-dir=~/chromium_dev_session
Chrome Windows:
"C:\Program Files\Google\Chrome\Application\chrome.exe" --ignore-certificate-errors --user-data-dir="c:/chrome_dev_session"
We are implementing an AngularJS based application which uses a rest web service hosted in a different domain. The following script is used for CORS and it works perfectly on Chrome and FireFox. It has an issue in IE9 and Safari when authenticating. It seems the issue is with the withCredentials attribute in those browsers. Is there any other way that IE and Safari supports CORS?
<script type="text/javascript">
XMLHttpRequest.prototype.realSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(vData) {
this.withCredentials = true;
this.realSend.apply(this, arguments);
};
</script>
According to the different scenarios we tried we could come up with following summary. Hope that would be useful.
According to the browser specifications IE10+ and Safari 4+ versions
supports XHR and withCredentials attribute.
That can be used for CORS without any issue as in the above script.
For other IE versions (9-) we need to use XDR.
URL rewrite mod was not successful with the server side when it
comes to HTTPS.
The solution was very simple. By default IE and Safari have disabled the 3rd party cookies. Since we use two different domains once a user enters the credentials to login, those browsers were unable to save that cookie. Because of that all other requests were unauthorized.
Steps for allowing 3rd party cookies
IE 10 - Internet Options > Privacy > Advanced > Third Party Cookies >
Accept
Safari - Preferences > Privacy > Block Cookies > Never
Due to this problem we found that in AngularJS version 1.1.1+ they have made it easy by setting the ‘withCredentials’ value in ‘config’ module (
$httpProvider.defaults.withCredentials = true;)
I am using this page - http://ecmazing.com/cors.html - to make a cross-origin Ajax request to this resource: http://hacheck.tel.fer.hr/xml.pl
It works in Chrome, Safari and Firefox, but doesn't in IE9 and Opera.
The code:
var pdata = {'textarea': 'test'};
$.post('http://hacheck.tel.fer.hr/xml.pl', pdata, function(data, status, xhr) {
output.value = xhr.responseText;
});
(The expected result is an XML code string.)
See for yourself: http://ecmazing.com/cors.html
In IE9 and Opera, the error handler of the XHR object executes and this error object is passed in:
{
readyState: 4,
status: 0,
statusText: 'error'
}
As you can see, this error object doesn't reveal much information.
How can I make it work in IE9 and Opera?
See the entry for cors at whencaniuse.
For Internet Explorer CORS is "Supported somewhat in IE8 and IE9 using the XDomainRequest object", so you need to use an alternate object to use it.
Opera simply doesn't support it.
If you need cross-domain Ajax in Opera, then use JSON-P.
I got so frustrated trying to use CORS with IE and jQuery, I wrote a library to smooth over the worst parts.
Yeah, Microsoft's shortage of cash and manpower have kept them from making their browsers properly CORS-compliant in the seven short years they've had to do it in, but I still prefer CORS to JSONP, which, frankly, is a hack.
Here is a solution that works for IE.
I want to make an XMLHttpRequest to a secure uri (https://site.com/ajaxservice/) from javascript running inside a nonsecure page (http://site.com/page.htm). I've tried all kinds of nutty stuff like iframes and dynamic script elements, so far no go. I know I am violating 'same origin policy' but there must be some way to make this work.
I will take any kind of wacky solution short of having the SSL protocol written in javascript.
That won't work by default due to the same origin policy, as you mentioned. Modern browsers are implementing CORS (Cross-Origin Resource Sharing) which you could use to get around this problem. However this will only work in Internet Explorer 8+, Firefox 3.5+, Safari 4+, and Chrome, and requires some server-side work. You may want to check out the following article for further reading on this topic:
Cross-domain Ajax with Cross-Origin Resource Sharing by Nicholas C. Zakas
You can also use JSONP as Dan Beam suggested in another answer. It requires some extra JavaScript work, and you may need to "pad" your web service response, but it's another option which works in all current browsers.
You can't circumvent cross-domain origin with XHR (well, only in Firefox 3.5 with user's permission, not a good solution). Technically, moving from port 80 (http) to 443 (https) is breaking that policy (must be same domain and port). This is the example the specification itself sites here - http://www.w3.org/Security/wiki/Same_Origin_Policy#General_Principles.
Have you looked into JSONP (http://en.wikipedia.org/wiki/JSON#JSONP) or CSSHttpRequests (http://nb.io/hacks/csshttprequest)?
JSONP is a way to add a <script> tag to a page with a pre-defined global callback across domains (as you can put the <script>s src to anywhere on the web). Example:
<script>
function globalCallback (a) { /* do stuff with a */ }
And then you insert a <script> tag to your other domain, like so:
var jsonp = document.createElement('script');
json.setAttribute('src','http://path.to/my/script');
document.body.appendChild(jsonp);
</script>
And in the source of the external script, you must call the globalCallback function with the data you want to pass to it, like this:
globalCallback({"big":{"phat":"object"}});
And you'll get the data you want after that script executes!
CSSHttpRequests is a bit more of a hack, so I've never had the need to use it, though feel free to give it a try if you don't like JSONP, :).
You said you would take anything short of having the SSL protocol written in JavaScript... but I assume you meant if you had to write it yourself.
The opensource Forge project provides a JavaScript TLS implementation, along with some Flash to handle cross-domain requests:
http://github.com/digitalbazaar/forge/blob/master/README
Check out the blog posts at the end of the README to get a more in-depth explanation of how it works.