使用Python gdata和oAuth 2进行日历身份验证
我正在把一个Python应用程序从oAuth 1迁移到oAuth 2,这个应用程序可以读取用户的Google日历。
在oAuth 1中: 我的应用会打开一个浏览器,用户可以用他的GMail账号进行认证并授权访问。然后我的应用会获得一个用户令牌和用户密钥,用来访问日历数据:
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)
这个令牌和密钥的有效期很长。
在oAuth 2中: 我在Google API控制台注册了我的应用,并获得了oAuth 2的客户端ID和客户端密钥。我还修改了应用程序,以便从https://accounts.google.com/o/oauth2/token请求用户的访问令牌和刷新令牌。对于GData库,我应用了这里指定的gauth.py补丁: http://codereview.appspot.com/4440067/
这个访问令牌的有效期很短。
我稍微玩了一下这里发布的代码http://codereview.appspot.com/4440067/,效果还不错。
我的问题是:
-我通过应用程序的curl调用获取访问令牌和刷新令牌,并且成功获取了这两个令牌。但是,当我把它们应用到这段代码时:
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)
它给了我:
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
-假设我能成功完成上述操作,我可以把访问令牌和刷新令牌保存在数据库中。使用Python的gdata库,我该如何使用刷新令牌请求另一个访问令牌(这样就不需要每次用户使用应用时都要求他们授权访问)
非常感谢!
M
1 个回答
Marchie,
我没有看到你完整的错误信息,但可以给你三个具体的问题和相应的解决方案,这些会帮助你解决整体问题。
问题一: 对象上没有设置 redirect_uri
的值。
注意在 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
})
这依赖于对象上的 redirect_uri
属性被设置为在 generate_authorize_url
中最初设置的值。因此,在通过调用
token = gdata.gauth.OAuth2Token(...)
重建令牌后,你只需要设置重定向 URI:
token.redirect_uri = 'http://path/that/you/set'
问题二: redirect_uri
的默认值不正确(更具体地说,已经不再支持)。
因为你在调用 generate_authorize_url
时没有传入参数,所以使用了默认的 redirect_uri
值,目前是 oob
。根据OAuth 2.0 文档,oob
并不是支持的值(它已经被弃用了)。
如果你确实在使用一个已安装的应用程序,你需要将其设置为
token.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
此外,当你调用 generate_authorize_url
来获取初始令牌时,你需要将其作为关键字参数使用
url = token.generate_authorize_url(redirect_uri='urn:ietf:wg:oauth:2.0:oob')
问题三: 你在调用 get_access_token
时使用了错误的值(而且这个值在你的代码片段中还没有被实例化)。
你应该用你在授权后收到的代码字符串值来调用这个,或者用一个字典,其中包含 'code'
作为键。
这可以通过以下方式完成:
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)
附言: 这个补丁的作者还发布了一篇博客文章,介绍如何使用这个补丁。(注意在文章中,当使用关键字 redirect_url
而不是 redirect_uri
时有一个拼写错误。)