GAS集成Firebase谷歌认证后登录状态下的流程及最佳实践咨询
Firebase谷歌认证集成到Google Apps Script Web应用的最佳实践问题与解答
问题描述
我正在尝试将Firebase谷歌认证集成到基于Google Apps Script(GAS)的Web应用中,作为开发新手,目前遇到了一些困难。我已完成部分步骤,但用户登录后无法正常导航应用。
已实现的正常流程
- doGet()返回
HtmlService.createHtmlOutputFromFile('auth'),包含所有认证必要代码; - 'auth.html'通过CDN调用Firebase相关资源,未登录时显示认证UI,登录后显示用户详情;
- 已将userID传递到服务端用于验证,但不确定此方式是否正确。
咨询的最佳实践问题
- 用户打开应用后,doGet()加载auth.html完成客户端认证并获取用户数据、传递userID到服务端后,如何加载实际应用内容?是否应通过
google.script.run.someFunction(userID)调用相关函数加载原应用内容? - 是否需要在每个页面加载前都执行认证?
相关代码示例
.gs 文件
function doGet(e) { return HtmlService.createHtmlOutputFromFile('auth2') .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL) .setTitle('FirebaseUI | Firebase Authentication'); }
auth.html 文件
<base target="_top"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <script src="https://www.gstatic.com/firebasejs/7.14.2/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/7.14.2/firebase-auth.js"></script> <script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script> <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" /> <script> var firebaseConfig = { apiKey: "stackoverflow", authDomain: "stackoverflow.firebaseapp.com", databaseURL: "https://stackoverflow-default-rtdb.europe-west1.firebasedatabase.app", projectId: "stackoverflow", storageBucket: "stackoverflow.appspot.com", messagingSenderId: "267227785525", appId: "1:stackoverflow:web:stackoverflow", measurementId: "G-stackoverflow" }; firebase.initializeApp(firebaseConfig); </script> <script> google.script.run.withSuccessHandler(function(url) { var uiConfig = { signInFlow: 'redirect', signInSuccessUrl: url, signInOptions: [ firebase.auth.GoogleAuthProvider.PROVIDER_ID ], }; var ui = new firebaseui.auth.AuthUI(firebase.auth()); var user = firebase.auth().currentUser; console.log(user); if (user) { document.getElementById("signOut").style.display = "inline-block"; } else { ui.start('#firebaseui-auth-container', uiConfig); } }) .webAppUrl(); </script> <script> initApp = function() { firebase.auth().onAuthStateChanged(function(user) { if (user) { user.getIdToken().then(function(accessToken) { document.getElementById('account-details').textContent = JSON.stringify({ displayName: user.displayName, email: user.email, custom: user.email, emailVerified: user.emailVerified, phoneNumber: user.phoneNumber, photoURL: user.photoURL, // remove quotes to get the photoURL uid: user.uid, accessToken: "hidden", // replace "hidden" with accessToken providerData: user.providerData // remove quotes to get the photoURL }, null, ' '); }); const userID = user.email; google.script.run.someFunction(userID); } else { document.getElementById('account-details').textContent = ''; } }); }; window.addEventListener('load', function() { initApp(); }); </script> </head>
解答
1. 登录后加载实际应用内容的方式
你当前用google.script.run.someFunction(userID)的思路可行,但可以优化得更安全合理:
- 方案一:客户端动态替换内容:在服务端写一个
getAppContent(userToken)函数,传入Firebase的ID Token而非仅userID(避免伪造),验证通过后返回主应用页面的HTML片段;客户端拿到片段后,用DOM操作替换当前页面的认证内容区域(比如把#firebaseui-auth-container的innerHTML替换为返回的内容)。 - 方案二:页面跳转+服务端路由:认证完成后,客户端通过
window.location.href = '?action=loadApp'跳转;在doGet(e)中判断e.parameter.action,如果是loadApp则先验证用户的ID Token,合法后返回主应用页面,否则重定向到认证页面。 - 关键注意:仅传递userID到服务端不安全,必须用Firebase的ID Token做身份验证,服务端通过Firebase Admin SDK校验Token的有效性。
2. 是否需要每次页面加载前执行认证
是的,必须在每次页面加载前执行认证:
- GAS Web应用是无状态的,每次请求都是独立会话,服务端无法保存用户登录状态;
- 客户端的Firebase登录状态可能过期、被用户主动退出,每次加载页面时通过
onAuthStateChanged检查能确保用户状态有效; - 服务端处理任何敏感请求前,都要重新验证ID Token,避免未授权访问。
内容的提问来源于stack exchange,提问作者LeSmoox
相关产品推荐
相关产品推荐

