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 服务帐户部署。
我正在尝试使用 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 服务帐户部署。