Update 10/2010: A new working example with cleaned up code is available.
About six weeks ago, I wrote a post about some issues I was encountering with iframes and cross-domain security. I promised I would write about whatever workaround I decided to use; this post details that workaround. Warning: it feels more complicated than it is, and may take a while to get your head around. Once you get the gist of it, it’s actually a pretty straightforward system.
Recap of the issue
- The course interface loads content stored on a website at domain B, which is a completely unrelated website and not a subdomain of domain A. Let’s call this site content.org.
- The interface loads the external content into an iframe; this content includes course activities that must send a completion notice to the interface.
What’s a boy to do? Make a hack, of course. 😉
After searching high and low for answers, I decided to use a nested-iframe hack. From what i can tell, it’s a fairly common workaround. Here’s how it works:
- Parent frame is from domain A.
- Content in child frame (iframe) is from domain B.
Ok, ok, it’s starting to make your head spin, right? Well, what makes it even more complicated is that the nested frame can’t communicate with the child frame, either! In fact, it all seems like a pointless exercise until you add in one crucial ingredient: a querystring in the nested iframe’s URL.
Here’s how the final sequence of events would look:
- myLMS.com loads quiz question from content.org into an iframe.
- Before loading the nested iframe, a querystring is added to the URL, such as
Parent frame (myLMS.com)
Content iframe (content.org)
The content iframe, which is loaded from the external domain content.org, contains a function that creates the nested iframe element, then loads the proxy.html file with the proper querystring. You can invoke the proxy whenever you need it. In this example, it gets invoked via the
Nested “proxy” iframe (myLMS.com)
When the content iframe creates the nested proxy frame, it appends a querystring. The proxy frame therefore needs to examine the proxy’s window.location parameter for a querystring, then act on the value of the querystring.
If you remove the comments and extra line breaks, this is a very short script that weighs in at 16 lines. Also, as I mentioned in the comments, please don’t try to use
eval() on the querystring; it would be very unwise and would cause major security vulnerabilities, much like an SQL injection.
Thoughts and observations
Now that I’ve covered the basics, here are some general thoughts and observations on the topic.
Does this hack work in all browsers?
I can’t guarantee anything, but in my personal tests it worked in the following browsers: IE6 (XP), IE7 (Vista), Firefox 3 (XP, Vista, OS X, Ubuntu 8.10), Safari 3.1 (XP, Vista, OS X), and Opera 9.5 (XP, Vista, OS X).
Where is the proxy.html file stored?
In my example, the proxy.html file (used for the nested iframe) must be stored on the same domain as the parent file (the course interface); the key to this workaround is that the proxy.html file has unrestricted access to the topmost parent file, which it can only have when being served from the same domain.
Do the nested iframes screw up the back button?
Yes and no. I didn’t document what happens in which browser, but I know some browsers’ back buttons are unaffected by the nested iframe, while others will require one extra ‘back’ click. I don’t know about you, but I can live with one extra back button click.
What if I have some files that aren’t on a different domain?
document.domain can be used to find out what the current domain is for security purposes. A simple string search will tell you whether the content frame’s domain is found inside the querystring that was passed from the parent.
What if I have multiple actions I’d like to perform using the proxy?
Disclaimer: I have no affiliation with any real sites that may be located at mylms.com or content.org; these addresses were picked at random and only used for demonstration purposes.