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

查看:164
本文介绍了几天后,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.', '{\n  "error": "invalid_grant",\n  "error_description": "Token has been expired or revoked."\n}')

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

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:

[...]

具有为外部用户类型配置的OAuth同意屏幕且发布状态为测试"的Google Cloud Platform项目.发出刷新令牌,该令牌将在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天全站免登陆