使用访问令牌调用 Google Apps 脚本网络应用
Calling a Google Apps Script web app with access token
我需要代表登录到我系统的用户执行 GAS 服务。所以我有 her/his 访问令牌。我想以某种方式将令牌传输到网络应用程序,而不必再次授权用户将其用于某些活动。这能实现吗?谢谢。
编辑: 我想我没有正确解释我想要完成的事情。这是我尝试实现的工作流程:
- 我们授权使用 OAuth2 和 Google 访问我们网站的用户;
- 我们获得 her/his 访问令牌 Google returns;
- 有一个 Google Apps Script 网络应用程序作为用户执行 运行 网络应用程序;
- 我们想通过提供访问令牌 (2) 来调用此应用程序 (3),这样 Google 就不会再次请求授权;
- 实际上,我们想要调用此应用程序 (3) 不是通过将用户重定向到它,而是通过将其作为 Web 服务来调用。
谢谢
很难回答是否定的,您不能将 Apps 脚本的内置服务与服务令牌一起使用。但是,如果您已经拥有服务帐户生成的用户令牌,则访问用户数据与任何其他语言非常相似。所有调用都将针对您的令牌范围内的服务的 REST 接口。
以这个小脚本为例。它将构建所有用户文件夹的列表,并将它们 return 作为 JSON:
function doGet(e){
var token = e.parameter.token;
var folderArray = [];
var pageToken = "";
var query = encodeURIComponent("mimeType = 'application/vnd.google-apps.folder'");
var params = {method:"GET",
contentType:'application/json',
headers:{Authorization:"Bearer "+token},
muteHttpExceptions:true
};
var url = "https://www.googleapis.com/drive/v2/files?q="+query;
do{
var results = UrlFetchApp.fetch(url,params);
if(results.getResponseCode() != 200){
Logger.log(results);
break;
}
var folders = JSON.parse(results.getContentText());
url = "https://www.googleapis.com/drive/v2/files?q="+query;
for(var i in folders.items){
folderArray.push({"name":folders.items[i].title, "id":folders.items[i].id})
}
pageToken = folders.nextPageToken;
url += "&pageToken="+encodeURIComponent(pageToken);
}while(pageToken != undefined)
var folderObj = {};
folderObj["folders"] = folderArray;
return ContentService.createTextOutput(JSON.stringify(folderObj)).setMimeType(ContentService.MimeType.JSON);
}
您确实错过了让 Apps 脚本如此强大的许多便利,主要是内置服务,但所有功能都可以通过 Google REST API 获得。
我找到方法了!只需在请求中包含以下 header:
Authorization: Bearer <user's_access_token>
Martin 的回答最终对我有用,但是当我制作原型时遇到了一个主要障碍。
我需要手动添加以下范围,因为 google 应用程序脚本的 "automatic scope detection system" 没有要求它:"https://www.googleapis.com/auth/drive.readonly"
。这导致 UrlFetchApp.fetch
总是向 401 提供我不理解的附加信息。记录此附加信息将显示 html,包括以下字符串
Sorry, unable to open the file at this time.</p><p> Please check the address and try again.
我还是不太明白为什么 "https://www.googleapis.com/auth/drive.readonly"
是必要的。可能与我们可以使用/devurl有关,但是谁可以使用/devurl是使用脚本文件的驱动权限来管理的。
就是说,下面的设置适用于我(它也适用于 doGet
等,但我选择了 doPost
)。我选择在清单文件中明确列出最低限度需要的范围,但您也可以确保调用脚本将请求以不同方式访问驱动器的权限。我们有两个 google 应用程序脚本项目,Caller 和 WebApp。
在Caller的清单文件中,即appsscript.json
{
...
"oauthScopes":
[
"https://www.googleapis.com/auth/drive.readonly",
"https://www.googleapis.com/auth/script.external_request"]
}
在 Code.gs 的来电者
function controlCallSimpleService(){
var webAppUrl ='https://script.google.com/a/DOMAIN/macros/s/id123123123/exec';
// var webAppUrl =
// 'https://script.google.com/a/DOMAIN/macros/s/id1212121212/dev'
var token = ScriptApp.getOAuthToken();
var options = {
'method' : 'post'
, 'headers': {'Authorization': 'Bearer '+ token}
, muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(webAppUrl, options);
Logger.log(response.getContentText());
}
在 WebApp 的 Code.gs 中(正在调用的网络应用程序)
function doPost(event){
return ContentService.createTextOutput("Hello World");
}
我需要代表登录到我系统的用户执行 GAS 服务。所以我有 her/his 访问令牌。我想以某种方式将令牌传输到网络应用程序,而不必再次授权用户将其用于某些活动。这能实现吗?谢谢。
编辑: 我想我没有正确解释我想要完成的事情。这是我尝试实现的工作流程:
- 我们授权使用 OAuth2 和 Google 访问我们网站的用户;
- 我们获得 her/his 访问令牌 Google returns;
- 有一个 Google Apps Script 网络应用程序作为用户执行 运行 网络应用程序;
- 我们想通过提供访问令牌 (2) 来调用此应用程序 (3),这样 Google 就不会再次请求授权;
- 实际上,我们想要调用此应用程序 (3) 不是通过将用户重定向到它,而是通过将其作为 Web 服务来调用。
谢谢
很难回答是否定的,您不能将 Apps 脚本的内置服务与服务令牌一起使用。但是,如果您已经拥有服务帐户生成的用户令牌,则访问用户数据与任何其他语言非常相似。所有调用都将针对您的令牌范围内的服务的 REST 接口。
以这个小脚本为例。它将构建所有用户文件夹的列表,并将它们 return 作为 JSON:
function doGet(e){
var token = e.parameter.token;
var folderArray = [];
var pageToken = "";
var query = encodeURIComponent("mimeType = 'application/vnd.google-apps.folder'");
var params = {method:"GET",
contentType:'application/json',
headers:{Authorization:"Bearer "+token},
muteHttpExceptions:true
};
var url = "https://www.googleapis.com/drive/v2/files?q="+query;
do{
var results = UrlFetchApp.fetch(url,params);
if(results.getResponseCode() != 200){
Logger.log(results);
break;
}
var folders = JSON.parse(results.getContentText());
url = "https://www.googleapis.com/drive/v2/files?q="+query;
for(var i in folders.items){
folderArray.push({"name":folders.items[i].title, "id":folders.items[i].id})
}
pageToken = folders.nextPageToken;
url += "&pageToken="+encodeURIComponent(pageToken);
}while(pageToken != undefined)
var folderObj = {};
folderObj["folders"] = folderArray;
return ContentService.createTextOutput(JSON.stringify(folderObj)).setMimeType(ContentService.MimeType.JSON);
}
您确实错过了让 Apps 脚本如此强大的许多便利,主要是内置服务,但所有功能都可以通过 Google REST API 获得。
我找到方法了!只需在请求中包含以下 header:
Authorization: Bearer <user's_access_token>
Martin 的回答最终对我有用,但是当我制作原型时遇到了一个主要障碍。
我需要手动添加以下范围,因为 google 应用程序脚本的 "automatic scope detection system" 没有要求它:"https://www.googleapis.com/auth/drive.readonly"
。这导致 UrlFetchApp.fetch
总是向 401 提供我不理解的附加信息。记录此附加信息将显示 html,包括以下字符串
Sorry, unable to open the file at this time.</p><p> Please check the address and try again.
我还是不太明白为什么 "https://www.googleapis.com/auth/drive.readonly"
是必要的。可能与我们可以使用/devurl有关,但是谁可以使用/devurl是使用脚本文件的驱动权限来管理的。
就是说,下面的设置适用于我(它也适用于 doGet
等,但我选择了 doPost
)。我选择在清单文件中明确列出最低限度需要的范围,但您也可以确保调用脚本将请求以不同方式访问驱动器的权限。我们有两个 google 应用程序脚本项目,Caller 和 WebApp。
在Caller的清单文件中,即appsscript.json
{
...
"oauthScopes":
[
"https://www.googleapis.com/auth/drive.readonly",
"https://www.googleapis.com/auth/script.external_request"]
}
在 Code.gs 的来电者
function controlCallSimpleService(){
var webAppUrl ='https://script.google.com/a/DOMAIN/macros/s/id123123123/exec';
// var webAppUrl =
// 'https://script.google.com/a/DOMAIN/macros/s/id1212121212/dev'
var token = ScriptApp.getOAuthToken();
var options = {
'method' : 'post'
, 'headers': {'Authorization': 'Bearer '+ token}
, muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(webAppUrl, options);
Logger.log(response.getContentText());
}
在 WebApp 的 Code.gs 中(正在调用的网络应用程序)
function doPost(event){
return ContentService.createTextOutput("Hello World");
}