window.name Transport July 22nd, 2008 at 12:04 am by Kris Zyp
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?
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.
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.
Tags: cross-domain, cross-site, secure, window.name



Posted July 23rd, 2008 at 5:09 am
[…] have written about using window.name as a transport and Kris Zyp has just posted about how Dojo has created a new dojox.io.windowName module. The window.name transport is a new technique for secure cross-domain browser based data transfer, […]
Posted July 23rd, 2008 at 7:40 am
[…] Ça se passe ici, et c’est vraiment épatant. Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin : addthis_url=location.href;addthis_title=document.title;addthis_pub=’Nix’; Posted: mercredi 23 juillet 2008 16:37 par KooKiz Classé sous : Javascript, AJAX […]
Posted July 23rd, 2008 at 11:51 am
Kirs,
Great work as usual. I’ve been thinking about using this technique for Jabbify (http://jabbify.com) and adding something to JavaScriptMVC. Currently, we support REST based JSONP. I’ve got it able to do writes by breaking up the message into small chunks.
Window.name would allow much bigger chunks, and security. But before I make the switch, I have a few questions about your implementation.
Are you basically creating an iframe, and then polling for window.name to change? Or is there another way to know when the iframe has loaded.
Should/do you remove window.name on unload to prevent other pages from getting it?
Should/do you remove the iframe when you are done with it? Or do you just keep using the same one?
Thanks for your help,
Justin
Posted July 23rd, 2008 at 12:42 pm
I presume that dojo.fromJson does not use eval. Seems to me that you can get either security or speed using window.name, but not both. Using eval, you can get the speed of XHR with the cross site feature of JSONP, but using a native JavaScript JSON parser instead of eval you would get cross-siteness and a modicum of security. I think we need performance metrics. It’s a very clever epiphany in any case.
Posted July 23rd, 2008 at 3:11 pm
dojo.fromJson does use eval, which is why it is not safe to use dojo.fromJson without doing JSON validation first. I will cover that more in the next blog post on security. And you are right that performance metrics would be helpful as well.
Posted July 23rd, 2008 at 11:49 pm
[…] Link: window.name transport […]
Posted July 24th, 2008 at 4:54 pm
Cool idea guys, you just solved a pressing problem. I snooped your implementation and implemented it in GWT, see here: http://timepedia.blogspot.com/2008/07/cross-domain-formpanel-submissions-in.html
I adopted your URL convention (windowname=true) for interoperability purposes. It would be nice if, like JSONP, this convention or something like it gets standardized.
-Ray
Posted July 27th, 2008 at 3:16 pm
[…] SitePen Blog » window.name Transport […]
Posted July 28th, 2008 at 2:46 pm
[…] forward to 2008. Kris Zyp has implemented a cross-domain transport for the Dojo JavaScript library using window.name. Kudos to Zyp for doing the legwork to turn the window.name oddity into a usable data transport […]
Posted July 31st, 2008 at 3:17 pm
[…] can also use the window.name module as an XHR plugin as well. There is a specific module to make this easy to add, so you can simply […]
Posted August 1st, 2008 at 6:44 am
[…] loading mechanism, but Dojo includes transports for those servers lacking cross-domain support. The window.name transport can be used for servers that support the window.name protocol, and native cross-site XHR can be […]
Posted August 5th, 2008 at 8:00 pm
Kris,
I’m amazed that you are building a form and then submitting it!
I’m sure this is naive, but would it be possible to make the frame load a page, check window.name, and then do an XHR request? When the request comes back, it updates window.name.
I guess you would lose the onload functionality and would have to resort to polling. Is this the only reason why? Thanks!
Posted August 5th, 2008 at 8:20 pm
I guess performance would suffer too.
Posted August 5th, 2008 at 9:24 pm
@Justin: The latest version (in SVN/nightlies) supports setting the window.name property asynchronously. It does this in “authorization mode” where you provide an authorization element so the iframe can interact with the user before handing over information the requesting page. Once the window.name variable is set the target page is responsible for navigating back to a return URL. You could also use this async/auth mode for doing an XHR request if you wanted. I will probably do another post explaining the async/auth functionality more, but it is based on Neil’s post http://www.sitepen.com/blog/2008/07/30/protected-cross-domain-authentication-with-javascript/.
Posted August 6th, 2008 at 10:23 am
Kris,
Thanks for the reply. I understand how it works. I’ve made a non-dojo version in http://tinyurl.com/5pwk8c.
I am more wondering if there are other ways of doing it. I’m planning on using it for a Comet request (for http://jabbify.com). But, during the log poll, the mouse shows a waiting hourglass.
I need to get rid of that hourglass.
Posted August 6th, 2008 at 10:24 am
Sorry, that link is
http://tinyurl.com/5pwk8c
Posted August 6th, 2008 at 10:26 am
Also, make sure your content type is text/html. I had mine at text/plain and the browser will put the form results in a tag inside the hidden iframe. This prevents the script tag from executing.
Posted August 14th, 2008 at 1:09 pm
The problem with this technique is that if you use it with IE, redirecting the iframe causes the click sound to fire. Overusing it will make the page sound like firecrackers are going off. I think it still has uses however if the cross domain requests are linked to actual clicks made by the user. I wrote a Jquery version based on the dojo one but it uses one iframe instead of many.
Posted August 14th, 2008 at 2:08 pm
@Ian:
This is an issue, but in contrast to fragment identifier messaging where a click occurs for each ~2K packet, the windowName module is much quieter.
That is great to hear you built a jquery one, do you have a URL for it? I am curious what you mean when you said your impl only uses one iframe? dojox.io.windowName only uses one iframe, except in the case of FF2 where it must use nested iframes in order to prevent frame-to-frame messaging theft.
Posted August 18th, 2008 at 3:25 pm
[…] new windowName module (dojox.io.windowName) now includes support for resource authorization as Neil Roberts described in his article on xauth. […]
Posted August 20th, 2008 at 9:46 am
Hi
I am relatively new to Javascript and dojo.
I am trying to do cross-domain communication with somewhat large data sets. When using the cross frame framework at http://www.julienlecomte.net/blog/2007/11/31/, I ran into the IE limitation of the length of message (around 4K.) I am now trying to find out a way to overcome this in a browser-independent fashion. My requirement is as follows:
1. The main page has an iframe that points to a different domain.
2. I want to send a message to the iframe (the message should be received by a Javascript method hosted within the iframe.)
3. The iframe then does something and can send another message that is intercepted by the Javascript code running in the main page.
These messages can be larger than 4K but should be less than
1M.
I tried to use the dojo 1.1.1 proxy method in the dojox but I am unable to run the example in the “tests” directory provided in the code (I believe I did follow the instructions on modifying the files.)
I am wondering if window.name transport can be used. If so, is the code available right now since dojo 1.2 does not seem to have been released as yet?
Posted August 23rd, 2008 at 8:12 pm
@Menon: Currently the window.name transport is only designed for “loading” data from other domains; it hasn’t be adapted for full cross-frame messaging because we change the frame back to the original domain in order to access the window.name value, and this effectively “destroys” the child frame once the data is loaded. We are considering adding a cross-frame messaging system in the future using this technique (with nested iframes).
If you only need to send a single message and receive a single message before destroying the child, this may still be viable with the new Dojo module. You can download the Dojo nightlies (with the windowName module) at http://archive.dojotoolkit.org/nightly/.
Posted September 9th, 2008 at 3:03 pm
[…] we demonstrated the window.name technique for communicating with servers via a proxy frame that can relay information back to the requesting […]
Posted September 25th, 2008 at 12:43 am
[…] window.name - This is the new technique we have developed for securely loading cross-site data. […]
Posted October 7th, 2008 at 7:35 pm
I don’t understand how this protects against untrusted sources. You would need access to the service in order to make the responses implement the window.name=. If you have access to the server code, it’s pretty much going to be trusted then, isn’t it? Am I missing something?
Posted October 8th, 2008 at 5:20 am
@JP: Parties can independently implement the window.name protocol. I have implemented window.name for http://persevere.sitepen.com/, but that doesn’t mean you trust that site, however you can still access the site from a web page without trusting it.
Posted October 8th, 2008 at 3:25 pm
I’ve ported this to jQuery as a plugin and added the possibility to send data that includes submit, target, method and action values. You can check the code at http://friedcellcollective.net/outbreak/jsjquerywindownameplugin/.
Posted October 29th, 2008 at 10:04 pm
Has this been tested on safari 3?
i get
Unsafe JavaScript attempt to access frame with URL http://skylined.org/~fry/js/jQuery.windowName/test.php from frame with URL http://friedcellcollective.net/js/jQuery.windowName/test.html. Domains, protocols and ports must match.
when trying the demo page.
Posted October 30th, 2008 at 6:53 am
@john: I assume you are talking about the jQuery version, which may not work Safari 3. The Dojo version that I wrote has been tested and does work on Safari 3.
Posted November 18th, 2008 at 10:24 am
[…] to the XMLHttpRequest object. Persevere supports both JSONP (scripts with callbacks) and the window.name protocol for providing data for cross-domain web clients. CouchDB does not provide a facility for handling […]