Rob Goldsmith
Rob Goldsmith

Reputation: 183

Retrieving contacts with gdata.contacts.client and oauth2

I am using oAuth2WebServerFlow to get an oAuth access token and then retrieve a list of a user's contacts. I'm using web2py as the web framework.

    flow = oauth2client.client.OAuth2WebServerFlow(client_id=CLIENT_ID,
                                                   client_secret=CLIENT_SECRET,
                                                  scope='https://www.google.com/m8/feeds', 
                                                   user_agent=USER_AGENT)
    callback = 'http://127.0.0.1:8000/Test/searcher/oauth2callback'
    authorise_url = flow.step1_get_authorize_url(callback)
    session.flow = pickle.dumps(flow)
    redirect(authorise_url) 

With the redirect then being handled as follows

flow = pickle.loads(session.flow)
credentials = flow.step2_exchange(request.vars) 

My question is how to change the OAuth2Credentials object returned above into an OAuth2AccessToken object, that I can then use to authorise a request to the contacts library with something like:

gc = gdata.contacts.client.ContactsClient(source="")
token.authorize(gc)
gc.GetContacts

I've tried various methods with no success, normally getting an oAuth2AccessTokenError message of "Invalid Grant". I'm thinking something like this may work but also think there must be a simpler way!

token = gdata.gauth.OAuth2Token(client_id=CLIENT_ID, client_secret=CLIENT_SECRET, scope='https://www.google.com/m8/feeds', user_agent=USER_AGENT)

    token.redirect_uri = 'http://127.0.0.1:8000/Test/searcher/oauth2callback'
    token.get_access_token(<<code to pass the access_token out of the Credentials object??>>)

Can anyone help with this?

Upvotes: 1

Views: 2440

Answers (2)

Kartik Ayyar
Kartik Ayyar

Reputation: 882

Assuming you have code for newer OAuth2.0 APIs setup correctly, you can get this working by creating a Token class that modifies headers that converts Credentials -> Token class.

OAUTH_LABEL='OAuth '

#Transforms OAuth2 credentials to OAuth2 token.
class OAuthCred2Token(object):

    def __init__(self, token_string):
        self.token_string = token_string

    def modify_request(self, http_request):
        http_request.headers['Authorization'] = '%s%s' % (OAUTH_LABEL,
                                                          self.token_string)

    ModifyRequest = modify_request

You can test it as follows:

gc = gdata.contacts.client.ContactsClient(source='')
token = OAuthCred2Token(creds.access_token)
gc.auth_token = token
print gc.GetContacts()

Note that this code will not handle token refreshes, which code using credentials handles. In my own application, it is acceptable to make a simple call using a service to refresh the credentials before making a call to get contacts.

Upvotes: 1

Rob Goldsmith
Rob Goldsmith

Reputation: 183

I managed to get this working. It was pretty straightforward actually, I just stopped using the OAuth2WebServerFlow, which didn't seem to be adding much value anyway. So the new code looks like this:

token = gdata.gauth.OAuth2Token(client_id, client_secret, scope, ua)
session.token = pickle.dumps(token)                   
redirect(token.generate_authorize_url(redirect_uri='http://127.0.0.1:8000/Test/default/oauth2callback'))

Followed by

def oauth2callback():
    token = pickle.loads(session.token)
    token.redirect_uri='http://127.0.0.1:8000/Test/default/oauth2callback'
    token.get_access_token(request.vars.code)
    gc = gdata.contacts.client.ContactsClient(source='')
    gc = token.authorize(gc)
    feed = gc.GetContacts()

Hope this is helpful to someoone!

Upvotes: 4

Related Questions