FCM OAuth2.0 访问令牌创建抛出 "TypeError [ERR_INVALID_ARG_TYPE]" 错误

FCM OAuth2.0 access token creation throwing "TypeError [ERR_INVALID_ARG_TYPE]" error

我正在尝试使用 JSON Web 令牌 (JWT) 为 Firebase 云消息传递创建访问令牌,但我无法将给定令牌应用于 FCM HTTP v1 API 请求 headers .当我使用 Postman 进行测试时,该函数在我的云函数之外工作,并且我能够创建令牌并使用 index.js:

中的此函数成功发送推送通知
async function getAccessToken(keyFile = process.env.GOOGLE_APPLICATION_CREDENTIALS) {
  return new Promise(function(resolve, reject) {

    const keys = require(keyFile)
    const client = new JWT({
      email: keys.client_email,
      key: keys.private_key,
      scopes: [
        'https://www.googleapis.com/auth/cloud-platform',
        'https://www.googleapis.com/auth/firebase.messaging'
      ]
    });

    client.authorize((err, tokens) => {
      if (err) {
        reject(err)
        return
      }
      resolve(tokens.access_token.replace(/\.+$/, ''))
    })
  })
}

my-cloud-function.js 文件中,我将这个相同的函数添加到我的云函数中,将其从 index.js 中删除(它用于测试目的)并尝试像这样发送 FCM:

await fetch(`https://fcm.googleapis.com/v1/projects/${my-project}/messages:send`, {
    method: 'POST',
    headers: {
         'Content-Type': 'application/json',
         'Authorization': getAccessToken()
    },
    body: {
        "message": {
          "topic": `${my-topic}`,
          "notification": {
            "title": "Test",
            "body": "Testing."
          },
        }
    },
})
    .then((response) => {
        response.json().then(res => {
            functions.logger.log('res', res)
            functions.logger.log('token::::', getAccessToken())
        })
        .catch(e => {
            functions.logger.log('an error here', e)
        })
    })
    .catch(error => {
        functions.logger.log('error:', error)
    })
    

同样,这个 post 请求在 Postman 中有效。我在云函数日志中得到的错误是:

TypeError [ERR_INVALID_ARG_TYPE]: The "id" argument must be of type string. Received undefined
    at new NodeError (internal/errors.js:322:7)
    at validateString (internal/validators.js:124:11)
    at Module.require (internal/modules/cjs/loader.js:967:3)
    at require (internal/modules/cjs/helpers.js:93:18)
    at /workspace/my-cloud-function.js:11:22
    at new Promise (<anonymous>)
    at getAccessToken (/workspace/my-cloud-function.js:10:12)
    at /workspace/my-cloud-function.js:95:59
    at processTicksAndRejections (internal/process/task_queues.js:95:5) 

错误指向第10、11和95行。第11行是const keys = require(keyFile),第95行是functions.logger.log('token::::', getAccessToken())。我在网上看到 require 语句接受一个字符串,我认为 keyFile 是。它在 Postman 中有效,但我现在被卡住了。任何帮助将不胜感激。

我终于想出了如何使用 Firebase Admin SDK 对云消息进行身份验证,而不是尝试使用 JWT。在我的 index.js 文件中,我有:

const admin = require('firebase-admin');
admin.initializeApp({
  credential: admin.credential.applicationDefault(),
});

为了让它工作,我必须在 Google 云平台网站中找到我的功能,编辑功能,点击 Runtime, build, connections and security settings ,-> Runtime,- > Runtime service account 并从那里选择 Admin SDK 服务帐户部署。