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

Google Apps脚本如何复用用户谷歌登录认证外部Django OAuth服务?

解决方案:在Google Apps Script中复用谷歌身份认证外部Django应用

这个场景我之前帮人处理过,核心问题在于Google Apps Script(GAS)的内置OAuth令牌仅适用于谷歌自家API,没法直接传递给外部服务做认证。不过我们可以借助Google官方的OAuth2库,实现复用用户已有的G Suite登录身份,完成对外部Django应用的认证授权,具体步骤如下:

1. 安装GAS OAuth2库

在GAS编辑器中,通过以下步骤添加官方OAuth2库:

  • 点击顶部菜单的「资源」→「库」
  • 在「添加库」输入框中填入库ID:1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF
  • 选择最新版本,点击「添加」

2. 配置谷歌OAuth客户端(针对Django应用)

需要在Google Cloud Console中创建一个专门用于Django应用的OAuth客户端ID:

  • 进入Google Cloud Console的「API和服务」→「凭据」页面
  • 点击「创建凭据」→「OAuth客户端ID」
  • 应用类型选择「Web应用」
  • 在「授权重定向URI」中添加GAS的OAuth回调地址,格式为:https://script.google.com/macros/d/你的脚本ID/usercallback(替换成你实际的脚本ID)
  • 创建完成后,记下客户端ID和客户端密钥

3. 在GAS中编写授权与API调用逻辑

以下是完整的示例代码,你可以根据自己的需求调整:

// 获取针对Django应用的OAuth2客户端实例
function getDjangoOAuthClient() {
  // 替换成你在Cloud Console中获取的客户端信息
  const CLIENT_ID = '你的谷歌OAuth客户端ID';
  const CLIENT_SECRET = '你的谷歌OAuth客户端密钥';
  // 这里的scopes要和你的Django应用要求的一致,通常openid、email、profile就足够
  const SCOPES = ['openid', 'email', 'profile'];
  
  return OAuth2.createService('DjangoApp')
    .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
    .setTokenUrl('https://oauth2.googleapis.com/token')
    .setClientId(CLIENT_ID)
    .setClientSecret(CLIENT_SECRET)
    .setCallbackFunction('authCallback')
    .setScope(SCOPES)
    .setCache(CacheService.getUserCache())
    .setPropertyStore(PropertiesService.getUserProperties());
}

// OAuth授权回调函数,处理授权结果
function authCallback(request) {
  const service = getDjangoOAuthClient();
  const isAuthorized = service.handleCallback(request);
  
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('授权成功!请关闭此页面继续操作。');
  } else {
    return HtmlService.createHtmlOutput('授权失败,请重试。');
  }
}

// 调用Django应用API的核心函数
function callDjangoAPI() {
  const service = getDjangoOAuthClient();
  
  // 检查是否已有有效授权凭据
  if (!service.hasAccess()) {
    // 生成授权链接,用户已登录G Suite,只需确认授权即可
    const authorizationUrl = service.getAuthorizationUrl();
    const authDialog = HtmlService.createHtmlOutput(`
      <a href="${authorizationUrl}" target="_blank" style="font-size:16px;">点击授权访问Django应用</a>
      <p>授权后请关闭此弹窗,重新运行脚本</p>
    `);
    SpreadsheetApp.getUi().showModalDialog(authDialog, '授权请求');
    return;
  }
  
  // 获取针对Django应用的访问令牌
  const accessToken = service.getAccessToken();
  
  // 调用Django应用的API,使用Bearer令牌认证
  const apiResponse = UrlFetchApp.fetch('https://你的Django应用域名/api/目标端点', {
    headers: {
      'Authorization': `Bearer ${accessToken}`
    },
    method: 'GET' // 根据API需求调整请求方法
  });
  
  // 处理API响应
  const responseData = JSON.parse(apiResponse.getContentText());
  Logger.log('Django API响应:', responseData);
  return responseData;
}

4. Django应用侧的配置说明

你的Django应用需要配置谷歌OAuth2后端,验证GAS传递过来的access_token:

  • 确保Django项目已安装django-allauth或social-auth-app-django这类OAuth2库
  • 在配置中添加谷歌作为认证提供商,使用和GAS中相同的客户端ID和密钥
  • 后端验证access_token的有效性(可以调用谷歌的令牌验证端点:https://oauth2.googleapis.com/tokeninfo?access_token=你的令牌),或者直接验证id_token的签名(如果请求了openid scope)

关键说明

为什么不能直接用GAS的ScriptApp.getOAuthToken()?因为这个令牌的受众(audience)是谷歌API的端点,外部Django应用不会认可它。而通过OAuth2库获取的令牌,受众是你自己的客户端ID,Django应用可以正常验证。

用户第一次授权后,凭据会存在用户的属性存储中,后续调用API时无需重复授权,体验和复用现有登录身份一致。

内容的提问来源于stack exchange,提问作者alonisser

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:37:22