具有 JWT 身份验证和 Google Sheets V4 API 的 Firebase 可调用函数

Firebase Callable function with JWT Authentication and Google Sheets V4 API

我想使用 Google Sheets V4 API 通过 JWT 身份验证和从 Google Sheet 获取数据来实现 firebase 可调用函数。 对于测试,我尝试使用 Example Spreadsheet,但 Sheets API 未为该电子表格激活,我将其克隆到我自己的驱动器上并用于测试。

参考文献: 我的代码基于这个问题 How to use Google sheets API while inside a google cloud function and Accessing Google APIs using Service account in Node.JS

中描述的解决方案

我还得到了两个重要信息:"Service Account".jsonAPI Key.我在 api_key.json 中保存 API 键,但没有找到如何将其与 Google Sheets V4 API:

一起使用的示例
{ 
  key: "xxxxxx"
}

不需要任何身份验证的 test() 可调用函数工作正常:

exports.test = functions.https.onCall((data, context) => {
  return { text: data.text };
});

在客户端某处(在浏览器中)调用 test() 函数:

function getTest() {
  console.log("clicked getTest()");
  var test = firebase.functions().httpsCallable('test');

  test({text: '12345'}).then(function(result) {
    console.log(result);
  }).catch(function(error) {
    console.log(error.code);
    console.log(error.message);
  });
}

在客户端某处(在浏览器中)调用 getData():

function requestData() {
  console.log("clicked requestData()");

  //https://firebase.google.com/docs/functions/callable
  //getData() function described in functions/index.js

  var getData = firebase.functions().httpsCallable('getData');

  getData(null).then(function (result) {
    // Read result of the Cloud Function.
    console.log(result);  //<------- Expected rows from Spreadsheet????
  }).catch(function(error) {
    console.log(error.code);
    console.log(error.message);
  });
}

**谢谢你,F10。我更正了代码。 index.js:

'use strict'
const functions = require('firebase-functions');
const { google } = require('googleapis');
var serviceAccount = require("./credentials/owner-service-account-gcloud.json");

function getJwt() {
  // Define the required scopes.
  var scopes = [
    'https://www.googleapis.com/auth/spreadsheets'
  ];
  return new google.auth.JWT(
    serviceAccount.client_email,
    null,
    serviceAccount.private_key,
    scopes
  );
}

function getSpreadsheetDate(jwt) {

  return new Promise((resolve, reject) => {
    jwt.authorize((error, access_token) => {
      if (error) {
        console.log('Error in jwt.authorize: ' + error);
        reject(error);
      } else {
        // access_token ready to use to fetch data and return to client
        const sheets = google.sheets({ version: 'v4', access_token });

        // set auth as a global default:
        google.options({ auth: jwt }); //<---------------------- 

        const request = {
          auth: jwt,
          spreadsheetId: 'xxxx',
          range: 'Class Data!A2:E', //'Class Data!A2:E',
        }

        sheets.spreadsheets.values.get(request, (err, response) => {
          console.log("inside: sheets.spreadsheets.values.get() -------------------------------");

          if (err) {
            console.log('The Sheets API returned an error: ' + err);
            //The API returned an error: Error: API key not valid. Please pass a valid API key.
            reject(err);
          };

          try {
            var numRows = response.data.values ? response.data.values.length : 0;
            console.log('%d rows retrieved.', numRows);

            console.log("response.data:-------------------------------");
            console.log(response.data.values);

            resolve(response.data.values);

          } catch (err) {
            console.log("Error processing Sheets API response: " + err);
            reject(err);
          }

        })

      }
    })
  })

}


exports.getData = functions.https.onCall((data, context) => {
  console.log("getData()---------------------------");
  if (!context.auth) {
    throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' + 'while authenticated.');
  } else {
    console.log("context.auth ------------ OK");
    const uid = context.auth.uid;
    console.log(uid);

    var jwt = getJwt();
    console.log("getJwt() --------------- OK");

    return getSpreadsheetDate(jwt); //<------------ Requested Spreadsheet's Data

  }
})

exports.test = functions.https.onCall((data, context) => {
  return { text: data.text };
});

有一个 that uses googleapis instead of the auth library to do the authentication with JWT. Regarding your token inquiries, you could check the OAuth 2.0 for client-side web applications 文档,其中解释了进行身份验证的步骤。