Wednesday, November 9, 2011

jsonp for cross-site fun

So, today's fun:
We run a few different servers for testing: www is our live site, cert is for final testing, test is for preliminary testing, and we hack DNS a bit so that dev loops back to each developer's machine.

We have a single WordPress install that we use for our blog, as well as to store the content for certain activities on the site. My most recent project was to add a simple tag system that would change a WP slug like 
[lookup value="user.profile.firstName"] 
into a rest call to /rest/user/profile and substitution with the fieldName parameter. (I also added conditional tags, something like 
[start_if value="user.grade" is="GRADE10"]Welcome to Tenth[end_if]
would display "Welcome to Tenth" only if the endpoint said that was their grade.

So when you just have the one WP install there's an obvious small problem when you want to test before pushing live, that while WP (which I keep accidentally calling "WordPerfect" not "WordPress", a habit that is catching on at work) can do its own preview, it's not part of the whole dev/test/cert/www cycle. We added a "src=" type parameter, telling the plugin where to pull its javascript guts and then rest calls from, but... d'ohh... the rest calls were failing, losing out to the draconian cross site scripting rules. 

The cool kids solution to this is JSONP, JSON-with-Padding. (The wikipedia page for it is a decent introduction.) The server needs to be configured to recongize a jsonp request, and then it forms a response of the form "<script>yourcallback(THE DATA)</script>"-- script tags aren't beholden to the usual xss rules. (Which is kind of a headscratcher, given that running code from another site seems to be a lot more dangerous than just grabbing data, but sometimes you have to take what you can get.)

So, in practice, I made a version of our wrapper for getting JSON that added a parameter dataType: "jsonp" to the jQuery.ajax call. We then ran smackdab into a kind of known Firefox issue (I'm not sure if us using a more up to date version of jQuery would have helped or not) where Firefox thinks that the JSON, what with its hashes and : and all, looks like it's trying to generate labels (what is this, BASIC?) and spits up "invalid label"... our fix for that was in the middle tier, a known solution is that wrapping the data in an additional set of parentheses fixes it, so that's what we did.

There's of course a bit of a security concern when you're allowing shenanigans like this-- especially if we were showing content from one user to another user. We'll look for some ways to tighten that up.

No comments:

Post a Comment