|
Secure AuthSub Authentication for GData Python on AppEngine 
By Bobby on Sun, 28 Dec 2008 22:42:20 +0000
:
authsub,
authentication,
gdata,
tlslite,
appengine,
python,
token,
At the time of writing this i'm using AppEngine and GData Python 1.2.2, which doesn't yet have support for Secure AuthSub authentication. Secure AuthSub requires requests to be signed according to the Google AuthSub spec (http://code.google.com/apis/accounts/docs/AuthSub.html#signingrequests).
The GData Python API has an implementation for AuthSubToken but has a ToDo for SecureAuthSubToken. This post is about implementing the SecureAuthSubToken class so that you can perform secure AuthSub authentication (i apologize for saying AuthSub so many times).
For implementing SecureAuthSubToken just extend the AuthSubToken class and override/add a few methods. You'll need to sign the requests using some Python Cryptography library (and your X.509 cert in PEM format).
I'm using TLSLite (http://trevp.net/tlslite/) which was recommended by someone at Google - it works nicely but i was stuck for a few weekends trying to have TLSLite generate a valid signature because i was using the method "sign" rather than "hashAndSign", which i missed completely when skipping through the TLSLite docs.
Use hashAndSign not sign.
Use hashAndSign not sign.
Use hashAndSign not sign.
Here's the class implementation:
import gdata.service
import gdata.alt.appengine
from gdata.alt.appengine import AppEngineTokenStore
import gdata.auth
from gdata.auth import AuthSubToken
from gdata.docs.service import DocsService
from tlslite.utils.RSAKey import RSAKey
import tlslite.utils.keyfactory
import tlslite.utils.compat
import tlslite.utils.cryptomath
import google.appengine.api.urlfetch
class SecureAuthSubToken(AuthSubToken):
def __init__(self, auth_header=None, scopes=None, token=None):
AuthSubToken.__init__(self, auth_header, scopes)
self.token_string = token
def perform_request(self, http_client, operation, url, data=None,
headers=None):
self.set_token_string(self.get_token_string(), operation, url)
return AuthSubToken.perform_request(self, http_client, operation,
url, data, headers)
def get_token_string(self):
return self.token_string
def set_token_string(self, token, operation='GET', url='',
sig_alg='rsa-sha1'):
self.token_string = token
nonce = str(tlslite.utils.cryptomath.getRandomNumber
(10000000000000000000, 18446744073709551615))
data = '%s %s %s %s' % (operation, url, int(time.time()), nonce)
token = '"%s" sigalg="%s" data="%s" sig="%s"' % (token, sig_alg,
data, self.sign_data(data))
self.auth_header = '%s%s' % (gdata.auth.AUTHSUB_AUTH_LABEL, token)
def sign_data(self, data):
key = tlslite.utils.keyfactory.parsePEMKey("""-----BEGIN RSA
PRIVATE KEY-----
Your PEM OpenSSL key here
-----END RSA PRIVATE KEY-----
""", private=True)
return tlslite.utils.cryptomath.bytesToBase64(key.hashAndSign
(tlslite.utils.compat.stringToBytes(data)))
Usage:
When calling GenerateAuthSubURL pass in secure=true and then when
upgrading to session token, instead of using the following lines:
myGDataClient.SetAuthSubToken(myUrlToken)
myGDataClient.UpgradeToSessionToken()
use:
myGDataClient.UpgradeToSessionToken(SecureAuthSubToken(token=myUrlToken))
The rest should work the same, i.e. the token should be automatically stored and retrieved from the
TokenStore, in the same that the unsecure tokens are, etc.
(see all)
web service, tile engine, google docs, flash, window, penn, pixel, python, game, compiler, server, tlslite, token, reference, rtmp, vmware, p vs np, Google Docs, poweredge, javascript, component, vbulletin, proxy, networking, vmware esxi, GData, forum, plugin, gwt, outlook, scales, puzzle, GWT, java, attach, shining force, subsets, appengine, permutations, pong, authentication, roland, screenshot, np-complete, gdata, neural net, php, latex, audio, AppEngine
|
Thanks for your brilliant article. I wonder if you will be able to update it for gdata 2.0? <br />I find authsub, oauth to be an unnecessarily complex process. I'm currently having trouble with <br />secure authsub. Quick question: most blog posts on this topic, describe the auth process only for the initial authorization/authentication dance, which involves exchanging a temporary auth token for a long lived session token. It would be nice if someone could describe how to send subsequent requests with a saved, secure session token. How do you programatically sign the requests etc