如何避免在离线GAE cron任务中“无法检索访问令牌:{”错误“:”invalid_grant“}'?

时间:2013-06-10 12:49:56

标签: python google-app-engine google-api oauth-2.0 google-api-python-client

这篇文章是How to make 'access_type=offline' / server-only OAuth2 operations on GAE/Python的后续内容。 http = credentials.authorize(httplib2.Http())部分在测试时不再失败,但似乎它仍然由GAE的cron运行,它无法刷新我的access_token

  1. 我可以通过拨打/fetch手动运行我的工作,比如说在11:45。
  2. 在11:55立即安排/cronfetch作业然后,没有任何access_token问题。
  3. 但是,我今天早上醒来时看到了相同的 /cronfetch任务(除了时间,我的非测试日常任务的时间是01:00)失败了:

    I 2013-06-10 05:53:51.324 make: Got type <class 'google.appengine.api.datastore_types.Blob'>
    I 2013-06-10 05:53:51.325 validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
    I 2013-06-10 05:53:51.327 URL being requested: https://www.googleapis.com/youtube/v3/playlists?alt=json&part=snippet%2Cstatus
    I 2013-06-10 05:53:51.397 Refreshing due to a 401
    I 2013-06-10 05:53:51.420 make: Got type <class 'google.appengine.api.datastore_types.Blob'>
    I 2013-06-10 05:53:51.421 validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
    I 2013-06-10 05:53:51.421 Refreshing access_token
    I 2013-06-10 05:53:51.458 Failed to retrieve access token: { "error" : "invalid_grant" }
    I 2013-06-10 05:53:51.468 make: Got type <class 'google.appengine.api.datastore_types.Blob'>
    I 2013-06-10 05:53:51.468 validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
    I 2013-06-10 05:53:51.471 validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
    I 2013-06-10 05:53:51.471 get: Got type <class 'oauth2client.appengine.CredentialsModel'>
    E 2013-06-10 05:53:51.480 invalid_grant Traceback (most recent call last): File "/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in
    
  4. Getting "invalid_grant" error on token refresh邮件列表邮件(+ SO post 1SO post 2SO post 3)与我的问题类似,但似乎发生了{{1}令牌。在我的情况下,我只使用默认的access_type=online,我在初始访问请求中看到“在我不使用应用程序时执行这些操作”

    我刚刚在08:25重新安排了一个cron运行(注意不要启动手动运行),调试打印语句是我为你提交给GitHub的。这是我得到的,它是相似的但不完全相同(请注意,最后几行看起来不正确,我绝对不会在access_type=offline中执行OAuth2,直到读取所有来源)。所以忽略了偏斜的顺序(GAE日志工件?),似乎my http = credentials.authorize(Http()) call in create_playlist(self), currently at line 144是错误的:

    create_playlist

    →为什么cron作业在手动运行后5分钟工作,但在6小时后失效?我以为刷新令牌永不过期。我究竟做错了什么?

    请注意,这是我的第一个GAE工作,我的第二个Python程序,一般代码审查/建议非常受欢迎,但请保持温和:)

    代码位于GitHub,我的实例可以通过dailygrooves.org与我联系。谢谢你的帮助!

1 个答案:

答案 0 :(得分:3)

当刷新令牌无法用于从当前用户获取新的访问令牌时,将返回invalid_grant。发生这种情况是因为存储的Credentials对象具有空刷新令牌,即

>>> credentials.refresh_token is None
True

正如How to make 'access_type=offline' / server-only OAuth2 operations on GAE/Python?中的注意所述:

  

如果用户已经授权您的客户端ID,则以后您为这些用户执行OAuth时,他们将看不到OAuth对话框,并且您将不会获得刷新令牌。

您需要确保Credentials存储有有效的刷新令牌,并且最简单的方法是执行此操作,如上一个问题以及您链接的所有3个问题中所述,使用{{ 1}}创建approval_prompt=forceOAuth2WebServerFlow对象时(无论您使用哪个)。