【发布时间】:2021-06-03 01:29:21
【问题描述】:
我有一个在 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)
当我第一次运行我的应用程序时,我必须进行身份验证。凭据存储在 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"
}
当我稍后重新运行该应用程序时,我不必重新进行身份验证。效果很好。
但 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}')
解决方法是删除凭据文件并重新进行身份验证。但我希望凭据刷新在几天后仍然有效!
我确实安装并运行了 NTP。我没有手动撤销令牌。我没有更改我的 Google 密码。我没有在其他地方生成很多其他令牌。我没有做任何其他地方告诉我导致此错误的事情。
需要注意的一点:该应用未经验证,因为它仅供内部使用。这不应该影响刷新令牌的生命周期,不是吗?
是什么让这种清爽在 1 天或 2 天后起作用,但在 3 天后不再起作用?!
最好的问候, 维克
【问题讨论】:
-
您是否多次授权?当您刷新访问权限时,它会返回相同的刷新令牌还是不同的刷新令牌。您可以有 50 个刷新令牌的限制,然后第一个提示音将过期。
-
当我在不到一小时后重新进行身份验证时,不会更新任何凭据。当我在一个多小时后重新进行身份验证时,凭证文件中的令牌和刷新令牌都是新的。不存储较旧的令牌。
标签: python-3.x google-api youtube google-oauth youtube-data-api