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
相关产品推荐
相关产品推荐

