python - 如何避免 'Failed to retrieve access token: { "错误": "invalid_grant" }' in offline GAE cron tasks?

标签 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. 立即安排 /cronfetch 在 11:55 工作,没有任何 access_token 问题。
  3. 但是,今天早上我醒来时看到相同 /cronfetch 任务(除时间外相同,对于我的非-测试每日任务)失败:

    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
    

Getting "invalid_grant" error on token refresh邮件列表消息 (+ SO post 1 , SO post 2 , SO post 3 ) 看起来与我的问题相似,但它似乎是通过 access_type=online token 发生的。在我的例子中,我只使用默认的 access_type=offline,并且我在初始访问请求中看到“在我不使用应用程序时执行这些操作”

我刚刚在 08:25 重新安排了一次 cron 运行(注意不要启动手动运行),其中包含我为您提交给 GitHub 的调试打印语句。这是我得到的,它相似但不相同(请注意最后几行似乎排序不正确,在阅读所有源之前我绝对不会在 create_playlist 中执行 OAuth2 内容)。所以忽略倾斜的顺序(GAE 日志神器?),似乎my http = credentials.authorize(Http()) call in create_playlist(self), currently at line 144是错误的:

    ...
    E 2013-06-10 08:26:12.817 http://www.onedayonemusic.com/page/2/ : found embeds ['80wWl_s-HuQ', 'kb1Nu75l1vA', 'kb1Nu75l1vA', 'RTWcNRQtkwE', 'RTWcNRQtkwE', 'ZtDXezAhes8', 'ZtDXezAhes8', 'cFGxNJhKK9c', 'cFGxNJhKK9c'
    I 2013-06-10 08:26:14.019 make: Got type <class 'google.appengine.api.datastore_types.Blob'>
    I 2013-06-10 08:26:14.020 validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
    I 2013-06-10 08:26:14.022 URL being requested: https://www.googleapis.com/youtube/v3/playlists?alt=json&part=snippet%2Cstatus
    I 2013-06-10 08:26:14.100 Refreshing due to a 401
    I 2013-06-10 08:26:14.105 make: Got type <class 'google.appengine.api.datastore_types.Blob'>
    I 2013-06-10 08:26:14.106 validate: Got type <class 'oauth2client.client.OAuth2Credentials'>
    I 2013-06-10 08:26:14.106 Refreshing access_token
    E 2013-06-10 08:26:18.994 Deadline exceeded while waiting for HTTP response from URL: https://accounts.google.com/o/oauth2/token Traceback (most recent call last): File "/pyt
    E 2013-06-10 08:26:18.996 http://www.onedayonemusic.com/page/3/ : found embeds ['80wWl_s-HuQ', '6VNu2MLdE0c', '6VNu2MLdE0c', 'YwQilKbK9Mk', 'YwQilKbK9Mk', 'KYdB3rectmc', 'KYdB3
    E 2013-06-10 08:26:18.996 crawl_videos end
    E 2013-06-10 08:26:18.996 create_playlist start
    E 2013-06-10 08:26:18.996 create_playlist got creds
    E 2013-06-10 08:26:18.996 create_playlist authorized creds

→ 为什么 cron 作业在手动运行后 5 分钟有效,但在 6 小时后失败?我认为刷新 token 永远不会过期。我究竟做错了什么?

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

密码在GitHub我的实例可以通过 dailygrooves.org 联系到.感谢您的帮助!

最佳答案

当刷新 token 不能用于从当前用户获取新的访问 token 时,将返回一个invalid_grant。这发生在你身上是因为存储的 Credentials 对象有一个空的刷新 token ,即

>>> credentials.refresh_token is None
True

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

If a user has already authorized your client ID, the subsequent times you perform OAuth for these users they will not see the OAuth dialog and you won't be given a refresh token.

您需要确保您的 Credentials 与有效的刷新 token 一起存储,并且最简单的方法是执行此操作,正如您在上一个问题以及您链接到的所有 3 个问题中提到的那样在创建 OAuth2WebServerFlowOAuth2Decorator 对象(无论您使用哪个)时使用 approval_prompt=force

关于python - 如何避免 'Failed to retrieve access token: { "错误": "invalid_grant" }' in offline GAE cron tasks?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17024282/

相关文章:

python - 使用分而治之算法的多数元素

java - Spring 3.0 的 Google App Engine 实体管理器配置

java - 在 AppEngine Datastore (Objectify) 中定义内部类

google-api - 添加到 Google 日历时如何在项目描述中使用换行符

java - 使用gmail API添加gmail签名

python - 如何使用 Google Drive API 替换 Google Drive 中的文件,修复 Google Drive API *fileIdInUse* 中的错误

python - 尝试仅使用 [HH :DD], 但返回 [YYYY-DD-MM HH:MM:SS] 来转换 Pandas Column

python - 防止 Windows 7 关机

python - 在 python 3.3 中从 .txt 向收件人发送电子邮件

google-app-engine - 有没有办法查看 Appstats 中正在访问哪些实体?