使用默认凭据访问Google表格

时间:2018-03-29 19:20:02

标签: javascript node.js google-app-engine google-cloud-platform google-sheets-api

我在Google表格上有一些数据。我正在使用Sheets API for Node.js来访问此数据。对于身份验证,我使用服务帐户JSON生成JWTClient。

我可以从工作表api访问数据,一切正常。代码托管在Google App Engine Flexible environment上。它适用于localhost和GAE。

唯一的问题是我需要提供服务帐户密钥json进行身份验证。这在本地环境中很好,但在App Engine上它为服务帐户提供default credential(我使用相同的服务帐户)。所以我认为我不应该手动提供凭据,让GAE处理服务器上的凭据。

但它没有自动验证,仍然是auth参数。

这是我目前对工作表api的实现 -

const { promisify } = require('util');
const google = require('googleapis');
const auth = require('./auth');
const credentials = require('../configs/credentials');

const sheets = google.sheets('v4');
const getSheetValuesAsync = promisify(sheets.spreadsheets.values.get);
//region private
function readSheet(params) {
  return getSheetValuesAsync(params);
}
//endregion private

//region public
async function get(sheetConfigName) {
  const sheetConfig = credentials.sheets[sheetConfigName];
  //This is theJWTClient which authenticates the api request currently.
  //I want to remove this
  const authClient = await auth.authorizeWithServiceAccount('serviceAccountName', [
    'https://www.googleapis.com/auth/spreadsheets.readonly'
  ]);
  console.log('Client received');
  let params = {
    auth: authClient, //I tried removing this parameter, but it didn't work
    spreadsheetId: sheetConfig.id,
    range: 'A:M'
  };
  let data = await readSheet(params);
  return data;
}
//endregion public
module.exports = {
  get: get
};

我得到的错误如下: -

{
  code:403,
  message: 'The request is missing a valid API key.
}

我已经为本地环境设置了GOOGLE_APPLICATION_CREDENTIALS环境变量,该环境变量适用于google-cloud API,但不适用于工作表。

Application Default Credentials仅适用于google-cloud API,还是可以与Sheets API或任何其他Drive API一起使用?如果它也能用于驱动API,那怎么办呢?

3 个答案:

答案 0 :(得分:0)

如果您想使用Google表格API,则需要提供documentation中所示的OAuth服务帐户。默认服务帐户主要用于从GCP(Google Cloud Platform)中提取数据时使用。因此,您的计算引擎可以访问您的云数据存储区,或者您的App Engine可以访问您的云存储。

默认服务帐户没有Sheets API所需的客户机密钥JSON。

或者,如果您要使用Google Sheets REST API,则可以将API密钥用于公开文档。

答案 1 :(得分:0)

Google Cloud服务帐户旨在访问Cloud API,无法为Sheets API授予适当的范围。

由于App Engine Flexible应用程序在Compute Engine VM上运行,您可以通过查询元数据服务器来获取默认服务帐户的令牌:

> curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google"

但是,在调用提供该令牌的Sheets API时,会出现以下错误:

{
  "error": {
    "code": 403,
    "message": "Request had insufficient authentication scopes.",
    "status": "PERMISSION_DENIED"
  }
}

我相信您需要为您的用例使用API​​密钥。

答案 2 :(得分:0)

在谷歌的Node.js客户端软件包(28.x)的最新更新中,他们有了一种获取authClient的新方法,而无需第二个软件包。以下是它的完成方式 -

const { google } = require('googleapis');
  const authClient = await google.auth.getClient({
  credentials: credentials,
  scopes: scopes
});

credentials只是服务帐户JSON对象。最好的部分是,如果您不提供该属性,它将检查GOOGLE_APPLICATION_CREDENTIALS环境变量,该变量将具有服务帐户密钥JSON的绝对路径,并自动将其视为身份验证。<登记/> 您可以使用生成的authClient,使用以下任一方式为google sheet API设置auth参数 -

首先,您希望为不同的API调用提供不同的身份验证。

const { google } = require('googleapis');
const sheets = google.sheets('v4');
sheets.spreadsheets.values.getAsync = promisify(sheets.spreadsheets.values.get);
sheets.spreadsheets.values.getAsync({
    auth: authClient,
    spreadsheetId: spreadsheetId,
    range: range
  });

或者您可以直接向工作表对象提供auth。该对象上的所有API调用都将使用相同的authClient,并且不需要auth参数。

const sheets = google.sheets({version:'v4',auth:authClient);

最好的方法是为所有Google API调用设置auth默认设置,然后您不必将authClient传递给任何工作表对象或API调用。

google.options({
  auth: authClient
});

如果您计划为不同的API使用不同的服务帐户,您仍然可以覆盖工作表(或驱动器或任何其他对象)API对象或任何API调用中的auth参数。

要在本地进行测试,您始终可以设置环境路径,这样您就不必将服务帐户传递给google.auth对象。这就是我的做法

let resolve = require('path').resolve;
if (process.env.NODE_ENV === 'production') {
  //Set config based on production environment. It won't be set in local environment, unless you specially set it.
} else if (!process.env.GOOGLE_APPLICATION_CREDENTIALS) {
  process.env.GOOGLE_APPLICATION_CREDENTIALS = resolve(
      './relative/path/to/the/json/key.json'
  ); //resolve will just convert relative path to the absolute path.
}