11

The Very Short Version: is anybody successfully requesting local resources via AJAX, in IE, over SSL? I cannot solve getting an "access denied" error.


The Longer Version:

I am using AJAX to retrieve JSON from an application that runs a local web service. The web service channel is encrypted so that if the remote site is being served over HTTPS, no "insecure resource on a secure page" errors appear.

So, in the address bar is a remote site of some sort... mysite.com. It is receiving information from https://localhost/.

The web service is setting correct headers for CORS and everything works in Chrome and Firefox. In IE, if I put my https://localhost resource into the address bar, the correct resource is returned and displayed. However, when using AJAX (not just the address bar), a security setting in IE is denying access. This is documented (in part) here:

Access denied in IE 10 and 11 when ajax target is localhost

The only proper solution in one reply is to add the requesting domain (mysite.com in this case) to the trusted sites. This works, but we would prefer to not have user intervention... pointing to a knowledge base article on how to add a trusted site is hardly a great user experience. The other replies to that question are invalid for the same reasons as below-->

Some more stumbling around and I discovered this:

CORS with IE, XMLHttpRequest and ssl (https)

Which had a reply containing a wrapper for AJAX requests in IE. It seemed promising, but as it turns out, IE11 has now deprecated the XDomainRequest API. This was probably the right thing for Microsoft to do... but now the "hack" workaround of adding a void onProgress handler to the XDR object is obviously not an option and the once-promising workaround wrapper is rendered null and void.

Has anybody come across either:

a) a way to get those requests through without needing to modify the trusted sites in IE? In other words, an updated version of the workaround in the second link?

b) as a "next best" case: a way to prompt the user to add the site to their trusted zone? "mysite.com wishes to be added to your trusted zones. Confirm Yes/No" and have it done, without them actually needing to open up their native settings dialogues and doing it manually?

Community
  • 1
  • 1
Greg Pettit
  • 10,305
  • 4
  • 47
  • 68

2 Answers2

7

For security reasons, Internet Explorer's XDomainRequest object blocks access (see #6 here) to the Intranet Zone from the Internet Zone. I would not be surprised to learn that this block was ported into the IE10+ CORS implementation for the XMLHTTPRequest object.

One approach which may help is to simply change from localhost to 127.0.0.1 as the latter is treated as Internet Zone rather than Intranet Zone and as a consequence the zone-crossing is avoided.

However, you should be aware that Internet Explorer 10+ will block all access to the local computer (via any address) when a site is running in Enhanced Protected Mode (EPM)-- see "Loopback blocked" in this post. Currently, IE uses EPM only for Internet sites when run in the Metro/Immersive browsing mode (not in Desktop) but this could change in the future.

No, there's no mechanism to show the Zones-Configuration UI from JavaScript or to automatically move a site from one zone to another. However, the fact that you have a local server implies that you are running code on the client already, which means you could use the appropriate API to update the Zone Mapping on the client. Note that such a change requires that you CLEARLY obtain user permission first, lest your installer be treated as malware by Windows Defender and other security products.

So, in summary, using the IP address should serve as a workaround for many, but not all platforms.

Community
  • 1
  • 1
EricLaw
  • 54,427
  • 7
  • 140
  • 182
  • Thank you for the detailed response, Eric. I will pass along that "use the appropriate API" link to the desktop application developer; my initial thought is that this is exactly what we would want to do. There's no requirement that we do it through JavaScript or the browser itself, though I may have inadvertently implied that. – Greg Pettit Apr 24 '14 at 15:12
  • That said, even as I navigated away from this answer, I realized... the desktop application doesn't know which domain needs to be added. :( I still see two "kinda better than nothing" options-- using the appropriate API to allow the application's own dialog (which will be simpler than instructions on navigating IE settings) or creating the ability to supply a domain to the installer at download time (via a script or even a flat file of some sort). – Greg Pettit Apr 24 '14 at 15:15
  • 1
    +1 for describing `Internet Zone` vs `Intranet Zone`. That solved my problem, thank you! – Brad Cupit May 05 '14 at 12:40
  • Internet vs Intranet was my problem. Just as a heads up, it effects IE up to version 11 (most recent version available). – Erikk Ross Feb 18 '15 at 20:48
  • +1. Confirmed in IE11 the AJAX request works when using 127.0.0.1 instead of localhost. Seems to "trick" it to thinking it's still in the internet zone – stonedauwg May 08 '15 at 21:12
  • @EricLaw Thanks for the post! It is quite elucidating. However, it disagrees with [your MSDN blog post](http://blogs.msdn.com/b/ieinternals/archive/2012/03/23/understanding-ie10-enhanced-protected-mode-network-security-addons-cookies-metro-desktop.aspx) (circa 2012) as to how `localhost` and `127.0.0.1` are mapped into security zones. Which one is correct? Thanks! – jpaugh Dec 04 '15 at 17:37
  • @jpaugh - I'm afraid I don't understand what "disagreement" you see? "localhost" is Intranet Zone, "127.0.0.1" is Internet Zone. – EricLaw Dec 04 '15 at 20:48
  • Tried all sort of things until I stumbled across this article. I was running the site under IIS Express and changing the server to bind to 127.0.0.1 and then using the IP instead of localhost solved the issue. IE11 and Firefox both are now sending the authentication cookie. Thanks – Jim Scott May 27 '16 at 02:01
0

Since those are two different domains, one solution would be to create an application which proxies the requests in the direction you want.

If you have control over the example.com end, and want to support users who bring their own localhost service, this would be harder, as you would have to provide more requirements for what they bring.

If however, you have control over what runs in localhost, and want to access example.com, and have it access the localhost service, set up redirection in your web server of preference, or use a reverse proxy. You could add an endpoint to the same localhost app which doesn't overlap paths, for example, route http://localhost/proxy/%1 to http://%1, leaving the rest of localhost alone. Or, run a proxy on e.g. http://localhost:8080 which performs a similar redirection, and can serve example.com from a path, and the API from another.

This winds up being a type of "glue" or integration code, which should allow you to mock interactions up to a point.

maxwellb
  • 11,744
  • 2
  • 21
  • 33
  • So if I'm understanding correctly, the proxy application in this model provides not only the data (as it already does) but also the web content. Is that the bottom line? Then to get the address bar transparently appear to be accessing "example.com" (instead of localhost), it's done with redirection set up on the web server? It's good thinking, and I believe it's already on the roadmap. For initial release we are not in control of the server-side web beyond providing the necessary UI components. – Greg Pettit May 01 '14 at 16:30
  • 1
    That's correct. You can only control what you can control. I don't know what setup works best for you, but if you needs must embed links to http://localhost/api/ajaxFunction within a page on example.com, then you can host a proxy on localhost, so that for example http://localhost/w/example.com loads example.com, and http://localhost/api/ajaxFunction loads the script. Then the example.com page proxied through localhost will not have the CORS problem. – maxwellb May 06 '14 at 02:10