【发布时间】:2019-08-02 11:26:30
【问题描述】:
问题
我们(我和一位同事)有一些代码非常适合 webapp 的用例,但我们域外的用户身份验证除外。如果不是因为这个问题,我们本来希望使用以下配置(在我们的清单文件的顶层)。
"webapp": {
"access": "ANYONE",
"executeAs": "USER_DEPLOYING"}
对于我们域内的用户,我们可以使用Session.getActiveUser()。然后,我们可以将其与我们的数据库进行比较,并显示应该只对该帐户可见的敏感数据。
然而,对于我们域之外的用户,Session.getActiveUser() 给出了空字符串'',所以我们不能用它来查询我们数据库中的信息,所以我们需要一些不同的东西。我们想出的是以下设置。
替代设置
我们使用"executeAs": "USER_ACCESSING" 和"oauthScopes": ["https://www.googleapis.com/auth/userinfo.email"] 部署webapp。我们使用特权帐户将另一个脚本部署为 API 可执行文件(并遵循说明here)。 webapp 的主 Code.gs 文件如下所示。
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index.html');
}
function getUserBackendData(){
//works for users outside our domain
var activeUserEmail = Session.getActiveUser();
var apiKey = 'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc'
var scriptId = 'ababababababababababababababababababababababab';
var token = 'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd'; //very secret
var url = 'https://script.googleapis.com/v1/scripts/'+ scriptId +':run?key='+ apiKey;
var functionCallData =
{
"function": 'retrieveData',
"parameters": [activeUserEmail],
"devMode": false};
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify(functionCallData),
'headers': {'Authorization': 'Bearer '+ token}
};
return UrlFetchApp.fetch(url, options).getContentText();
}
我们的想法是,这允许我们以特权用户身份在我们的 API 可执行文件中执行函数 retrieveData(activeUserEmail),同时使用 webapp 来找出访问该应用程序的用户的电子邮件地址。 Session.getActiveUser() 现在适用于我们域外的用户的原因是我们部署为 "executeAs": "USER_ACCESSING"。
问题
我们担心的是 1) 有一种更简单/更好的方法来执行此操作,以及 2) 访问 webapp 的用户可以以某种方式检索用于调用 api 可执行文件中的函数的令牌,我们担心这可能会被用来窃取私人数据。
This Q&A 涉及到关注点 2。不幸的是,答案没有引用任何官方文档/资源(并且并非所有人都同意)。此外,在那里,秘密库密钥不存在于 webapp 的源代码中(它在清单文件中),而在我们的例子中,秘密令牌 在源代码中。
问题:这种替代设置是否安全合理?
更新:我刚刚找到this answer,由一位看起来可信的用户撰写。答案是网络应用程序的用户将无法看到网络应用程序的代码,即使应用程序部署为“任何人,甚至是匿名的”。不过,此声明与“我所知道的”相对应。
【问题讨论】:
-
@Jescanellas 感谢您的评论。回复:“用户无法看到图书馆”;我假设您所说的库是指“Google Apps 脚本文件”,并且我假设您的意思是甚至无法检查与 webapp 对应的文件(并且希望也无法调试等)。这对我来说是很有价值的信息,你可能有这方面的消息来源吗?
-
Re: "你应该尝试通过代码生成它";请注意,我的设置并不典型,因为服务器通常会向用户询问令牌(涉及用户的交互),服务器可以使用令牌访问用户数据。你的first link 似乎是典型的情况。似乎StateTokenBuilder(您的第二个链接)旨在帮助进行典型设置...
-
... 在我的设置中,服务器/后端/特权用户不需要令牌来访问用户数据,而是“作为用户”运行的 webapp 脚本告诉特权用户运行一个函数,它需要一个与特权用户关联的令牌。假设我们真的需要一个我们不想与用户共享的秘密,无论是令牌本身还是生成它的东西(如刷新令牌),我的困难是代表用户执行的脚本只能访问用户可用的信息,除了脚本的来源(或其他东西)。
-
感谢您指出令牌过期是一个问题。我没有考虑那么多。如果我们将刷新令牌硬编码在 web 应用程序中,也许这仍然可以工作。同样,我很想知道这是否合理,或者存在哪些替代方案(如果有的话)。也许更合理的事情是让google cloud function 依次调用 api 可执行文件,但我已经超出了我的深度。
标签: security google-apps-script google-apps-script-api