【发布时间】:2014-10-17 23:51:38
【问题描述】:
我最近一直在为这个问题烦恼。
一些背景
- 使用oauth2client 库来管理用户的令牌。令牌用于定期和同时执行各种后台任务。
- 每次这些任务中的一项即将为用户运行时,我们都会从存储中获取 Credentials 对象,并在到期时间约为 5 分钟后进行刷新。否则,当前的访问令牌将被重新使用。
- 有时会同时运行 1 个用户的多个任务
- 一段时间一切正常,令牌正常刷新
- 间歇性 并且看似出乎意料的是,在其中一次尝试刷新期间,会返回“invalid_grant”错误,并且它会使存储中的刷新令牌完全无效。 (何时/如何/为什么发生是我希望通过这个问题弄清楚的)
四处搜索,有很多关于这个问题的线程/报告。但到目前为止我发现的一切都不适用于我们的案例。我将尝试列出迄今为止我研究过的那些:
- 用户已撤销权限
这是最明显、记录最多且易于重现的,但不幸的是,在我们的案例中,我们的用户(或我们自己,在测试时)根本没有撤销权限。
- 刷新“旧”访问令牌
起初我认为一个用户一次只能有 1 个有效的访问令牌。 That is false,并在 OAuth2 Playground 上进行了验证。
每个客户端每个用户的活动令牌限制为 25 个。一旦达到该限制,旧的访问令牌就会静默失效,即使它们的到期日期尚未过去。
这对我们来说也是一个死胡同,因为我们的问题发生在刷新时,而不是使用最旧的访问令牌。而且这个限制只影响访问令牌,不影响刷新令牌。
- 短时间内请求刷新次数过多
根本没有记录。只是顺便提及,没有参考。试图通过在 7 秒内刷新 25 次来模拟它,但一切都很顺利。但是没有参考资料,这是在黑暗中拍摄的。而且我们的后台任务每几分钟最多只能完成约 10 个任务。继续前进。
- 并发刷新导致令牌成功的竞争条件
I've asked a question here, but this wasn't the case。通过同时运行两个计划的任务在 AppEngine 上进行测试。
我无计可施,试图确定这个问题。我们不能轻易复制它的事实是一种痛苦。我真的很想了解可能导致我错过的原因?
这是我们的刷新代码:
def refresh_oauth_credentials(user, credentials, force=False):
if not credentials:
return None
logging.debug(credentials.token_expiry)
do_refresh = credentials._expires_in() < 300
if force or do_refresh:
h = httplib2.Http()
try:
logging.debug('Refreshing %s\'s oauth2 credentials...' % user.email)
credentials.refresh(h)
except AccessTokenRefreshError:
logging.warning('Failed to refresh.')
return None
return credentials
【问题讨论】:
标签: python google-app-engine google-oauth