如何通过AppScript将登录回调Token传回Gmail插件
解决Gmail插件登录回调中Token传回与存储问题
核心问题分析
现有代码存在三个关键缺陷:
getCallbackURL中state是字符串而非实际生成的有效Token,导致回调无法触发指定方法- 缺少处理回调URL中Token的服务器端逻辑
- 回调页面未实现向父窗口(插件登录弹窗)传递Token的机制
修复方案
1. 修正State Token生成逻辑
将getCallbackURL中的字符串形式代码改为实际执行Token生成:
var SCRIPT_ID = "MY_SCRIPT_ID"; // get a callback url to render in popup function getAuthURL() { var authorizeURL = getCallbackURL('testCallback'); return authorizeURL; } // generate a user callback url function getCallbackURL(callback) { // 实际生成State Token,而非字符串 var state = ScriptApp.newStateToken() .withTimeout(3600) .withMethod(callback) .createToken(); return 'https://script.google.com/macros/d/'+SCRIPT_ID+'/usercallback?state='+state; }
2. 实现回调处理函数testCallback
该函数负责提取URL中的Token、存储到UserProperties,并向父窗口发送登录成功通知:
function testCallback(e) { // 从回调请求中获取Token参数 const token = e.parameter.token; // 将Token存入用户属性 if (token) { PropertiesService.getUserProperties().setProperty('USER_LOGIN_TOKEN', token); } // 返回用于传递消息的HTML页面 return HtmlService.createHtmlOutput(` <script> // 向父窗口发送Token消息 window.opener.postMessage({ action: 'loginSuccess', value: '${token}' }, '*'); // 自动关闭回调弹窗 window.close(); </script> `); }
3. 调整前端消息监听与处理逻辑
修改doGet中的前端代码,确保收到Token后完成后续流程:
// generate login function doGet(e){ return HtmlService.createTemplate(` <!DOCTYPE html> <html> <head> <script> function openSeparatePopup() { var url = encodeURIComponent('<?= getAuthURL() ?>'); var popupOptions = "width=500,height=600"; var separatePopup = window.open('https://url.com/addon_login/?client=gmailaddon&redirect_url=' + url, "SeparatePopupWindow", popupOptions); } // 监听回调弹窗的消息 window.addEventListener("message", function(event) { if (event.data.action === 'loginSuccess') { console.log('登录Token已获取:', event.data.value); // 可选:调用服务器端函数确认存储状态 google.script.run.withSuccessHandler(() => { alert('登录完成'); // 此处可添加通知Gmail插件主逻辑更新状态的代码 }).confirmTokenStorage(); } }); </script> </head> <body> <button onclick="openSeparatePopup()">Login</button> </body> </html> `).evaluate(); }
4. 可选:添加Token存储确认函数
如果需要在前端验证Token是否成功存储,可添加以下服务器端函数:
function confirmTokenStorage() { const storedToken = PropertiesService.getUserProperties().getProperty('USER_LOGIN_TOKEN'); return storedToken ? true : false; }
流程说明
- 用户点击插件登录按钮,打开第三方登录弹窗
- 第三方登录成功后,跳转到Web App的
usercallback地址,携带token参数 testCallback函数提取Token并存入UserProperties,同时生成页面向父窗口发送消息- 插件登录弹窗收到消息后,可触发后续逻辑(如关闭弹窗、通知插件主界面登录完成)
内容的提问来源于stack exchange,提问作者Yasin Ansari
相关产品推荐
相关产品推荐

