使用Python gdata和oAuth 2进行日历身份验证

4 投票
1 回答
2173 浏览
提问于 2025-04-17 00:22

我正在把一个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)
    

这个令牌和密钥的有效期很长。

这个访问令牌的有效期很短。

我稍微玩了一下这里发布的代码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 个回答

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 时有一个拼写错误。)

撰写回答