Authorizing makeRequest calls from OpenSocial containers
OpenSocial is a solid standard, but when it comes to documentation it can get pretty confusing, especially because every container has their own quirks and documentation. Anyway, I needed to communicate with my own server and as it appears OpenSocial provides a method makeRequest just for that.
It sends a request to container server, which then makes a request to your server and same way back. So in short, container acts as a proxy between your application and server. For this to be secure, it uses OAuth signing protocol. Both hosts share a secret key which they use to sign and verify requests.
Issuing and signing a request on the client is pretty easy:
function makeSignedRequest() { var params = {'person': 1, 'context':100}; params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED; params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT; params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST; var url = "http://www.test.com/resource"; gadgets.io.makeRequest(url,authResponse, params); } function authResponse(data) { for(var i in data) { alert(i+'='+data[i]); } }
Verifying a request on the server (python code, you’ll also need OAuth package):
#!/usr/local/bin/python # -*- coding: utf-8 -*- from oauth import oauth signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1() OAUTH_CONSUMER_KEY = 'http://www.myspace.com/xxxxxxxx' OAUTH_SECRET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' def _get_request_signature(url, params): '''Returns a signature built with consumer key, secret and parameters of the request''' request = oauth.OAuthRequest(http_url=url, parameters=params) consumer = oauth.OAuthConsumer(OAUTH_CONSUMER_KEY, OAUTH_SECRET_KEY) return signature_method.build_signature(request, consumer, None) def request_secure(url, params): '''Tests if request for given URL(and parameters) is safe''' try: remote_signature = params['oauth_signature'] local_signature = _get_request_signature(url, params) return local_signature == remote_signature except KeyError: return False except: logging.exception("error verifying signature: %r"%params) return False if __name__ == '__main__': # build signature test_signature = _get_request_signature("http://www.test.com/resource", dict(person=1, context=100)) assert request_secure("http://www.test.com/resource", dict(person=1, context=100, oauth_signature=test_signature)) print "All ok."
That’s it. Looks easy, right? I wish documentation was more clear on this, I spent half a day figuring this out.