IE9 jQuery AJAX with CORS returns "Access is denied"
Asked Answered
G

12

123

The following works in all browsers except IE (I'm testing in IE 9).

jQuery.support.cors = true;
...
        $.ajax(
            url + "messages/postMessageReadByPersonEmail",
            {
                crossDomain: true,
                data: {
                    messageId       : messageId,
                    personEmail     : personEmail
                },
                success: function() {
                    alert('marked as read');
                },
                error: function(a,b,c) {
                    alert('failed');
                },
                type: 'post'
            }
        );

I have another function which uses dataType: 'jsonp', but I don't need any data returned on this AJAX call. My last resort will be to return some jibberish wrapped in JSONP just to make it work.

Any ideas why IE is screwing up with a CORS request that returns no data?

Groove answered 19/4, 2012 at 15:56 Comment(1)
Since none of the proposed answers worked for me (I had to pass cookies into the CORS request as well, which is a no-no when using XDomainRequest), here's a work-around : blog.gauffin.org/2014/04/…. Proxying to the rescue! :pHeadsman
G
150

This is a known bug with jQuery. The jQuery team has "no plans to support this in core and is better suited as a plugin." (See this comment). IE does not use the XMLHttpRequest, but an alternative object named XDomainRequest.

There is a plugin available to support this in jQuery, which can be found here: https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js

EDIT The function $.ajaxTransport registers a transporter factory. A transporter is used internally by $.ajax to perform requests. Therefore, I assume you should be able to call $.ajax as usual. Information on transporters and extending $.ajax can be found here.

Also, a perhaps better version of this plugin can be found here.

Two other notes:

  1. The object XDomainRequest was introduced from IE8 and will not work in versions below.
  2. From IE10 CORS will be supported using a normal XMLHttpRequest.

Edit 2: http to https problem

Requests must be targeted to the same scheme as the hosting page

This restriction means that if your AJAX page is at http://example.com, then your target URL must also begin with HTTP. Similarly, if your AJAX page is at https://example.com, then your target URL must also begin with HTTPS.

Source: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

Geld answered 19/4, 2012 at 16:14 Comment(20)
Thanks! Any idea how to use that plugin?Groove
I am not entirely sure, but I've added my assumptions to my answer.Geld
The "better version" of the plugin is innate; I just included it in my page and it automagically fixed my $.ajax calls :) Assuming, of course, that you have all the necessary headers in place.Adjacent
I am missing something: neither of these are working for me. Include the script via a script tag, then just make ajax calls as normal?Hartshorn
If I put an alert statement inside the function passed to ajaxTransport, that statement never gets executed. Additionally, the request (which is to 'localhost') doesn't show up in ie9's developer tool's network panel.Hartshorn
To add to dennisg answer, xdr.js has a bug - ajaxTransport callback will not be called as is. I had to change it in accordance with #12482060 (added "+*" as a first argument of ajaxTransport call).Sidestroke
@VolodymyrOtryshko -- Dude let me buy you a beer! Brilliant comment, fixed all my headaches.Pathic
The $.ajaxTransport function you linked on github does absolutely nothing for me. And I really wanted it to. Darn.Microcosm
jQuery.XDomainRequest.js makes sure that the current page and remote page are either both http or https. Does this mean that you cannot make a call to an https API from an http page?Brazen
Note if you're dealing with an HTML response, the improved jQuery.XDomainRequest.js only deals with json and xml. My get now works by adding xdr.js. Wonderful (had done browser sniffing previously and done a XDocumentRequest which works for ie8 and ie10, but inexplicably, no go for ie9).Atomic
It's worth noting that the code that was linked to on moonscripts github repo is an old version that doesn't work. Be sure to get the latest version at: raw.github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest/…Glycoprotein
@Brazen I had problems with IE when I added the bitly API which was using https. Because the page itself was http, IE wouldn't allow it.Oversweet
@Aaron, adding on to @HariKaramSingh's comment: changing protocols (http to https), domains (google.com to bing.com), subdomains (mail.google.com to maps.google.com), or protocols (google.com:80 - the default port to google.com:8080) will all trigger a "cross domain" request. Basically everything before the first / in your URL need to be identical.Garonne
The extending ajax link is now dead.Olav
I've been trying to use this solution, but the cookies setted by the server are never being applied (the ASP.NET_SessionId in particular), so each calls is a new session. I'm on the same protocol, different domain (either different port or domain name), I've tried with jQuery 1.11 or 2.1. Did someone have something similar to this and resolved it, or is there no hope?Spahi
Actually, it sets the cookies, but each time the server makes a cors request, the server returns a new set of cookiesSpahi
I found my issue and patched the source. There really was something missing. I will fork and make a pull request later today with more detailsSpahi
@Frank, at least if you are using XDomainRequest, it does not allow cookies to be sent or received. See this MSDN blog post for more information, specifically the section titled "No authentication or cookies will be sent with the request."Inutile
If I had read the coments, I would have saved myself a lot of time, but I wasted several hours trying to make ajax calls to an https service from an http site. I added it to the answer to avoid other people runnng into the sampe problem.Suez
I had a problem with applying this solution because in my ajax call contained an option 'async: false', while in xdr.js there is an if condition that applies the fix only if async us true.Metaphysical
I
62

Building off the accepted answer by @dennisg, I accomplished this successfully using jQuery.XDomainRequest.js by MoonScript.

The following code worked correctly in Chrome, Firefox and IE10, but failed in IE9. I simply included the script and it now automagically works in IE9. (And probably 8, but I haven't tested it.)

var displayTweets = function () {
    $.ajax({
        cache: false,
        type: 'GET',
        crossDomain: true,
        url: Site.config().apiRoot + '/Api/GetTwitterFeed',
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        success: function (data) {
            for (var tweet in data) {
                displayTweet(data[tweet]);
            }
        }
    });
};
Increasing answered 22/1, 2013 at 17:1 Comment(10)
The jQuery.XDomainRequest.js plugin was exactly what I needed! I couldn't get the iexhr.js plugin to work for requests behind HTTP Basic Authentication, but XDomainRequest worked like a charm!Resting
This worked for me. I didn't need Site.config().apiRoot + (which I'm assuming is for twitter....) But it works great, thanks for doing this.Martlet
@NicholasDecker Site.config().apiRoot was just implementation specific code to get the root URL of the API, nothing universal or fancy. Glad it helped!Increasing
I was hoping this would work for me, but I'm trying to POST. wonder if that's the problem for me.Unburden
Hey @JackMarchetti, for POST requests it doesn't work for me.Marlowe
thanks @SwampDiner, it works fine, it's a shame POST requests are sent as text/plain but it did the trick for me.Joppa
I am having the same problem and i also refered the above links and put the jquery.xdomainrequest.min.js script in my current page but on post event it goes to jquery.min.js and result to No Access-Control-Allow-Origin header is present on the requested resource. what i need to do in this case?Dekaliter
@Dekaliter Are you only having issues with POST? Double check the script is loading after jQuery and your call matches MoonScript's documentation.Increasing
it's going into jquery.min.js only but anyways thanks for the reply as i have added the Headers from back end and it's working fine now..Dekaliter
This worked perfect. Dropped the script in, our call pd.$.get(pd.URL, function(data) { //do work with data } works perfectly. Thanks.Ison
H
16

Complete instructions on how to do this using the "jQuery-ajaxTransport-XDomainRequest" plugin can be found here: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest#instructions

This plugin is actively supported, and handles HTML, JSON and XML. The file is also hosted on CDNJS, so you can directly drop the script into your page with no additional setup: http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest.min.js

Hagiography answered 17/6, 2013 at 18:1 Comment(1)
This worked great -- drop in fix. Unbelievable that this issue exists in jQuery but... Thank you!Hunnish
O
3

The problem is that IE9 and below do not support CORS. XDomainRequest do only support GET/POST and the text/plain conten-type as described here: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

So if you want to use all HTTP verbs and/or json etc you have to use another solution. I've written a proxy which will gracefully downgrade to proxying if IE9 or less is used. You do not have to change your code at all if you are using ASP.NET.

The solution is in two parts. The first one is a jquery script which hooks into the jQuery ajax processing. It will automatically call the webserver if an crossDomain request is made and the browser is IE:

$.ajaxPrefilter(function (options, originalOptions, jqXhr) {
    if (!window.CorsProxyUrl) {
        window.CorsProxyUrl = '/corsproxy/';
    }
    // only proxy those requests
    // that are marked as crossDomain requests.
    if (!options.crossDomain) {
        return;
    }

    if (getIeVersion() && getIeVersion() < 10) {
        var url = options.url;
        options.beforeSend = function (request) {
            request.setRequestHeader("X-CorsProxy-Url", url);
        };
        options.url = window.CorsProxyUrl;
        options.crossDomain = false;
    }
});

In your web server you have to receive the request, get the value from the X-CorsProxy-Url http header and do a HTTP request and finally return the result.

My blog post: http://blog.gauffin.org/2014/04/how-to-use-cors-requests-in-internet-explorer-9-and-below/

Overflight answered 24/4, 2014 at 11:7 Comment(0)
G
1

I just made all requests JSONP because it was the only solution for all of our supported browsers (IE7+ and the regulars). Mind you, your answer technically works for IE9 so you have the correct answer.

Groove answered 20/4, 2012 at 17:57 Comment(1)
Just a note to anyone with this problem-- in this case, if you have a <= IE7 requirement, and you don't have control over the server (e.g. can't make it support GET + script tags w/ JSONP) your best bet is a lightweight middleware server which translates the JSONP call to a POST and streams the response from the black box server back to the user.Larrylars
T
1

Building on the solution by MoonScript, you could try this instead:

https://github.com/intuit/xhr-xdr-adapter/blob/master/src/xhr-xdr-adapter.js

The benefit is that since it's a lower level solution, it will enable CORS (to the extent possible) on IE 8/9 with other frameworks, not just with jQuery. I've had success using it with AngularJS, as well as jQuery 1.x and 2.x.

Tainataint answered 15/8, 2014 at 22:54 Comment(0)
M
0

Getting a cross-domain JSON with jQuery in Internet Explorer 8 and newer versions

Very useful link:

http://graphicmaniacs.com/note/getting-a-cross-domain-json-with-jquery-in-internet-explorer-8-and-later/

Can help with the trouble of returning json from a X Domain Request.

Hope this helps somebody.

Mumbletypeg answered 30/5, 2013 at 20:11 Comment(0)
F
0

To solve this problem, also check if you have some included .js into your ajax file called: I received Access denied error while including shadowbox.js in my ajax.php

Farewell answered 8/7, 2013 at 8:4 Comment(0)
E
0

I was testing a CORS web service on my dev machine and was getting the "Access is denied" error message in only IE. Firefox and Chrome worked fine. It turns out this was caused by my use of localhost in the ajax call! So my browser URL was something like:

http://my_computer.my_domain.local/CORS_Service/test.html

and my ajax call inside of test.html was something like:

//fails in IE 
$.ajax({
  url: "http://localhost/CORS_Service/api/Controller",
  ...
});

Everything worked once I changed the ajax call to use my computer IP instead of localhost.

//Works in IE
$.ajax({
  url: "http://192.168.0.1/CORS_Service/api/Controller",
  ...
});

The IE dev tools window "Network" tab also shows CORS Preflight OPTIONS request followed by the XMLHttpRequest GET, which is exactly what I expected to see.

Exhibitor answered 7/11, 2013 at 13:37 Comment(0)
U
0

Update as of early 2015. xDomain is a widely used library to supports CORS on IE9 with limited extra coding.

https://github.com/jpillora/xdomain

Uball answered 13/2, 2015 at 4:42 Comment(0)
A
0

Try to use jquery-transport-xdr jQuery plugin for CORS requests in IE8/9.

Audieaudience answered 6/10, 2015 at 17:21 Comment(0)
K
-1

Note -- Note

do not use "http://www.domain.xxx" or "http://localhost/" or "IP >> 127.0.0.1" for URL in ajax. only use path(directory) and page name without address.

false state:

var AJAXobj = createAjax();
AJAXobj.onreadystatechange = handlesAJAXcheck;
AJAXobj.open('POST', 'http://www.example.com/dir/getSecurityCode.php', true);
AJAXobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
AJAXobj.send(pack);

true state:

var AJAXobj = createAjax();
AJAXobj.onreadystatechange = handlesAJAXcheck;
AJAXobj.open('POST', 'dir/getSecurityCode.php', true);   // <<--- note
AJAXobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
AJAXobj.send(pack);
Korean answered 28/6, 2015 at 21:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.