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.)
精彩评论