访问令牌和刷新令牌,在Python中使用Google Plus提供无效授权?

时间:2015-05-08 04:46:15

标签: python oauth google-api google-plus google-oauth

我正确地确定了离线访问并存储了它。每隔60分钟,在需要时,我会检索一个新的access_token。代码没有改变,但奇怪的是,当他第一次通过授权时。

client_id       ="xxxxx.apps.googleusercontent.com"
client_secret   ="xxxxxxxxxxxxxxxxxxxx"
refresh_token   ="xxxxxxxxxxxxxxxxxxx"
response        = oauth2a.RefreshToken(client_id,client_secret,refresh_token)

def RefreshToken(client_id, client_secret, refresh_token):
  params = {}
  params['client_id'] = client_id
  params['client_secret'] = client_secret
  params['refresh_token'] = refresh_token
  params['grant_type'] = 'refresh_token'
  request_url = AccountsUrl('o/oauth2/token')

  response = urllib.urlopen(request_url, urllib.urlencode(params)).read()
  return json.loads(response)

回复始终是{u'错误':u' invalid_grant'}。我在三台不同的机器上尝试了这个,并且还得到了 HTTPError:HTTP错误400:错误请求

谢谢

5 个答案:

答案 0 :(得分:12)

Invalid_grant错误有两个常见原因。

  1. 您服务器的时钟与NTP不同步。 (解决方案:检查服务器时间是否正确修复它。)
  2. 已超出刷新令牌限制。 (解决方案:您无法做任何事情,他们无法使用更多刷新令牌)应用程序可以请求多个刷新令牌。例如,这在用户想要在多台计算机上安装应用程序的情况下非常有用。在这种情况下,需要两个刷新令牌,每个安装一个。当刷新令牌的数量超过限制时,旧令牌变为无效。如果应用程序尝试使用无效的刷新令牌,则会返回invalid_grant错误响应。每个唯一的OAuth 2.0客户端对的限制是25个刷新令牌(请注意,此限制可能会发生变化)。如果应用程序继续请求同一客户端/帐户对的刷新令牌,则一旦发出第26个令牌,先前发出的第一个刷新令牌将变为无效。第27个请求的刷新令牌将使先前发出的第二个令牌失效,依此类推。

答案 1 :(得分:2)

我遇到了同样的问题(Windows操作系统)。我已经通过更新时间服务器同步来解决这个问题,现在它可以很好地工作了。

enter image description here

答案 2 :(得分:1)

您可能想尝试采用Google+ Python Hybrid身份验证示例中使用的方法,并让图书馆管理OAuth 2令牌。这里有一个完整的例子:

https://developers.google.com/+/quickstart/python

在该示例中,代码交换是使用Google的库执行的,凭据在成功时存储在基本会话中(您应该在实践中使用数据库):

# Retrieve authorization code from POST data
code = request.data

try:
  # Upgrade the authorization code into a credentials object
  oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='')
  oauth_flow.redirect_uri = 'postmessage'
  credentials = oauth_flow.step2_exchange(code)
except FlowExchangeError:
  response = make_response(
    json.dumps('Failed to upgrade the authorization code.'), 401)
  response.headers['Content-Type'] = 'application/json'
  return response

#... other code ...
session['credentials'] = credentials

稍后,您可以只检索凭据(来自会话或数据库),然后Python库完成剩下的工作。

"""Get list of people user has shared with this app."""
credentials = session.get('credentials')
# Only fetch a list of people for connected users.
if credentials is None:
  response = make_response(json.dumps('Current user not connected.'), 401)
  response.headers['Content-Type'] = 'application/json'
  return response
try:
  # Create a new authorized API client.
  http = httplib2.Http()
  http = credentials.authorize(http)
  # Get a list of people that this user has shared with this app.
  google_request = SERVICE.people().list(userId='me', collection='visible')
  result = google_request.execute(http=http)

  response = make_response(json.dumps(result), 200)
  response.headers['Content-Type'] = 'application/json'
  return response
except AccessTokenRefreshError:
  response = make_response(json.dumps('Failed to refresh access token.'), 500)
  response.headers['Content-Type'] = 'application/json'
  return response

答案 3 :(得分:1)

在发现OAuth2重定向没有设置刷新令牌后,我发现我的修复程序位于此线程https://github.com/google/google-api-python-client/issues/213中。总结一下,将prompt = 'consent'添加到交换流程中:

flow.params['prompt'] = 'consent'

答案 4 :(得分:0)

我遇到了类似的问题并且收到了“invalid_grant”回复。事实证明我正在使用grant_type =“client_credentials”进行初始OAuth调用,而我应该使用grant_type =“password”进行调用。希望分享对我有用的解决方案。

grant_types之间的更多解释可以在下面找到

Difference between grant_type=client_credentials and grant_type=password in Authentication Flow?