Image may be NSFW.
Clik here to view. This evening I had the opportunity to implement what should have been a simple OAuth signature validation until I ran into trouble parsing the parameters of the request. I decided to use one of the many pre-built libraries instead of rolling my own (perhaps that’s where I went wrong) but I found that it wasn’t as easy as I had expected.
A quick primer for those unfamiliar with PHP, there are multiple variables that hold request information. The two most common for passing parameters to a PHP script are $_GET and $_POST, which are both associative arrays. PHP handles the encoding of the values and brings everything back to regular strings. This is very handy for passing data. There is one more useful structure called $_REQUEST that actually holds both sets of values in one structure – also very handy if you don’t know where your data will be coming from on a given request. Now back to my issue.
OAuth augments your parameters with a few specific values that are unique to it’s implementation and uses a shared secret key system to digitally sign requests providing a level of trust with any request. If your lost with OAuth, I wrote a quick primer about it a month or so ago. OAuth takes any data you pass and signs them into a hashed value by concatenating the data with the shared secret and a few other parameters. The resulting hash is then very unique and very difficult to guess. On the server side, you can now validate the request by looking at the parameters and re-calculating the hash value.
While that’s simple in theory, it’s a bit more difficult in practice, especially with MySpace’s implementation of OpenSocial and OAuth. Yesterday I blogged about how to make AJAX requests using OpenSocial. As a habit, I always default requests to POST when possible to get around any arbitrary data size limits that might be present and to keep data out of my log files. This resulted in quite a bit of drama trying to implement the signature because the library wanted to evaluate the POST parameters and MySpace sends them as GET values. I tried tweaking the library to use the generic $_REQUEST parameters, however, the $_POST values weren’t included in the hash! As a result I ended up moving all requests over to use get – which was very simple.
Below you’ll find the revised GET friendly code:
function ajaxRequest(url, callback_func, post_params){ var queryString = ""; for (k in post_params) { queryString += "&" + k + "=" + encodeURIComponent(post_params[k]); } url += "?" + queryString; var osParams = {}; osParams[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED; gadgets.io.makeRequest(url, makeRequest_callback, osParams); function makeRequest_callback(data){ renderStatus("Handling ajax response with typeof: " + typeof(data.data)); var json = gadgets.json.parse(data.data); if(!json){ alert('Unable to parse JSON object'); } callback_func(json); } }
Now you can use the OAuth libraries to parse your signature in PHP and verify who’s posting to your data points. Don’t forget to s/_POST/_GET/g your code to update all POST references. It seems like a bug to me in the implementation that if the request is made via POST the parameters wouldn’t also be passed in the same way. Perhaps there’s a method to the madness I’m not aware of?