几天后 Python OAuth 无法使用“invalid_grant"刷新令牌;错误 [英] Python OAuth after few days fails refreshing tokens with "invalid_grant" error

查看:15
本文介绍了几天后 Python OAuth 无法使用“invalid_grant"刷新令牌;错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在 Raspberry Pi 上运行的 Python 应用程序,它开始向我管理的 YouTube 频道进行直播.这是我用来验证的代码:

I have a Python app running on Raspberry Pi that starts a livestream to a YouTube channel that I manage. This is the code that I use to authenticate:

import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors
import google.auth.transport.requests
import google.oauth2.credentials
import requests

CLIENT_SECRETS_FILE = "client_secrets.json"
YOUTUBE_READ_WRITE_SCOPE = "https://www.googleapis.com/auth/youtube"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

def get_authenticated_service(args):
    credentials = None
    credentials_json_file = "youtube-%s.json" % slugify(args.oauth2_name)
    if os.path.exists(credentials_json_file):
        # load credentials from file
        with open(credentials_json_file, encoding='utf-8') as f:
            credentials_json = json.load(f)
        credentials = google.oauth2.credentials.Credentials.from_authorized_user_info(credentials_json)
    if not credentials or not credentials.valid:
        # no credentials file or invalid credentials
        if credentials and credentials.expired and credentials.refresh_token:
            # refresh
            request = google.auth.transport.requests.Request()
            credentials.refresh(request)
        else:
            # re-authenticate
            flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, [YOUTUBE_READ_WRITE_SCOPE])
            credentials = flow.run_console()
        # save credentials to file
        credentials_json = credentials.to_json()
        with open(credentials_json_file, 'w', encoding='utf-8') as f:
            f.write(credentials_json)
    return googleapiclient.discovery.build(
        YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, credentials=credentials)

当我第一次运行我的应用程序时,我必须进行身份验证.凭据存储在如下所示的 JSON 文件中:

When I run my app a first time, I must authenticate. The credentials are stored in a JSON file that looks like this:

{
  "token": "...", 
  "refresh_token": "...", 
  "token_uri": "https://oauth2.googleapis.com/token", 
  "client_id": "....apps.googleusercontent.com", 
  "client_secret": "...", 
  "scopes": ["https://www.googleapis.com/auth/youtube"],    
  "expiry": "2021-02-28T09:27:44.221302Z"
}

当我稍后重新运行应用程序时,我不必重新进行身份验证.效果很好.

When I re-run the app later on, I don't have to re-authenticate. That works fine.

但 2-3 天后,我收到此错误:

But after 2-3 days, I get this error:

Traceback (most recent call last):
  File "./create_broadcast.py", line 188, in <module>
    youtube = get_authenticated_service(args)
  File "./create_broadcast.py", line 83, in get_authenticated_service
    credentials.refresh(request)
  File "/home/pi/.local/lib/python3.7/site-packages/google/oauth2/credentials.py", line 214, in refresh
    scopes,
  File "/home/pi/.local/lib/python3.7/site-packages/google/oauth2/_client.py", line 248, in refresh_grant
    response_data = _token_endpoint_request(request, token_uri, body)
  File "/home/pi/.local/lib/python3.7/site-packages/google/oauth2/_client.py", line 124, in _token_endpoint_request
    _handle_error_response(response_body)
  File "/home/pi/.local/lib/python3.7/site-packages/google/oauth2/_client.py", line 60, in _handle_error_response
    raise exceptions.RefreshError(error_details, response_body)
google.auth.exceptions.RefreshError: ('invalid_grant: Token has been expired or revoked.', '{
  "error": "invalid_grant",
  "error_description": "Token has been expired or revoked."
}')

解决方法是删除凭据文件并重新进行身份验证.但我希望凭据刷新在几天后仍然有效!

The workaround is to delete the credentials file and re-authenticate. But I'd expect the credentials refresh to still work after a couple of days!

我确实安装并运行了 NTP.我没有手动撤销令牌.我没有更改我的 Google 密码.我没有在其他地方生成很多其他令牌.我没有做任何其他地方被告知会导致此错误的事情.

I do have NTP installed and running. I didn't manually revoke the token. I didn't change my Google password. I didn't generate a lot of other tokens elsewhere. I did none of the things that are told elsewhere to cause this error.

需要注意的一点:该应用未经验证,因为它仅供内部使用.这仍然不应该影响刷新令牌的寿命,是吗?

One thing to note: the app is not verified, because it's only meant for internal use. Still this shouldn't impact the lifespan of the refresh token, should it?

什么可以使这种刷新在 1 天或 2 天后起作用,但在 3 天后不再起作用?!

What could make that refreshing works after 1 day or after 2 days, but not anymore after 3 days?!

最好的问候,维克

推荐答案

我非常认为您相应的 Google 项目会显示 -- 从开发人员控制台内的页面 OAuth 同意屏幕 --您的应用的发布状态设置为测试.

I very much presume that your corresponding Google project shows -- from within the Developers Console, on the page OAuth consent screen -- your app to have its Publishing status set as Testing.

根据官方文档,您的刷新令牌受到以下限制:

According to the official documentation, your refresh tokens are subject to the following restrictions:

刷新令牌过期

您必须编写代码以预测授予的刷新令牌可能不再起作用的可能性.由于以下原因之一,刷新令牌可能会停止工作:

You must write your code to anticipate the possibility that a granted refresh token might no longer work. A refresh token might stop working for one of these reasons:

[...]

一个 Google Cloud Platform 项目,其 OAuth 同意屏幕为外部用户类型配置,发布状态为测试";已发出 7 天后到期的刷新令牌.

A Google Cloud Platform project with an OAuth consent screen configured for an external user type and a publishing status of "Testing" is issued a refresh token expiring in 7 days.

直到您的应用的发布状态设置为生产中——即您的应用被 Google 审核——,上述限制意味着您必须运行才能成功每周完成一次 OAuth 身份验证/授权流程,以获取新的刷新令牌(有效期仅为 7 天).

Until your app's publishing status becomes set to in production -- i.e. your app gets audited by Google --, the above restriction implies that you have to run to successful completion an OAuth authentication/authorization flow every week for to obtain new refresh tokens (that have a limited lifespan of only 7 days).

这篇关于几天后 Python OAuth 无法使用“invalid_grant"刷新令牌;错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆