Google Books API突发401无效凭证错误排查求助
问题:Google Play Books API上传时返回401 Invalid Credentials错误
原本使用Python脚本将Google Drive中的epub文件上传至Google Play Books库,此前运行完全正常,近期突然失效。执行上传操作时,Google Books API返回401“Invalid Credentials”错误,已尝试重新认证获取新令牌,但问题仍未解决。
OAuth2.0令牌获取脚本
from flask import Flask, request from google.oauth2.credentials import Credentials import google_auth_oauthlib.flow import json import os def credentials_to_dict(credentials): return { "token": credentials.token, "refresh_token": credentials.refresh_token, "token_uri": credentials.token_uri, "client_id": credentials.client_id, "client_secret": credentials.client_secret, "scopes": credentials.scopes, "expiry": credentials.expiry.isoformat() if credentials.expiry else None, } flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( "client_secrets.json", scopes=["https://www.googleapis.com/auth/books"] ) flow.redirect_uri = "https://callback/callback" authorization_url, state = flow.authorization_url( access_type="offline", include_granted_scopes="true", prompt="consent", ) print("Please go to this URL:", authorization_url) app = Flask(__name__) @app.route("/callback") def callback(): code = request.args.get("code") flow.fetch_token(code=code) creds = flow.credentials cred_dict = credentials_to_dict(creds) with open("credentials.json", "w") as outfile: json.dump(cred_dict, outfile) return "Authentication successful!" app.run(host="127.0.0.1", port=8000)
credentials.json示例
{ "token": "ya29.a0AcM612xFMQgQrX-jI1meqxyi2jZrTjiGN0rFiHQWq_Dg9hf7JKJXrtrb5gjCAZieeRxSZ-6k-X4a_qvZBF4rRGW4GQO2ksBkDobvMfbcBmem_zfHS_fN6I83Hf1naCgYKAWYSARESFQHGX2MihDmMJS1g7doDnZTdFV7iKg0175", "refresh_token": "1//09DwiJZIARAAGAkSNwF-L9VjT8t8aqhQIZ65Gl1Ga68C03ZB-M7Jz4Z5x3OB-ONj_YPc_pMVU8mI_i9g", "token_uri": "https://oauth2.googleapis.com/token", "client_id": "726229-jsq22ptgsjv4umdkf0sg0tljc.apps.googleusercontent.com", "client_secret": "GOCSPX-CLuI2JI0_n0gU", "scopes": [ "https://www.googleapis.com/auth/books" ], "expiry": "2024-08-21T16:57:53.932878" }
上传脚本
from googleapiclient.discovery import build import google.auth.transport.requests as refresh from google.oauth2.credentials import Credentials import sys id=sys.argv[1] def upload_epub_to_play_books(): # Load the OAuth 2.0 credentials from a file creds = Credentials.from_authorized_user_file('/home/varo/scripts/playbooks/credentials.json') if not creds.valid: if creds.refresh_token: request = refresh.Request() creds.refresh(request) if creds.valid: print("Creds valid and were refreshed") with open('/home/varo/scripts/playbooks/credentials.json', 'w') as token: token.write(creds.to_json()) else: print("creds already valid") # Create a Google Play Books API service client service = build('books', 'v1', credentials=creds) # Upload the epub file to Google Play Books response = service.cloudloading().addBook(drive_document_id=id).execute() print(response) # Upload an epub file to Google Play Books upload_epub_to_play_books()
报错信息
This is the id: 1gODrE4DeRzmiwjrE3XTc-J8tToJ7Lh2F Creds valid and were refreshed Traceback (most recent call last): File "/home/varo/scripts/playbooks/add_to_playbooks.py", line 33, in <module> upload_epub_to_play_books() File "/home/varo/scripts/playbooks/add_to_playbooks.py", line 28, in upload_epub_to_play_books response = service.cloudloading().addBook(drive_document_id=id).execute() File "/home/varo/.local/lib/python3.9/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper return wrapped(*args, **kwargs) File "/home/varo/.local/lib/python3.9/site-packages/googleapiclient/http.py", line 938, in execute raise HttpError(resp, content, uri=self.uri) googleapiclient.errors.HttpError: <HttpError 401 when requesting https://books.googleapis.com/books/v1/cloudloading/addBook?drive_document_id=1gODrE4DeRzmiwjrE3XTc-J8tToJ7Lh2F&alt=json returned "Invalid Credentials". Details: "[{'message': 'Invalid Credentials', 'domain': 'global', 'reason': 'authError', 'location': 'Authorization', 'locationType': 'header'}]">
排查建议
修正OAuth回调地址匹配问题
脚本中设置的redirect_uri为https://callback/callback,但本地Flask服务实际回调地址是http://127.0.0.1:8000/callback,两者完全不匹配。需在Google Cloud控制台的OAuth客户端配置中,将回调地址改为http://127.0.0.1:8000/callback,同时同步修改脚本中的flow.redirect_uri值,确保三者一致。统一令牌序列化逻辑
认证脚本用自定义的credentials_to_dict序列化令牌,上传脚本用官方的creds.to_json()写入文件,两种格式可能存在差异。建议修改认证脚本,直接用creds.to_json()生成文件内容,避免手动序列化导致的格式错误:# 替换原认证脚本中的写入逻辑 with open("credentials.json", "w") as outfile: outfile.write(creds.to_json())验证API启用状态与权限范围
- 登录Google Cloud控制台,确认对应项目已启用Google Play Books API;
- 重新认证时,确认授权页面明确显示「管理您的Google Play Books库」权限,确保令牌包含
https://www.googleapis.com/auth/books范围。
更新依赖库版本
旧版本的Google认证库可能存在令牌刷新bug,执行以下命令更新到最新稳定版:pip install --upgrade google-auth google-auth-oauthlib google-api-python-client flask检查Drive文件权限
确认OAuth授权的账号有权限访问指定的Drive文件(drive_document_id对应文件),若文件为私有且未共享给该账号,也可能触发权限类错误。
内容的提问来源于stack exchange,提问作者Varo OP
相关产品推荐
相关产品推荐

