几天后 Python OAuth 无法使用“invalid_grant"刷新令牌;错误 [英] Python OAuth after few days fails refreshing tokens with "invalid_grant" error
问题描述
我有一个在 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屋!