Google Apps Script Web应用使用服务账户时遇权限未授权/过期错误
我完全懂你遇到的头疼问题——明明在普通Apps Script里能正常修改用户签名,改成Web应用关联GCP项目后,突然就抛出Error: Access not granted or expired. at Service_.getAccessToken报错。你已经做了大部分正确配置,那个不可编辑的Apps Script OAuth客户端其实是关联GCP后自动生成的,不用纠结它,咱们重点排查几个容易踩坑的点:
1. 核对服务账户的核心配置
确保你代码里用的服务账户邮箱是完整的官方格式(比如xxx@your-gcp-project-id.iam.gserviceaccount.com),而且密钥JSON里的private_key和client_email字段复制完全正确——别漏了私钥里的换行符,也别多打或少打引号,这些细节很容易导致授权失败。
2. 确认全域委托的Scopes完全匹配
在G Suite管理控制台添加的Scopes必须和代码里请求的一字不差,修改用户签名至少需要这两个Scopes:
https://www.googleapis.com/auth/gmail.settings.basichttps://www.googleapis.com/auth/gmail.settings.sharing
如果还有其他操作,要把对应Scopes也加上,注意Scopes之间用逗号分隔,不能有空格。
3. 检查Web应用部署与服务账户模拟逻辑
部署Web应用时,重点关注代码里的服务账户模拟用户逻辑:
const service = OAuth2.createService('Gmail') .setTokenUrl('https://oauth2.googleapis.com/token') .setPrivateKey(privateKey) .setIssuer(clientEmail) .setSubject(targetUserEmail) // 这里必须是你要修改签名的域内用户邮箱 .setPropertyStore(PropertiesService.getScriptProperties()) .setScope('https://www.googleapis.com/auth/gmail.settings.basic');
核心是setSubject(targetUserEmail)必须正确设置为目标用户的邮箱,而且这个用户必须在你的G Suite域内——服务账户的全域委托只能模拟同域用户。另外部署时的访问权限设置,只要符合你的业务需求即可,比如选Anyone, even anonymous或者域内用户,不影响服务账户的授权逻辑。
4. 验证GCP项目的API启用状态
你已经启用了Gmail API,但要确认是在当前关联的GCP项目里启用的——别不小心在其他项目操作了,导致Web应用绑定的项目没开API。
关于那个不可编辑的Apps Script OAuth客户端
这个是Google自动生成的,专门用于Apps Script自身的OAuth授权流程,和你用服务账户的全域委托逻辑完全不冲突,不用管它,也没法编辑,不会影响你的功能。
最后:刷新配置并重新部署
有时候Google的配置同步需要一点时间,你可以做这几步:
- 重新部署Web应用,选择创建新版本(别用临时测试部署)
- 临时在代码里加一行
PropertiesService.getScriptProperties().deleteAllProperties(),运行一次后删掉,清除旧的授权缓存 - 等待10-15分钟让全域委托的配置生效
如果还是不行,建议在代码里加日志打印授权状态:
if (service.hasAccess()) { console.log('授权成功'); } else { console.log('授权失败详情:' + service.getLastError()); }
这样能更精准定位问题根源。
内容的提问来源于stack exchange,提问作者zlZimon

