The window.name transport is a new technique for secure cross-domain browser based data transfer, and can be utilized for creating secure mashups with untrusted sources. window.name is implemented in Dojo in the new dojox.io.windowName module, and it is very easy to make web services available through the window.name protocol. window.name works by loading a cross-domain HTML file in an iframe. The HTML file then sets its window.name to the string content that should be delivered to the requester. The requester can then retrieve the window.name value as the response. The requested resource never has access to the requester’s environment (JavaScript variables, cookies, and DOM).

Dojo API

To use the window.name transport, you can use dojox.io.windowName‘s single function, send, with an API very similar to dojo.xhr:

dojox.io.windowName.send(method, args);

The method parameter can be GET or POST. The args parameter is an object that provides the target URL and other information per the Dojo ioArgs API. When you call dojox.io.windowName.send, it will send the specified request and return a dojo.Deferred object, which you can listen to for the response. For example:

var deferred = dojox.io.windowName.send("GET", {url:"http://somesite.com/resource"});
deferred.addCallback(function(result){
  alert("The request returned " + result);
});

Making Web Services Available with window.name

In order to implement window.name with web services (REST or RPC), the server should simply look for requests that include a parameter windowname. If the windowname parameter is included, the server should respond to the request with an HTML document that sets its window.name to the string that is to be delivered to the client. For example, if a client makes a window.name request like:

http://othersite.com/greeting?windowname=true

And if the server wants to respond to the client with Hello, it should return an html page:

<html>
<script type="text/javascript">
window.name="Hello";
</script>
</html>

The value returned to the client will be Hello. One can easily transfer JSON data as well:

<html>
<script type="text/javascript">
window.name='{"foo":"bar"}';
</script>
</html>

The client will than receive the JSON data as a string which can then be parsed with a JSON parser like dojo.fromJson. On the client side, it is highly recommended you use a JSON or secure JavaScript validator if you want to prevent arbitrary code execution and unrestrained access to your environment from the target web service data. To securely parse the JSON, you can test the JSON with the dojox.secure.capability validator prior to calling fromJson:

var deferred = dojox.io.windowName.send("GET", {url:"http://somesite.com/resource"});
deferred.addCallback(function(result){
  // capability.validate will throw an error 
  // if there is unsafe script code in the JSON
  dojox.secure.capability.validate(result,[],{});
  console.log("received object", dojo.fromJson(result));
});

Writing extensive multi-line JSON objects in a quoted string can be rather difficult and error-prone if you are manually creating resources. You can use this template HTML to easily create JSON data that will be delivered as a JSON string without having to manually escape the JSON as a string:

<html>
<script type="\'text/javascript\'">
  window.name = document.getElementsByTagName("script")[0]
    .innerHTML.match(/temp\s*=([\w\W]*)/)[1];
  temp= {foo:"bar", // put json data here



 	baz:"foo"}
</script>
</html>

Likewise, if you want to deliver HTML/XML data, here is a template for doing so without manually putting all the data in a string:

<html>
<body>
<p id="content">
some <strong>html/xml-style</strong>data
</p>
</body>
<script type="\'text/javascript\'">
 window.name = document.getElementById("content").innerHTML;
</script>
</html>

This module has been tested on Firefox 2 and 3, Safari 3, IE 6 and 7, and Opera 9. You can see a simple test/demo page that loads data using the window.name protocol. By default, this demo loads data from our Persevere server, which now supports this protocol.

Benefits

This technique has several advantages over other cross-domain transports:

  • It is secure, JSONP is not. That is, it is as secure as other frame based secure transports like fragment identifier messaging (FIM), and Subspace. (I)Frames also have their own security issues because frames can change other frames locations, but that is quite a different security exploit, and generally far less serious.
  • It is much faster than FIM, because it doesn’t have to deal with small packet size of a fragment identifier, and it doesn’t have as many “machine gun” sound effects on IE. It is also faster than Subspace. Subspace requires two iframes and two local HTML files to be loaded to do a request. window.name only requires one iframe and one local file.
  • It is simpler and more secure than Subspace and FIM. FIM is somewhat complicated, and Subspace is very complicated. Subspace also has a number of extra restrictions and setup requirements, like declaring all of the target hosts in advance and having DNS entries for a number of different particular hosts. window.name is very simple and easy to use.
  • It does not require any plugins (like Flash) or alternate technologies (like Java).

How does it work?

windowname.png Of course you can use the new windowName module without understanding how it works, but since this is a tool for protecting against miscreant web services, you may wish to understand how it provides protection. name is a property of the global/window object in the browser environment, and the value of the name property remains the same as new pages are navigated for the frame. By loading a resource in an iframe where the target page will set the name property for its frame, this name property value can be retrieved to access the information sent by the web service. The name property is only accessible for frames that are in the same domain. This means that Dojo must navigate the frame back to the origin domain after the remote web service page has been loaded, in order to access the name property. This same-origin policy also protects against other frames from accessing the name property while Dojo is retrieving the value. Once the name property is retrieved, the frame is destroyed.

At the top level, the name property is not secure, any information put in the name property is available for all subsequent pages. However, the windowName module always loads resources in an iframe. The iframe is destroyed once the data is retrieved, or when you navigate to a new page at the top level, so other pages never have access to the window.name property.

The principle vector of attack is for other frames to attempt to access the loading frame and navigate that frame to their own domain in order to access the name property (using the same technique that Dojo does). However, navigating frames that are not child or parent frames is not permitted in most browsers, and therefore the third party frames are blocked from this action by the browser. Only the main frame that is loading the resources can access this information. Unfortunately, Firefox 2 does not block this action. Consequently, the windowName module uses a set of three nested frames, where 1st frame blocks all frame traversal to the 2nd frame using dynamically installed getters that return null. This means that third party frames can never traverse the frames to get a reference to the 2nd or 3rd frames, and consequently can never induce navigation of the target frame (the 3rd frame) in order to access the name property. Same-origin security prevents the third party frame from removing the installed getter that protects access to the inner frames as well. These measures protect against attacks and ensure that data can be delivered securely.

The idea for the window.name transport is based Thomas Franke‘s library for doing session variables with window.name, but this obviously has a completely different goal.

Cross Domain Builds

If you are using Dojo from a CDN or a cross domain build, you will need to set dojo.config.dojoCallbackUrl (which can be set through the djConfig attribute in the dojo.js script tag) to the URL of a blank.html on your server.

Conclusion

The next generation of browsers will most likely include native capabilities for securely accessing resources from other sites, however it is extremely valuable to have a safe, efficient means for loading data from other domains with current browsers, in order to build secure mashups. The window.name transport provides an efficient secure mechanism for loading data and can play an important role as a foundation for client-side mashups for current and legacy browser technology. The new Dojo windowName module is an easy to use tool for leveraging this transport, and handles the cross-browser issues and protects against the different attack vectors so you can safely utilize this protocol. The Dojo windowName module is available in nightly Dojo builds, and will be available with Dojo 1.2.