开发者

Authenticating to Calendar with Python gdata and oAuth 2

I'm migrating a Python application from oAuth 1 to oAuth 2 that reads a user's Google calendar feed.

  • With oAuth 1: My app would open a browser were user can authenticate with his GMail account and authorize access, and my app would obtain a user_token, user_secret for that user, then authenticate to the calendar feed:

    client = gdata.calendar.client.CalendarClient(source='test')
    client.auth_token = gdata.gauth.OAuthHmacToken(app_key,
             app_secret,user_token,user_secret,gdata.gauth.ACCESS_TOKEN)
    

This token, secret pair would be long lived.

  • With oAuth 2: I registered my app in the Google API console and obtained the oAuth 2 client_id and client_secret, and modified the app to request the user's access_token, refresh_token from https://accounts.google.com/o/oauth2/token For the GData lib, I applied the gauth.py patch specified here: http://codereview.appspot.com/4440067/

This access_tok开发者_开发问答en is short lived.

I played a little bit with the code posted here http://codereview.appspot.com/4440067/ and works ok.

My questions:

-I am obtaining access_token, refresh_token via a curl call from my app, and I can successfully retrieve both. However, when I apply it to this code:

    token =
    gdata.gauth.OAuth2Token(client_id=client_id,client_secret=client_secret',
                           scope='https://www.google.com/calendar/
    feeds',user_agent='calendar-cmdline-sample/1.0')
    uri = token.generate_authorize_url()
    token.get_access_token(access_token)

It gives me:

Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "/Library/Python/2.6/site-packages/gdata/gauth.py", line 1267,
in get_access_token
   raise OAuth2AccessTokenError(error_msg)
gdata.gauth.OAuth2AccessTokenError

-Assuming I can successfully do the above, I can save the access/refresh tokens in a DB. Using python gdata lib, how can I use refresh_token to request another access_token (hence not having to ask the user every time they use the app to authorize access to it)

Thanks much in advance!

M


Marchie,

I don't see the rest of your stack trace, but can give three particular issues with corresponding solutions that will solve your overall problem.

Problem I: The value redirect_uri is not set on the object.

Note how the body of the request is specified in get_access_token:

body = urllib.urlencode({
  'grant_type': 'authorization_code',
  'client_id': self.client_id,
  'client_secret': self.client_secret,
  'code': code,
  'redirect_uri': self.redirect_uri,
  'scope': self.scope
  })

This depends on the redirect_uri property being set on the object to the value that was originally set in generate_authorize_url. So, after reconstructing the token by calling

token = gdata.gauth.OAuth2Token(...)

you will simply need to set the redirect URI:

token.redirect_uri = 'http://path/that/you/set'

Problem II: The default value of redirect_uri is incorrect (more specifically, deprecated).

Since you called generate_authorize_url with no arguments, the default value for redirect_uri was used, which is currently oob. As the OAuth 2.0 docs state, the oob is not among the supported values (it has been deprecated).

If you are indeed using an Installed Application, you will need to instead set it to

token.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'

In addition, when you call generate_authorize_url to get the initial token, you will need to use this as a keyword parameter

url = token.generate_authorize_url(redirect_uri='urn:ietf:wg:oauth:2.0:oob')

Problem III: You are calling get_access_token with the incorrect value (also one that hasn't been instantiated in your code snippet).

You should either call this with a string value of the code you receive after authorizing or with a dictionary that has 'code' as a key.

This can be done via the following:

import atom.http_core

# Page the user is redirected to after authorizing
redirected_page = 'http://path/that/you/set?code=RANDOM-CODE'
uri = atom.http_core.ParseUri(redirected_page)

# uri.query is a dictionary with the query string as key, value pairs
token.get_access_token(uri.query)

Post Script: The author of the patch also published a blog post on using the patch. (Note there is a typo in the post when the keyword redirect_url is used instead of redirect_uri in the generate_authorize_url function.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜