几天后 Python OAuth 无法刷新令牌并显示“invalid_grant”错误

vic*_*ans 0 youtube google-api python-3.x google-oauth youtube-data-api

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

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)
Run Code Online (Sandbox Code Playgroud)

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

{
  "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"
}
Run Code Online (Sandbox Code Playgroud)

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

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

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.', '{\n  "error": "invalid_grant",\n  "error_description": "Token has been expired or revoked."\n}')
Run Code Online (Sandbox Code Playgroud)

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

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

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

什么可以使这种令人耳目一新的工作在 1 天或 2 天后起作用,但在 3 天后不再起作用?!

最好的问候,维克

stv*_*var 6

我非常假设您相应的 Google 项目显示 - 从开发人员控制台内,在页面OAuth 同意屏幕上- 您的应用程序将其Publishing 状态设置为Testing

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

刷新令牌过期

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

[...]

为外部用户类型配置了 OAuth 同意屏幕且发布状态为“测试”的 Google Cloud Platform 项目会收到一个刷新令牌,该令牌将在 7 天后到期。

在您的应用程序的发布状态设置为生产中(即您的应用程序被 Google 审核)之前,上述限制意味着您必须每周运行一次 OAuth 身份验证/授权流程以成功完成以获得新的刷新令牌(即寿命有限,只有 7 天)。