为何Google Drive令牌自动续期代码失效,需重复授权?
问题诊断与修复方案
常见导致invalid_grant错误的原因及解决方法
1. 刷新令牌已失效或被撤销
Google OAuth2的刷新令牌并非永久有效,尤其是桌面应用类型的令牌,以下情况会导致其失效:
- 用户修改了Google账号密码
- 刷新令牌超过6个月未被使用(即使你每半小时执行代码,也可能刷新操作未真正触发)
- 用户在Google账号「安全」页面手动撤销了该应用的权限
- 同一客户端ID下,同一用户生成的刷新令牌数量超过25个(旧令牌会被自动撤销)
解决:
- 检查用户账号是否修改过密码、是否撤销过应用权限,恢复权限后重新授权
- 避免频繁触发新授权流程(比如每次运行都跳过刷新直接走授权),防止超过令牌数量限制
2. 代码逻辑的潜在问题
你的代码框架没问题,但几个细节可能导致刷新令牌无法正确保存或验证:
- 要确保刷新操作成功后才写入
token.json,当前代码块虽包含写入逻辑,但未做异常隔离(若刷新失败仍会覆盖文件) creds.valid的判断可能存在缓存延迟:即使令牌快过期,valid可能仍返回True,导致错过刷新时机。建议提前检测令牌有效期,比如提前5分钟主动刷新
修改后的代码建议:
import os import datetime from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow SCOPES = ["https://www.googleapis.com/auth/drive"] creds = None # 加载已保存的凭证 if os.path.exists("token.json"): creds = Credentials.from_authorized_user_file("token.json", SCOPES) # 检查凭证有效性,主动提前刷新 if not creds or not creds.valid: refresh_success = False # 有刷新令牌时尝试刷新 if creds and creds.refresh_token: # 提前检测:令牌已过期/即将过期(提前300秒) if creds.expired or (creds.expiry - datetime.datetime.now(datetime.timezone.utc)).total_seconds() < 300: try: creds.refresh(Request()) # 刷新成功后立即保存新凭证 with open("token.json", "w") as token: token.write(creds.to_json()) refresh_success = True except Exception as e: print(f"刷新失败: {e},将启动重新授权") # 刷新失败或无有效凭证时,启动授权流程 if not refresh_success: flow = InstalledAppFlow.from_client_secrets_file( "client_secrets.json", SCOPES ) creds = flow.run_local_server(port=0) with open("token.json", "w") as token: token.write(creds.to_json())
3. 系统时间不同步
OAuth2协议对时间同步要求严格,如果本地系统时间与Google服务器时间偏差超过5分钟,会直接导致令牌验证失败,触发invalid_grant错误。
解决:
- 开启系统自动同步时间功能,确保本地时间与标准时间一致
4. 客户端配置错误
如果client_secrets.json对应的是Web应用而非桌面应用类型,刷新令牌可能无法正常生成或使用。
解决:
- 登录Google Cloud控制台,确认OAuth客户端ID的类型为「桌面应用」,重新下载正确的
client_secrets.json替换现有文件
内容的提问来源于stack exchange,提问作者Digital Farmer
相关产品推荐
相关产品推荐

