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

如何为整个组织授予指定Apps Script API的读取访问权限

问题背景

我正在开发一款Google Docs插件,为了支持持续迭代更新,设计了一套自动更新机制:将每个文档最近使用的脚本版本存储在对应文档的Document Property中,通过调用Apps Script API列出脚本所有版本,判断是否存在可用新版本,核心实现代码如下:

var oauthtoken =  ScriptApp.getOAuthToken();
var resp = UrlFetchApp.fetch(`https://script.googleapis.com/v1/projects/${ScriptApp.getScriptId()}/versions`, {
  headers: {
    'Authorization': 'Bearer ' + oauthtoken,
    'method': 'GET',
    'muteHttpExceptions': true,
  }
});
resp = JSON.parse(res.getContentText());
var last_version = resp.versions[0].versionNumber;
var current_version = PropertiesService.getDocumentProperties().getProperty('ADD_ON_VERSION');
if (version != last_version) {
  PropertiesService.getDocumentProperties().setProperty('ADD_ON_VERSION', last_version);
  // 触发新版本适配逻辑
}

当前机制存在运行问题:如果用户未获得该脚本的访问权限(即未按照Google Drive文件共享规则将脚本分享给对应用户),调用https://script.googleapis.com/v1/projects/{script_id}/versions接口时会返回403 Unauthorized错误。需要找到可行方案,为整个组织内的所有用户授予该特定请求的访问权限。

可行解决方案

注意:仅给插件添加https://www.googleapis.com/auth/script.projects.readonly的OAuth scope无法解决403问题,该接口同时校验调用者对脚本项目文件本身的Drive访问权限,普通用户没有脚本共享权限时,即使scope匹配也会被拒绝。

方案1:域范围授权+服务账号代理请求(正规权限方案)

这个方案是Google Workspace组织内给内部应用开全局权限的标准实现,不需要给每个用户单独开脚本文件的共享权限:

  • 先将你的Apps Script项目关联到同组织下的Google Cloud项目,在GCP控制台创建服务账号,为该项目启用Apps Script API,同时给服务账号授予脚本项目的查看权限
  • 进入Google Workspace管理后台,打开「安全-API控制-域范围授权」页面,为刚创建的服务账号添加https://www.googleapis.com/auth/script.projects.readonly的OAuth授权范围,授权生效范围覆盖整个组织
  • 修改原有代码逻辑:不再使用当前用户的OAuth令牌请求版本接口
  • 把服务账号的私钥存在脚本级属性(Script Properties)中,请求版本列表时,用服务账号生成短期访问凭据调用接口即可,普通用户不需要持有脚本的访问权限。

方案2:绕开权限校验的轻量实现(推荐,运维成本更低)

调用版本接口报403的核心原因是该接口强制要求调用者必须有脚本项目的查看权限,你完全可以绕开这个接口,把版本号存在所有域内用户默认可读的位置,不需要申请特殊权限:

  • 每次发布新版本时,手动或通过部署流水线把最新版本号写入一个域内所有用户拥有只读权限的资源,比如:
    • 共享权限设置为「组织内任何人可查看」的纯文本Google Drive文件
    • 脚本项目绑定的Google Site的静态页面
    • 直接把最新版本号硬编码在每次部署的新版脚本的常量里,搭配脚本的自动部署机制同步
  • 用户端检测更新时,直接请求这个公开可读的资源拿到最新版本号即可,全程不需要调用需要特殊权限的Apps Script API,不会出现403问题。
原代码的已知问题

你贴的核心代码本身有几个会导致运行异常的bug,需要先修复:

  • method、muteHttpExceptions参数不应该放在headers对象内部,需要和headers平级作为fetch的顶层参数
  • 解析响应时变量名错误:fetch返回值存在resp变量里,解析时写成了res.getContentText()
  • 版本对比时变量未定义:判断条件里的version不存在,应该用之前取到的current_version和last_version对比

内容的提问来源于stack exchange,提问作者Yuval.R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:57:14