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

Python使用OAuth调用Google Calendar API报缺失API key的403错误

问题描述

使用OAuth认证方式通过Python官方SDK调用Google Calendar API时,返回403 PERMISSION_DENIED错误,错误响应如下:

{
"error": {
    "code": 403,
    "message": "The request is missing a valid API key.",
    "errors": [
      {
        "message": "The request is missing a valid API key.",
        "domain": "global",
        "reason": "forbidden"
      }
    ],
    "status": "PERMISSION_DENIED"
  }
}

已检索到JS场景下的同类问题解决方案:初始化服务实例时传入auth参数,示例代码如下:

google.calendar({ version: "v3", auth: client })

该方案不适用于Python SDK场景,Python SDK初始化服务时传入credentials参数,写法如下:

service = build('calendar', 'v3', credentials=creds)

现有代码除client_secret文件名外,与官方Quickstart示例完全一致,完整代码如下:

from __future__ import print_function

import datetime
import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']


def main():
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'client_secret_desktop.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    try:
        service = build('calendar', 'v3', credentials=creds)

        # Call the Calendar API
        now = datetime.datetime.utcnow().isoformat() + 'Z'  # 'Z' indicates UTC time
        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

        # Prints the start and name of the next 10 events
        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)


if __name__ == '__main__':
    main()

初步判断问题出在Credentials配置环节,需要对应排查方向与解决方法。

排查与解决步骤

按优先级从高到低依次排查:

  • 第一步:清除旧凭据缓存重新授权
    直接删除脚本运行目录下的token.json文件,再重新运行脚本走完整授权流程。90%的同类问题都是修改了client_secret配置、调整了SCOPES范围后,没有删除旧的token缓存,导致请求携带的是无效的旧凭据,被服务端识别为未携带有效认证信息的匿名请求,才会提示缺少有效API key。
  • 第二步:校验OAuth客户端类型与配置
    代码里用的是InstalledAppFlow,对应Google Cloud控制台创建的OAuth客户端必须是**桌面应用(Desktop app)**类型,不能选Web应用、服务账号等其他类型,类型不匹配会导致生成的凭据结构不符合预期,无法被SDK正确识别传入请求头。同时确认下载的client_secret_desktop.json文件没有下载损坏、内容截断,文件路径和代码里的引用路径一致。
  • 第三步:检查API启用状态与同意屏配置
    进入Google Cloud控制台的「API和服务」页面,确认Google Calendar API已经正式启用,仅创建凭据不启用对应API时,所有请求都会被直接拦截返回权限错误。如果你的OAuth同意屏幕配置为外部用户类型,测试阶段必须把当前用来授权的谷歌账号添加到测试用户列表中,否则授权生成的凭据不具备访问权限。
  • 第四步:修复SDK版本兼容问题
    旧版本的Google API Python SDK存在credentials参数解析bug,会出现传了凭据但请求头没带认证信息的问题,先执行以下命令升级所有相关依赖到最新稳定版:
    pip install --upgrade google-api-python-client google-auth google-auth-oauthlib
    
    升级后可以在初始化service之前加两行调试代码,确认凭据有效:
    print(creds.valid)  # 正常应该返回True
    print(bool(creds.token)) # 正常应该返回True
    
    如果两个值有任意一个为False,说明凭据生成环节存在问题,回到第二步重新检查客户端配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:39:39