Here we want to show how to validate OAuth signed requests from an OpenSocial container, using the example of Orkut.
To validate requests from Orkut, the following function can be defined outside your controller class:
import base64
import hashlib
import urllib
from opensocial import oauth
from Crypto.PublicKey import RSA
from Crypto.Util import number
def validate_signed_orkut():
# Construct a RSA.pubkey object
exponent = 65537
public_key_str = """0x\
00b1e057678343866db89d7dec2518\
99261bf2f5e0d95f5d868f81d600c9\
a101c9e6da20606290228308551ed3\
acf9921421dcd01ef1de35dd3275cd\
4983c7be0be325ce8dfc3af6860f7a\
b0bf32742cd9fb2fcd1cd1756bbc40\
0b743f73acefb45d26694caf4f26b9\
765b9f65665245524de957e8c547c3\
58781fdfb68ec056d1"""
public_key_long = long(public_key_str, 16)
public_key = RSA.construct((public_key_long, exponent))
# Apply the public key to the signature from the remote host
sig = base64.decodestring(urllib.unquote(request.params["oauth_signature"]))
remote_hash = public_key.encrypt(sig, '')[0][-20:]
# Rebuild the message hash locally
oauth_request = oauth.OAuthRequest(http_method=request.method,
http_url=request.browser_url, # request.url for TG2
parameters=request.params.mixed())
message = '&'.join((oauth.escape(oauth_request.get_normalized_http_method()),
oauth.escape(oauth_request.get_normalized_http_url()),
oauth.escape(oauth_request.get_normalized_parameters()),))
local_hash = hashlib.sha1(message).digest()
# Verify that the locally-built value matches the value from the remote server.
if local_hash != remote_hash:
raise Exception('Incorrect user signature!')
Then, in a controller method where you expect a signed request, just code like this:
@expose('json')
def foo(self, **params):
validate_signed_orkut()
return {'success' : True}
Reference: http://code.google.com/apis/opensocial/articles/appengine-0.8.html#signing