Chrome Extension(Manifest v3)调用带OAuth2的GAS WebApp遇CORS错误
Chrome扩展Manifest v3调用域受限GAS WebApp的CORS错误解决
问题场景
使用Manifest v3开发的Chrome扩展,通过OAuth2调用仅限域用户访问的Google Apps Script(GAS)WebApp时,触发CORS错误:chrome-extension://xxx has been blocked by CORS policy
现有配置与代码
配置说明
- GAS WebApp部署时设置为仅限域用户访问
- 已参考Manifest v2 OAuth教程完成凭据配置
GAS代码
function doGet(e) { var headers = { 'Access-Control-Allow-Origin': '*' }; var output = ContentService.createTextOutput(JSON.stringify({"code": 200, "data": "aaaa"})).setMimeType(ContentService.MimeType.JSON); output.setHeaders(headers); return output; }
Manifest v3配置
{ "manifest_version": 3, "name": "DEMO", "version": "1.0.0.3", "permissions": ["tabs", "identity", "identity.email", "https://www.googleapis.com/auth/script.webapp.deploy", "https://www.googleapis.com/auth/script.container.ui"], "background": { "service_worker": "background.js" }, "content_scripts": [ { "matches": ["https://*.google.com/*"], "run_at": "document_end", "js": ["jquery-3.6.0.min.js", "content.js"], "all_frames": false } ], "oauth2": { "client_id": "<PERSONAL_ID>.apps.googleusercontent.com", "scopes": ["https://www.googleapis.com/auth/script.webapp.deploy"] }, "action": { "default_icon": { "16": "assets/alembic.png", "24": "assets/alembic.png", "32": "assets/alembic.png", "128": "assets/alembic.png" }, "default_title": "DEMO", "default_popup": "popup.html" } }
background.js调用代码
function call_appsscript() { chrome.identity.getAuthToken({ interactive: true }, function(token) { if (chrome.runtime.lastError) { console.error(chrome.runtime.lastError); return; } const url = "https://script.google.com/a/macros/<DOMAIN>/s/<DEPLOYMENT_ID>/exec" const headers = new Headers({ 'Authorization': `Bearer ${token}` }); const init = { method: 'GET', headers: headers, }; fetch(url, init).then((response) => { console.log(response); }).catch((error) => { console.error(error); }); }); }
问题原因
- 浏览器跨域请求会先发OPTIONS预请求,当前GAS未处理该请求,导致预请求返回无合法CORS头,触发错误。
- GAS中设置
Access-Control-Allow-Origin: *的同时,WebApp要求身份验证,但*不允许请求携带Authorization凭证,二者冲突导致CORS失败。 - Manifest v3未配置GAS WebApp的
host_permissions,且OAuth2权限范围错误(使用了部署权限而非WebApp执行权限)。
解决步骤
1. 修改GAS代码,处理OPTIONS预请求并指定CORS源
添加OPTIONS请求处理逻辑,同时将允许的源指定为你的Chrome扩展ID(避免使用*):
function doGet(e) { return handleResponse(); } // 处理浏览器OPTIONS预请求 function doOptions(e) { return handleResponse(); } function handleResponse() { const headers = { 'Access-Control-Allow-Origin': 'chrome-extension://你的扩展ID', // 替换为实际扩展ID 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Authorization' }; const output = ContentService.createTextOutput(JSON.stringify({"code": 200, "data": "aaaa"})) .setMimeType(ContentService.MimeType.JSON); output.setHeaders(headers); return output; }
2. 更新Manifest v3配置
- 添加GAS WebApp的
host_permissions,让扩展获得访问权限:
在manifest.json中新增:
"host_permissions": [ "https://script.google.com/a/macros/<DOMAIN>/s/<DEPLOYMENT_ID>/exec" ]
- 修正OAuth2权限范围,将部署权限替换为WebApp执行权限:
修改permissions和oauth2.scopes:
"permissions": [ "tabs", "identity", "identity.email", "https://www.googleapis.com/auth/script.webapp.execute", // 替换原deploy权限 "https://www.googleapis.com/auth/script.container.ui" ], "oauth2": { "client_id": "<PERSONAL_ID>.apps.googleusercontent.com", "scopes": [ "https://www.googleapis.com/auth/script.webapp.execute" ] }
3. 优化background.js的fetch调用
确保请求携带凭证,并正确处理响应状态:
function call_appsscript() { chrome.identity.getAuthToken({ interactive: true }, function(token) { if (chrome.runtime.lastError) { console.error(chrome.runtime.lastError); return; } const url = "https://script.google.com/a/macros/<DOMAIN>/s/<DEPLOYMENT_ID>/exec"; fetch(url, { method: 'GET', headers: { 'Authorization': `Bearer ${token}` }, credentials: 'include' }).then(async (response) => { if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } const data = await response.json(); console.log(data); }).catch((error) => { console.error(error); }); }); }
4. 确认GAS WebApp部署设置
部署时确保:
- 执行权限选择域内用户或你自己(根据业务需求)
- 访问权限选择仅限域内用户
内容的提问来源于stack exchange,提问作者Waxim Corp
相关产品推荐
相关产品推荐

