The future of cross-domain Ajax

From Jimbojw.com

Jump to: navigation, search
Tip: This is part of the Weekly Web Hack article series. If you like it, please subscribe to my blog. Thanks!

This Weekly Web Hack is the third in a four part series on cross-domain scripting. Moving even further away from the "traditional" solutions, this article discusses a few competing schemes to extend cross-domain data access and finally reveals a proof-of-concept Greasemonkey script for lifting all cross-domain restrictions.

I've already written a thorough introduction to cross-domain Ajax, and described how to do cross-domain Ajax via Flash using my SWFHttpRequest Flash/Ajax Utility. So I'll assume you have a pretty solid understanding of XMLHttpRequest, the same origin policy, Adobe's approach to cross-domain data access (called crossdomain.xml), and their collective effect on the cross-domain scripting landscape.

Proposed and forthcoming "solutions"

The policies controlling who can access what and from where have been in place for years now, but that's not to say that nothing has been done. Almost as long as Ajax has been a buzzword, various voices on the Internet have spoken out against the overly restrictive same-origin policy.

In April of 2006, Douglas Crockford (of json.org fame) proposed JSONRequest. In his detailed proposal, he explains:

XMLHttpRequest has a security model which is inadequate for supporting the next generation of web applications. JSONRequest is proposed as a new browser service that allows for two-way data exchange with any JSON data server without exposing users or organization to harm.

He goes on to say that:

The next generation of web applications will be much more data intensive. They will want to go to a server, any server, and exchange data. The XMLHttpRequest interface suggests, but does not achieve, this. It is severely limited by a defective security model. ... The Same Origin Policy frustrates these [Cross Site Scripting] attacks, but it also frustrates a larger class of legitimate uses. It should be possible for a script in a page to access data from other servers without compromising the security of the user or his organization.

More recently, the W3C has posted a working draft detailing Access Control for Cross-site Requests. Although it doesn't mention JSON, it does include a number of Douglas' recommendations regarding Cookies and HTTP headers.

Kris Zyp has a good writeup titled W3C - Enabling Read Access for Web Resources in which he explains the (minimal) impact this proposal has on XHR security and offers a side-by-side comparison of the JSONRequest and W3C proposals.

According to the comments Mozilla's bugzilla bug 389508, this has already been implemented in Mozilla's SVN trunk as of July 2007 following these design details. All signs indicate that cross-domain XMLHttpRequest calls will be available in Firefox 3 - which is in public beta at the time of this writing.

Too little too late?

Given that the cross-domain policy file used by the Flash runtime already allows third-party access to web services, one has to wonder whether the W3C draft is too little too late. After all, using SWFHttpRequest, it's trivial to make cross-domain requests using flash as an intermediary.

The answer, as is too often the case, is yes and no. It's certainly nice that there is an attempt to finally broaden the scope of cross-domain accessibility. Here are a few pros of the W3C proposal:

  • It takes into account different HTTP request methods as a basis for access restriction.
  • It restricts the presentation of cookies in cross-domain requests.
  • Finally, not everyone has Flash player installed, and in some contexts (such as with handheld devices) installing Flash may not even be possible.

However, it falls short in the following ways:

  • Like crossdomain.xml, the W3C proposal dosen't offer any protection or flexibility for applications co-hosted on the same domain. The HTTP headers apply in an all-or-nothing fashion, with no accounting for paths.
  • Unlike crossdomain.xml, which is just a file, the W3C plan requires sending new custom HTTP headers. This is more complicated, and will be comparatively more difficult for service-providers to implement.
  • Like any W3C standard, its uptake will be gruesomely slow. Internet Explorer versions 6 and 7 will NEVER support it, and it is unknown whether IE 8 will. In any case, it'll be a long time before the majority of Internet users will have sufficient browser power to utilize this.

Going off the deep end

The biggest problem with both Adobe's scheme and the W3C's option is that they require third-party buy-in. The service provider has to explicitly agree to allow other sites to access their data. In nearly all discussions on XHR security, it's considered blasphemy to suggest that one site should be able to access and utilize another site's resources without the latter condoning the activity.

Lest we forget that this kind of thing happens all the time. Images are prime targets for hotlinking, a practice which continues to this day. Frames and IFrames are still used to display one site "within" another. And of course, dynamic <script> tag injection is used to grab JavaScript and JSON data across domain lines.

Herein lies the paradox. Since all the present and planned cross-domain access controls require the service provider to "opt in" to allowing their data to be accessed, they could just implement an On-Demand Javascript solution and call it a day. Why require a Flash intermediary or a bleeding-edge browser when JSONP offers a ready and supremely backwards-compatible solution?

Nearly all of the discussion surrounding how to do cross-domain requests is moot when you remember that they require the consent of the target web service. If the web service provider has to consent, why can't they just provide a JavaScript solution? It boggles the mind.

A modest proposal

What the Internet needs is inversion of access control. Rather than the service providers publishing who can use what, it should be up to the end-user to decide whether the web-application they're using should be able to make those requests (provided the third-party hasn't already explicitly allowed it).

That is, rather than outright preventing somedomain.com from making requests to someotherdomain.com, maybe we should ask the user whether they'd like to allow it? Coming up with a UI to make this painless for all parties is the tough part. Nobody wants to see "This web application is trying to access someotherdomain.com, Cancel or Allow?"

Greasemonkey makes headway in this department, providing a function called GM_xmlhttprequest, which can be used to issue cross-domain requests to anywhere. Unfortunately, it doesn't follow the W3C's XMLHttpRequest specification, so it's a pain to use with Ajax libraries out-of-the-box.

For this reason, I have created GMHttpRequest - a JavaScript object which behaves like XMLHttpRequest, but utilizing GM_xmlhttprequest for its underlying data transport. To see it in action:

  1. Download and install Greasemonkey, if you haven't already. (You'll need to restart Firefox for it to take effect)
  2. Install my GMHttpRequest userscript.
  3. Check out the GMHttpRequest Demo.

Note: The Greasemonkey userscript only works with the demo (that exact URL). This is to protect users from the dangers of unbridled cross-domain access.

The above is merely a proof-of-concept implementation, demonstrating what becomes possible when you lift the heavy hand of the same-origin policy. A real solution to open cross-domain access will require careful planning. Stay tuned.


Got something to say?

Leave a comment
Sorry, comments are disabled.

or, read what others have said...