Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Easy Cross-site Scripting using the easyXDM Library

4.80/5 (3 votes)
17 Aug 2009MIT4 min read 46.4K   641  
How to use the easyXDM JavaScript library to transmit messages and method calls between windows in different domains.

Introduction

Even though we, for security reasons, most often do not wish pages from different domains to be able to communicate, sometimes we do. And then, we discover that there is no 'proper' way to do so - the current standards and the current technologies are built to disallow it.

So we turn to workarounds, we use dynamic script tags included from external domains, we use JSONP, or we try our best using postMessage or the IFrame URL technique. These solutions often become quite complex and fragile, and transporting the pure string messages between the domains might very well end up making up most of your code.

Well, easyXDM (cross domain messaging) is now here, and it is meant to reduce the amount of work needed for cross-site communication - actually, it can do this in as little as 4 lines of code! And, if you want to be able to actually call methods across the boundary, well, that only takes 3 more!

See here for a demo of some of the functionality presented.

Background

This library was designed and built due to my company needing to expose an interface to one of our AJAX-applications. This application would have to be launched, and controlled to a certain degree from other web applications implementing our API, and our wish was to make it as reliable as possible (work both on IE6 and on FF3.5), and as easy to implement as possible. This has led us to easyXDM, which we are now publishing under an MIT-license.
easyXDM was previously called easyXDM, but due to it often being mislabelled as malware (XSS), we decided to change its name.

The library lives at easyxdm.net, where you can easily get access to the source, ready made packages and also the extensive documentation. In the documentation you also find several interesting demos.

Using the Code

The code presented here assumes that you have a website with a method (an API, weather service, stock service ..) that you want to expose. In this example, the method is called _privateDoMagic: it takes three arguments, and will return a JSON object.

What we want the API consumer to be able to do is call this method, like any other JavaScript method, and get the result back - something like this:

JavaScript
remote.doMagic('argument1',2,'three',function(result){
    // Consume the result
}

So first of all, we'll assume that the easyXDM library is present on both the page providing the API and the page consuming it, and that the JSON object is also present in both, either natively or via the json2 library.
With easyXDM you can actually use the following to load json2.js only when needed:

JavaScript
easyXDM.DomHelper.requiresJSON("/json2.js");

easyXDMs base functionality is that it provides a reliable mechanism for transporting string messages between domains, and it uses different techniques to do this depending on the browser.

But what easyXDM is also able to do is to take an interface configuration, where you describe the methods you want to expose, and the methods you want to consume, and transform it into working code - easyXDM does all the plumbing so that you can call the method in one domain, have the method call with arguments sent to the other domain, and have the result returned to the invoking method.

The interface is two-way, and both sides of the interface are able to expose and consume methods. The only difference in the configuration has to do with which side sets up the channel.

To expose the above-mentioned _privateDoMagic method, so that it can be consumed, all we need to do is insert the following code:

JavaScript
var remote = new easyXDM.Interface({}, {    
    local: {
        doMagic:{
            method: _privateDoMagic
        }
    }
});		

Here is the same code in a more compact form:

JavaScript
var remote = new easyXDM.Interface({},{local: {doMagic:{method: _privateDoMagic}}});
What we are doing here is creating a new easyXDM.Interface, using default values for our easyXDM.Channel, and an InterfaceConfiguration exposing a single method.
By omitting the settings for the channel, we are indicating that the library should use the default settings combined with the settings provided by the consumer.

That's all for the API provider!

Now, to consume this method, the following code is needed:

JavaScript
var remote = new easyXDM.Interface({
   local: "../hash.html",
   remote: "http://apiprovidersdomain.com/api.html"
},{
    remote: {
        doMagic: {}
    }
});

And again in compact form:

JavaScript
var remote=new easyXDM.Interface({local:"../hash.html",
	remote:"http://apiprovidersdomain.com/api.html"},{remote:{doMagic:{}}});

Again, we create an easyXDM.Interface, this time supplying the channels configuration in the first parameter.
The supplied settings here are the path to the local copy of hash.html, and the URL to the API providers endpoint.

And that's it.

The consumer is now able to call the method locally using:

JavaScript
remote.doMagic('argument1',2,'three',function(result){
    // Consume the result
}

and have the result returned.

Good luck! Or actually, with this library, you don't need it! :)

Points of interest

If you look at the source code, you will actually see that the implementation is quite simple. It's also well documented, and experienced developers should be able to understand how it works quite easily.

The debug version includes extensive tracing, and you can easily see what's going on. This is used in the examples.

History

  • 24th June, 2009: Initial post
  • 14th August, 2009: Article updated

License

This article, along with any associated source code and files, is licensed under The MIT License