You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django集成Google OAuth 存储凭证刷新后身份认证失败

问题根因

你的代码存在3个核心错误,直接导致凭证无法持久化生效:

  • 凭证更新语法错误:在oauth_redir视图更新已存在的用户凭证时,每个字段赋值末尾多余的逗号会让Python将值包装为单元素元组,最终存入数据库的client_id、client_secret、token等字段全是元组类型而非字符串,加载凭证时SDK读到的参数完全非法,直接触发invalid_client: The OAuth client was not found报错。
  • 凭证字段存储缺失:你的Emp_google_creds模型没有存储凭证的expiry(过期时间)字段,从数据库加载凭证时,Google SDK无法判断token有效期,会直接将凭证标记为无效。
  • 授权配置与刷新逻辑缺失:初始化OAuth授权流程时没有配置access_type='offline',Google不会返回可长期使用的refresh_token,短期access_token(有效期1小时)过期后没有自动刷新的依据;同时你将凭证刷新的代码全部注释,即使存在合法refresh_token也不会触发刷新动作。
修复步骤
  1. 修正凭证更新的语法错误,删除oauth_redir中更新凭证块所有字段赋值末尾的逗号,同时补充过期时间的存储逻辑:
# 修正后的更新逻辑
else:
    creds=Emp_google_creds.objects.get(employee=u)
    creds.token = credentials.token
    creds.refresh_token = credentials.refresh_token
    creds.token_uri = credentials.token_uri
    creds.client_id = credentials.client_id
    creds.client_secret = credentials.client_secret
    creds.scopes = " ".join(credentials.scopes)
    creds.expiry = credentials.expiry
    creds.save()
  1. 给Emp_google_creds模型添加过期时间字段,执行数据库迁移生效:
from django.db import models
class Emp_google_creds(models.Model):
    # 保留原有所有字段,新增下面这行
    expiry = models.DateTimeField(null=True, blank=True)
  1. 修改引导用户跳转Google授权页的逻辑,添加离线访问参数,确保能拿到refresh_token:
# 生成授权跳转URL时必须添加以下两个参数
authorization_url, state = flow.authorization_url(
    access_type='offline', # 要求Google返回可用于长期刷新的refresh_token
    prompt='consent', # 强制弹出授权确认,避免已授权用户拿不到refresh_token
    include_granted_scopes='true'
)
# 再执行redirect(authorization_url)引导用户跳转授权
  1. 修复calendar_home视图的凭证加载与刷新逻辑,不要凭证一失效就跳授权,优先尝试用refresh_token刷新:
# 先导入刷新需要的依赖
from google.auth.transport.requests import Request

def calendar_home(request):
    u = Employee.objects.filter(dashboard_user=request.user)
    if not u:
        u = Employee.objects.create(dashboard_user=request.user)
    else:
        u = u[0]

    if not Emp_google_creds.objects.filter(employee=u):
        return redirect("/calendar/cal_auth/")
    else:
        creds=Emp_google_creds.objects.filter(employee=u)[0]
        gcreds=google.oauth2.credentials.Credentials.from_authorized_user_info(creds.to_dict())
        # 凭证无效时优先尝试刷新
        if not gcreds.valid:
            if gcreds.expired and gcreds.refresh_token:
                try:
                    gcreds.refresh(Request())
                    # 刷新成功后把新的凭证同步回数据库
                    creds.token = gcreds.token
                    creds.expiry = gcreds.expiry
                    if gcreds.refresh_token:
                        creds.refresh_token = gcreds.refresh_token
                    creds.save()
                except Exception as e:
                    # 刷新失败再跳授权
                    return redirect("/calendar/cal_auth/")
            else:
                # 没有有效refresh_token,跳转重新授权
                return redirect("/calendar/cal_auth/")
        # 后续调用Calendar API的逻辑保持不变即可
        try:
            service = googleapiclient.discovery.build('calendar', 'v3', credentials=gcreds)
            now = datetime.datetime.utcnow().isoformat() + 'Z'
            print('Getting the upcoming 10 events')
            events_result = service.events().list(calendarId='primary', timeMin=now,
                                                  maxResults=10, singleEvents=True,
                                                  orderBy='startTime').execute()
            events = events_result.get('items', [])

            if not events:
                print('No upcoming events found.')
                return render(request,"schedule.html")

            for event in events:
                start = event['start'].get('dateTime', event['start'].get('date'))
                print(start, event['summary'])

        except HttpError as error:
            print('An error occurred: %s' % error)
    return render(request,"schedule.html")
  1. 修复完成后,需要让所有已授权过的用户重新走一次授权流程,才能拿到有效的refresh_token存入数据库,后续页面刷新、token过期时都会自动刷新,不需要重复授权。

内容的提问来源于stack exchange,提问作者wrong1man

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 10:18:53