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

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);
        });
    });
}

问题原因

  1. 浏览器跨域请求会先发OPTIONS预请求,当前GAS未处理该请求,导致预请求返回无合法CORS头,触发错误。
  2. GAS中设置Access-Control-Allow-Origin: *的同时,WebApp要求身份验证,但*不允许请求携带Authorization凭证,二者冲突导致CORS失败。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:40:32