26

I have a CORS (cross origin resource sharing) request coming from my login page to the application site, on a different URL. I have a simple page I ping to determine if a user is already logged in, and if so, redirects them. Otherwise I show a login page. I use jQuery.

This works great in safari, chrome, firefox... and not IE (naturally). According to MS, IE 10 and later should support CORS requests with withCredentials

I'm using jquery-2.0.3.min.js

Any ideas why this isn't working in IE11?

EDIT: It appears as though it IS partially working, as it is now returning a value of {"id":false}. This happens every time, meaning that the server is never getting the credentials. I am also posting my is_logged_in page, I am using the code igniter framework.

EDIT: After enabling "Allow data sources across domains" under IE's security settings, I no longer receive any error messages.

The exact error I receive is:

SEC7118: XMLHttpRequest for http://mysite.net/guest/is_logged_in required Cross Origin Resource Sharing (CORS).

$.ajax({
url: 'http://mysite.net/guest/is_logged_in',
type: 'POST',
crossDomain: true,
xhrFields: {
       withCredentials: true
  },

dataType: 'json',
success: function(data) {

    if(data.id) {
        window.location.replace("http://mysite.net");
    }
}
});

and

public function is_logged_in()
{
    $allowed = array(
        'http://mysite.net',
        'http://www.mysite.net',
        'http://www.mysite.com',
    );

    $url = $_SERVER['HTTP_REFERER'];
    $url = substr($url, 0, strpos($url, '/', 8));
    if(isset($_SERVER['HTTP_ORIGIN']))
    {
        if(in_array($_SERVER['HTTP_ORIGIN'], $allowed))
        {
            $this->output->set_header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
        }
    }
    else
    {
        if(in_array($url, $allowed))
        {
            $this->output->set_header('Access-Control-Allow-Origin: ' . $url);
        }
    }


    $this->output->set_header('Access-Control-Allow-Headers: X-Requested-With');
    $this->output->set_header('Access-Control-Allow-Credentials: true');
    $this->output->set_header("Access-Control-Expose-Headers: Access-Control-Allow-Origin");


    //TODO: Try to detect if this is an ajax request, and disallow it if not.

    $data = new stdClass();
    $this->load->library("ion_auth");
    if($this->ion_auth->logged_in())
    {
        $data->name = $this->ion_auth->user()->row()->first_name;
        $data->id = $this->ion_auth->get_user_id();
    } else {
        $data->id = false;
    }

    $this->output->set_output(json_encode($data));

}

Thanks in advance

Drew
  • 1,014
  • 2
  • 10
  • 21
  • 1
    By any chance you've got "Miscellaneous -> Access data sources across domains" setting in your Internet -> Security options set to disabled? – eithed Nov 25 '13 at 16:58
  • The fact that you're redirecting in the success makes me wonder if you need ajax for this at all. – Kevin B Nov 25 '13 at 17:02
  • As a matter of fact, it was set to "disabled". I enabled it, and it still doesn't work, but now there's no error either. – Drew Nov 25 '13 at 17:07
  • do you perhaps have an older version of this js (before you added the 'withCredentials' setting) sitting in your IE cache (IE loves to cache. Loves it)? Just guessing here. IE loves to cache data from ajax requests too. Make sure you use something like: $.ajaxSetup({cache: false}). – James Adam Nov 25 '13 at 17:13
  • The fact that it no longer gives you an error says that the ajax was successful (or at least that the server responded and the script had credentials to proceed). What is the response that the server is outputting? edit: maybe it's the `location.replace` thing? Try first checking if the code goes into the success block with just the `window.alert(data)` – eithed Nov 25 '13 at 17:23
  • I did some more digging: I opened up the network details and grabbed the response from the ajax call. It included a PHP error, because IE doesn't send the HTTP_ORIGIN header, where as I assume Chrome, Safari, and FF do. I fixed that, and now I get back the proper "not logged in" response. This means it's going through, checking, failing the check, and returning false. – Drew Nov 25 '13 at 19:28
  • @Drew - could you please tick your question as answered. I think that at least it will help people in future to diagnose initial problems. – eithed Nov 27 '13 at 17:44
  • p3p headers just works, here's the nginx config ( 1 line ! ) : https://gist.github.com/radzikowski/2908924 – vincent Feb 11 '15 at 19:27

6 Answers6

20

Changing the setting for "Access data sources across domains" to Enabled turns off cross-domain checks in IE and is horrifically unsafe. Instead, you need to ensure that the target 3rd-party resource sends a valid P3P policy that indicates that it's not doing horrible things to the user's privacy.

EricLaw
  • 56,563
  • 7
  • 151
  • 196
  • 2
    I looked into P3P, but decided against it as it's not really used. From Wikipedia > P3P was developed by the World Wide Web Consortium (W3C) and officially recommended on April 16, 2002. Development ceased shortly thereafter and there have been very few implementations of P3P. Microsoft Internet Explorer is the only major browser to support P3P – Drew Feb 14 '14 at 21:44
  • 45
    You: "Why doesn't my code work in IE?" Me: "Because IE requires P3P." You: "But P3P isn't really used, except in IE." Me: "..." – EricLaw Feb 17 '14 at 22:58
  • 6
    That's a very elegant way to put my stance (: And yes, if this was a more critical feature, I would be implementing a P3P policy. I'll give you the answer because you're technically correct, and that's the best kind of correct. – Drew Feb 19 '14 at 15:48
  • 2
    I added P3P in response header, but still no go. I can only change "Access data sources across domains" to allow to make it work! – kiford Apr 23 '15 at 02:36
  • I also tried to add P3P header in response and it didn't help. – termit May 25 '16 at 13:10
  • 1
    @termit: Because your problem is completely different than the original poster's. Please open a new question on StackOverflow and paste in the content of the F12 Script Debugger log when the scenarios fails. – EricLaw May 29 '16 at 00:39
  • @EricLaw I am using IE 11 (11.0.9600.18639) on Win 7 Pro and my target 3rd-party resource is setting following CP="ALL DSP COR CUR ADM TAI OUR IND COM NAV INT" I can see them fine in Fiddler but still I am seeing the warning popup "This page is access information that is not under it's control...". Please suggest what am I missing. – user961954 May 09 '17 at 01:16
  • @user961954: The P3P policy isn't what causes the "This page is accessing information..." warning. – EricLaw May 09 '17 at 19:17
  • @EricLaw Then can you please point me in the direction what does. Any pointer will be appreciated. I don't want to set "Access data sources across domains" but I can add Headers. – user961954 May 10 '17 at 01:15
  • 3
    The right way to ask a question on StackOverflow is to click the big blue "Ask a question" button on the top-right side of the page. Your question is: "How do I allow cross-origin access to data using CORS?" which has probably been asked many times already. – EricLaw May 10 '17 at 21:06
  • @EricLaw really had a laugh this morning. Thank you – Sergio A. Nov 19 '19 at 10:20
15

Found the issue.

I had a similar problem (using CORS in general, not specifically GWT). It turned out that the browser settings were blocking third-party cookies (IE10 > Internet Options > Privacy > Advanced > Third Party Cookies > Accept). To solve the problem, I checked "Override automatic cookie handling", "Accept" (Third-party Cookies) and "Always allow session cookies."

Andrew answered this question here: CORS doesn't work with cookies in IE10

EDIT: (Now that I know what to search for) This question may yield some help too, if anyone else runs into this issue. Internet Explorer 10 is ignoring XMLHttpRequest 'xhr.withCredentials = true'

Community
  • 1
  • 1
Drew
  • 1,014
  • 2
  • 10
  • 21
6

We had the problem that, except every other browser, the IE11 send Access-Control-Request-Headers: accept with the request, so "accept" had to be added to the allowedHeaders cors configuration, because it seems not to be part of the default spring cors configuration.

RiZKiT
  • 2,107
  • 28
  • 23
  • In my case it sends `Access-Control-Request-Headers: content-type, accept` – halfpastfour.am Sep 26 '18 at 14:01
  • This suggestion helped me fix an IE11 CORS issue with AWS API Gateway v2 (httpapi). In the CORS config our Access-Control-Allow-Headers whitelist is now: x-apigateway-header, authorization, content-type, accept. Works with an Axios Vue library too (saw another answer mention they couldn't get that to work). Thank you! – twamley Sep 29 '20 at 23:36
1

IE10 requires the server return a valid P3P policy in addition to CORS headers for cross domain requests. Here is sample php code for returning a P3P header from the server.

  $szOrigin = $_SERVER['HTTP_ORIGIN'];
  if ($szOrigin != null)
  {
        header("Access-Control-Allow-Origin: $szOrigin");
        header("Access-Control-Allow-Credentials: true");
        header("P3P: CP=\"ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"");
  }
3spot
  • 1,839
  • 1
  • 11
  • 5
0

After a lot of digging i found that the page that i'm pinging using ajax is on the internet zone while my current page in on the intranet zone.

IE 11 has the "Protected Mode" enabled for internet sites and when this is enabled cookies are not being sent to the site that i'm pinging even if they belong to that domain.

Adding the page to the trusted sites, or disabling "Protected Mode" solved the problem.

Note that this problem does not happen when both sites are in the internet zone even when "Protected Mode" is enabled.

Fadi
  • 55
  • 1
  • 10
0

I had similar problem and found that neither axios or jquery can be made to work with Internet Explorer and the preflight/CORS issue. Only good old XMLhttpRequest worked. Because in pure XMLhttpRequest we can do this:

if (xhttp.readyState == 4 && xhttp.status == 200)

It seems that axios and jquery take into account the status and not the readyState - they somehow interpret that there is a cors problem - and it takes a few ticks to reach readyState == 4 in IE.