如何通过Node.js程序获取Google ID Token调用认证后的AppScript API
如何从Node.js服务获取Google ID Token以调用需认证的Apps Script Web App
问题描述
我需要获取ID Token来访问要求本人账号认证的Google Apps Script Web App,最终要实现getGoogleIDTokenToInvokeAppScriptEndPoint函数。具体要怎么从外部Node.js服务程序化获取这个Token?我不想用服务账号,只想用自己的Google账号(abc@gmail.com)来获取Token,之后用它调用我的Apps Script服务。
我已经完成的操作:
- 创建了
doPost请求并完成部署,当前接口仅能携带Bearer格式的ID Token时被调用。
期望实现的Node.js代码示例:
// External Script from where I am invoking AppScript API const token = getGoogleIDTokenToInvokeAppScriptEndPoint(); // Now Since I got my ID Token, I could use the same // to invoke my appScript app: fetch(appScriptEndpoint, { method:"POST", headers: { Authorization: `Bearer ${token}` // Token I got from first step } }).then(res => res.json().then(data => data))
我的Apps Script代码(供参考):
// AppScript Script const doPost = (request = {}) => { const { _, postData: { contents, type } = {} } = request; let query = {}; if (type === 'application/json') { query = JSON.parse(contents); } else if (type === 'application/x-www-form-urlencoded') { contents .split('&') .map((input) => input.split('=')) .forEach(([key, value]) => { query[decodeURIComponent(key)] = decodeURIComponent(value); }); } else if (type === 'text/plain') { try { query = JSON.parse(contents); } catch (e) { return ContentService.createTextOutput( JSON.stringify({ "error": true, "statusCode": 400, "msg": 'Unable to Parse JSON', "type": type, "requestBody": contents, "payload": {} }) ).setMimeType(ContentService.MimeType.JSON); } } else return ContentService.createTextOutput( JSON.stringify({ "error": true, "statusCode": 400, "msg": 'Unknown Request Type', "type": type, "requestBody": contents, "payload": {} }) ).setMimeType(ContentService.MimeType.JSON); const apiKey = query.apiKey; const isAuthenticated = authenticate({apiKey}); if(!isAuthenticated) return ContentService.createTextOutput( JSON.stringify({ "error": true, "statusCode": 401, "msg": 'User not authorized to make the Request.', "type": type, "requestBody": contents, "payload": {} }) ).setMimeType(ContentService.MimeType.JSON); else { const {opType,opProps} = query; const result = requestHandler({opType, opProps}); return ContentService.createTextOutput( JSON.stringify({ "error": false, "statusCode": 200, "msg": 'Connection Established', "type": type, "requestBody": contents, "payload": result }) ).setMimeType(ContentService.MimeType.JSON); } };
解决方案步骤
1. 创建OAuth 2.0桌面客户端凭据
- 进入Google Cloud控制台,选择对应项目(无项目则新建)
- 导航到「API和服务」→「凭据」
- 点击「创建凭据」→「OAuth客户端ID」
- 应用类型选「桌面应用」,填写名称后完成创建
- 下载生成的
credentials.json,保存到Node.js项目目录
2. 安装依赖
在Node.js项目中执行:
npm install google-auth-library
3. 实现Token获取函数
核心逻辑是通过OAuth 2.0授权码流获取ID Token,指定Apps Script Web App的客户端ID作为受众。完整代码如下:
const { OAuth2Client } = require('google-auth-library'); const fs = require('fs'); const path = require('path'); // 配置参数 const CREDENTIALS_PATH = path.join(__dirname, 'credentials.json'); // 替换为你的Apps Script Web App客户端ID(格式:{部署ID}.apps.googleusercontent.com) const APPS_SCRIPT_CLIENT_ID = '你的Apps Script客户端ID'; const TOKEN_PATH = path.join(__dirname, 'token.json'); async function getGoogleIDTokenToInvokeAppScriptEndPoint() { const oAuth2Client = new OAuth2Client(); // 加载客户端凭据 const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH)); const { client_secret, client_id, redirect_uris } = credentials.installed; oAuth2Client.setCredentials({ client_id, client_secret, redirect_uri: redirect_uris[0] }); // 读取缓存token或发起授权流程 let token; try { token = JSON.parse(fs.readFileSync(TOKEN_PATH)); oAuth2Client.setCredentials(token); // 自动刷新过期token if (oAuth2Client.isTokenExpiring()) { const refreshedToken = await oAuth2Client.refreshAccessToken(); token = refreshedToken.credentials; fs.writeFileSync(TOKEN_PATH, JSON.stringify(token)); } } catch (err) { token = await getAccessToken(oAuth2Client); fs.writeFileSync(TOKEN_PATH, JSON.stringify(token)); } // 获取针对Apps Script的ID Token const idToken = await oAuth2Client.getIdToken(APPS_SCRIPT_CLIENT_ID); return idToken; } // 首次授权流程 async function getAccessToken(oAuth2Client) { const authUrl = oAuth2Client.generateAuthUrl({ access_type: 'offline', scope: ['openid', 'email', 'profile'], }); console.log('请访问以下链接授权:', authUrl); const readline = require('readline').createInterface({ input: process.stdin, output: process.stdout, }); return new Promise((resolve) => { readline.question('输入页面返回的授权码: ', (code) => { readline.close(); oAuth2Client.getToken(code).then(({ tokens }) => resolve(tokens)); }); }); } // 测试调用示例 async function testCallAppScript() { const appScriptEndpoint = '你的Apps Script Web App部署URL'; const token = await getGoogleIDTokenToInvokeAppScriptEndPoint(); const response = await fetch(appScriptEndpoint, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ apiKey: '你的API密钥', opType: 'xxx', opProps: {} }) }); const data = await response.json(); console.log(data); } testCallAppScript();
4. 获取Apps Script Web App客户端ID
- 打开Apps Script项目,点击「部署」→「管理部署」
- 找到目标部署,点击「编辑」查看部署ID
- 客户端ID格式为
{部署ID}.apps.googleusercontent.com,也可在Google Cloud控制台的「OAuth同意屏幕」中确认
关键注意事项
- 首次授权:第一次运行代码会输出授权URL,用abc@gmail.com登录授权后输入返回的代码,token会缓存到
token.json,后续无需重复授权 - Token有效期:ID Token有效期1小时,代码已实现自动刷新逻辑
- OAuth同意屏幕配置:个人账号需在Google Cloud控制台的OAuth同意屏幕中添加abc@gmail.com为测试用户,否则会触发授权错误
- Web App权限:确保部署时选择「仅限我自己」或「组织内用户」,且开启「需要授权」选项
内容的提问来源于stack exchange,提问作者Shivam Sahil
相关产品推荐
相关产品推荐

