Simple cross-domain ajax with a wormhole

At NetWallet, we need to embed our application in a host page and communicate securely with our backend servers using cross-domain ajax.  Some of the standard techniques for performing cross-domain requests won’t work for us: we can’t expect all third parties to proxy requests (this would be practically infeasible, let alone insecure), nor can we use jsonp because we need to set cookies from our domain to verify user and machine identities. Instead, we’ll create a wormhole.

The basic idea is to create an iframe in the host page that loads content from our domain. This is the idea behind the ‘post to iframe’ trick used by Facebook, among others. As a variant of this technique, we’ve been using porthole.js to set up an iframe to which we can post messages, and from which we can receive messages. This works, but we wanted to wrap this low-level interface into something slightly more convenient.  We like jQuery’s ajax method, so we’ll try to imitate that.  In the end we’ll have a communication channel that lets us quickly and easily talk to another domain almost as if it were right here, which is why we call it a wormhole: it bridges time and space!

On the host page, the wormhole frontend, we create an Ember object (did I mention we’re using Ember.js?) that sets up the porthole windowProxy and listens for messages from it.  This object also has an ajax method that emulates jQuery.ajax, taking a standard settings object. When Wormhole.ajax is called, we create a Deferred to handle the result and store this deferred in a dictionary, indexed by a unique request id. Then, we simply send the settings object through the porthole to be handled on the other side, and we return a promise that the deferred will eventually be fulfilled. When the response comes back from the porthole, Wormhole.onResponse is called and we simply pop the matching deferred out of the dictionary and resolve or reject it, depending on whether the request succeeded or failed.

For convenience, we even handle ajax requests that are made before the iframe has loaded by stuffing those requests into a queue and then sending them when we get a message that the porthole is ready. That way clients can use the Wormhole immediately after it has been created, without themselves waiting for it to be established.

To make this all work the backend page which is pulled down into the iframe from wormholeUrl runs a simple script that sets up the porthole windowProxy from its side, sends a ready message, and then listens for requests posted from the frontend. When a request comes in, it fires off a real jquery ajax call, no cross-domain hoops to jump through, and then sends a response message back through the porthole when the request is complete, indicating whether the call succeeded or failed.

Here’s the code:

Et voila! We can now make cross-domain requests through our iframe using the convenient jQuery.ajax interface. We’re working on interesting problems like these at NetWallet every day, and we’re hiring!

About these ads

, , ,

  1. #1 by Gabriel Claramunt (@gclaramunt) on April 30, 2012 - 7:03 pm

    Interesting technique… that doesn’t cause any security warnings?

    • #2 by matthew on April 30, 2012 - 7:29 pm

      No warnings. Porthole.js allows you to send messages back and forth between iframes, which is the tricky part from the point of view of cross-domain security warnings; we just wrap a more convenient around that low-level messaging interface.

  2. #3 by Jamesu on June 6, 2012 - 12:21 am

    Thanks for this write up. It has helped me to have a 70% understanding on how i can create an embedable widget that i can give 3rd-party sites using emberjs.

    But one thing you didn’t show is an example of the javascript that you will give these 3rd party sites to paste into their websites. Do you mind adding an example of that to the article or this comment section.

    Thanks again for the write up.

    • #4 by matthew on June 6, 2012 - 4:53 pm

      The wormhole_frontend.js script needs to run in the 3rd-party page. So conceptually the snippet to be pasted in to the 3rd-party site could be just a script tag like <script type="application/javascript" src="http://www.yoursite.com/wormhole_frontend.js">. However, if you want to use Ember and other libraries you would need to ensure that they get loaded as well, so you need some bootstrap code to load library dependencies and only then start the wormhole. We use script.js to do the dependency loading, before spinning up the wormhole. Does that help? I can try to work up a more complete example to make things a bit more concrete.

      • #5 by Jamesu on June 7, 2012 - 9:16 am

        What a great answer. You knocked out all my confusion especially with the bit on the dependency loading.

        Thanks for the quality answer.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: