Google Apps Script OAuth2.0 SSO登录重定向异常问题排查
问题描述
我正在使用Google Apps Script开发一款简单Web应用,用户通过SSO(Google Sign-In)登录,认证成功后需跳转至首页。
已完成操作
- 在Google Cloud Console创建项目
- 在API与服务下配置OAuth 2.0客户端ID
- 设置授权JavaScript源:
https://script.google.com,授权重定向URI:https://script.google.com/macros/s/AKfycbzvkNVrn3xfguC2dTSW9RNT65NbAGATKGPZ11rQS8C1adbvAkbL-9QaXjaSe-iaXjVQjA/usercallback - 引入Google Sign-In脚本:
<script src="https://accounts.google.com/gsi/client" async></script>
登录页代码(index.html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Google SSO Login</title> <script src="https://accounts.google.com/gsi/client" async></script> </head> <body> <h2>Google SSO Login</h2> <div id="g_id_onload" data-client_id="208292407248-2g41mq1nu6munitpsrhev01b5kvfl5gv.apps.googleusercontent.com" data-context="signin" data-ux_mode="popup" data-callback="handleCredentialResponse" data-auto_prompt="false"> </div> <div class="g_id_signin" data-type="standard" data-shape="rectangular" data-theme="outline" data-text="signin_with" data-size="large" data-logo_alignment="left"> </div> <button id="logoutBtn" onclick="logout()" style="display: none;">Sign Out</button> <script> function decodeJwtResponse(token) { var base64Url = token.split(".")[1]; var base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/"); var jsonPayload = decodeURIComponent( atob(base64).split("").map(c => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join("") ); return JSON.parse(jsonPayload); } function handleCredentialResponse(response) { const userData = decodeJwtResponse(response.credential); console.log("User:", userData); google.script.run.withSuccessHandler(() => { document.getElementById('logoutBtn').style.display = "block"; }).handleLogin(userData); } function logout() { google.accounts.id.disableAutoSelect(); google.script.run.withSuccessHandler(() => { document.getElementById('logoutBtn').style.display = "none"; console.log("User Logged Out"); }).handleLogout(); } </script> </body> </html>
Code.gs代码
function doGet(e) { return HtmlService.createHtmlOutputFromFile("index").setTitle("Google SSO Login"); } // Handle login response function handleLogin(userData) { var scriptProperties = PropertiesService.getScriptProperties(); scriptProperties.setProperty("userEmail", userData.email); return "Login Successful: " + userData.email; } // Handle logout function handleLogout() { var scriptProperties = PropertiesService.getScriptProperties(); scriptProperties.deleteProperty("userEmail"); return "User Logged Out"; }
当前问题
用户成功登录后无法正常重定向至首页,出现以下错误:
Error 400: invalid_request Request details: redirect_uri=https://n-eegz6qkhxofscrf6dbo55h5cggdgdxogbcfmbcq-0lu-script.googleusercontent.com flowName=GeneralOAuthFlow
疑问
- 是否需要针对Google Apps Script采用不同的OAuth流程处理方式?
- Google Cloud Console是否需要额外配置?
解决方案
1. OAuth流程适配Google Apps Script的问题
是的,当前实现存在流程适配问题:
- 你用
PropertiesService存储的userEmail是脚本级全局变量,多用户登录会互相覆盖,不能用来管理用户会话。 - 前端缺少明确的跳转逻辑,导致触发错误的重定向路由。
修正方案:
- 前端登录成功后,在回调中添加页面重定向逻辑;
- 服务器端改用
Session对象管理用户会话(GSI会自动维护用户授权会话)。
修改前端handleCredentialResponse函数:
function handleCredentialResponse(response) { const userData = decodeJwtResponse(response.credential); console.log("User:", userData); google.script.run.withSuccessHandler(() => { // 登录成功后跳转到首页路由 window.location.href = "https://script.google.com/macros/s/你的脚本ID/exec?page=home"; }).handleLogin(userData); }
修改Code.gs的doGet函数,根据路由参数展示对应页面:
function doGet(e) { const userEmail = Session.getActiveUser().getEmail(); const page = e.parameter.page; if (page === "home" && userEmail) { // 展示首页内容 return HtmlService.createHtmlOutput(`<h1>首页</h1><p>欢迎回来,${userEmail}</p>`); } else { // 展示登录页 return HtmlService.createHtmlOutputFromFile("index").setTitle("Google SSO Login"); } }
2. Google Cloud Console的额外配置
错误中的redirect_uri未被添加到OAuth客户端的授权列表中,需要补充配置:
- 打开Google Cloud Console的OAuth 2.0客户端ID配置页面;
- 在授权重定向URI中添加错误提示里的完整URI:
https://n-eegz6qkhxofscrf6dbo55h5cggdgdxogbcfmbcq-0lu-script.googleusercontent.com; - 确保Web应用部署权限设置为「任何人,甚至匿名」或「任何人」,并勾选「允许OAuth客户端访问」。
额外建议
- 不要依赖前端解析JWT的用户信息,服务器端可调用Google令牌验证API校验JWT合法性,避免数据篡改;
- 无需手动存储用户邮箱,
Session.getActiveUser()可直接获取已授权用户的身份信息。
内容的提问来源于stack exchange,提问作者Namita Tare
相关产品推荐
相关产品推荐

