使用Google Apps Script获取Chat附件存Google Drive遇认证问题
解决Google Apps Script Chat机器人附件上传Drive的认证问题
问题根源
直接通过UrlFetchApp访问Chat附件的downloadUri时,脚本默认身份未携带有效授权凭证——浏览器能下载是因为继承了当前用户的登录会话,而脚本身份无权限访问该资源,因此返回Google认证页面的HTML内容。
可行解决方案
方案1:使用用户授权的OAuth令牌访问
适合以发送附件的用户身份上传文件的场景:
- 配置脚本的OAuth权限范围,确保包含Chat消息读取和Drive文件操作权限
- 请求
downloadUri时携带用户授权的OAuth令牌
步骤:
配置OAuth范围:
在脚本编辑器中,打开「项目设置」→ 勾选「显示"appsscript.json"清单文件」,修改appsscript.json添加以下权限:{ "oauthScopes": [ "https://www.googleapis.com/auth/chat.bot", "https://www.googleapis.com/auth/chat.messages.readonly", "https://www.googleapis.com/auth/drive.file" ] }附件处理代码示例:
function handleChatEvent(event) { // 提取首个附件的下载链接 const attachment = event.message?.attachments?.[0]; if (!attachment) return; const downloadUri = attachment.downloadUri; // 获取当前用户的OAuth授权令牌 const authToken = ScriptApp.getOAuthToken(); // 携带授权头请求附件内容 const fetchOptions = { headers: { 'Authorization': `Bearer ${authToken}` } }; const response = UrlFetchApp.fetch(downloadUri, fetchOptions); // 将Blob上传到指定Drive文件夹 const fileBlob = response.getBlob().setName(attachment.title); DriveApp.getFolderById('你的目标文件夹ID').createFile(fileBlob); }
方案2:使用服务账号身份访问
适合组织内机器人,以机器人自身身份处理附件的场景:
- 在Google Cloud Console为机器人创建服务账号,下载密钥JSON
- 使用OAuth2库生成服务账号的授权令牌
- 为服务账号分配Chat API访问权限,并在目标Drive文件夹中添加服务账号为编辑者
代码示例(需先安装OAuth2库):
function getServiceAccountToken() { const serviceAccountKey = { /* 粘贴你的服务账号JSON密钥内容 */ }; const service = OAuth2.createService('ChatBotServiceAccount') .setTokenUrl('https://oauth2.googleapis.com/token') .setPrivateKey(serviceAccountKey.private_key) .setIssuer(serviceAccountKey.client_email) .setScope([ 'https://www.googleapis.com/auth/chat.messages.readonly', 'https://www.googleapis.com/auth/drive.file' ]); if (service.hasAccess()) { return service.getAccessToken(); } else { throw new Error('服务账号授权失败:' + service.getLastError()); } } function handleAttachmentWithServiceAccount(event) { const attachment = event.message?.attachments?.[0]; if (!attachment) return; const token = getServiceAccountToken(); const response = UrlFetchApp.fetch(attachment.downloadUri, { headers: { 'Authorization': `Bearer ${token}` } }); const fileBlob = response.getBlob().setName(attachment.title); DriveApp.getFolderById('目标文件夹ID').createFile(fileBlob); }
关键注意事项
- 方案1首次运行时,需要用户完成OAuth授权流程
- 服务账号需在Google Cloud Console启用Chat API,并被授予域内Chat访问权限
- 目标Drive文件夹必须对使用的身份(用户或服务账号)开放编辑权限
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

