【发布时间】:2020-10-28 14:48:13
【问题描述】:
我正在尝试设置一个受限制的 firebase 函数,该函数可以从在 GCP 外部运行的另一个客户端应用程序调用。到目前为止,我未能设置客户端应用程序身份验证以通过 firebase 功能上的受限访问。
这是我所做和尝试的:
-
我创建并部署了一个简单的 helloWorld firebase 函数,并验证该函数可以从具有默认公共访问权限的客户端应用程序调用。
-
我从 GCP 的 helloWorld 权限中删除了 allUsers,并验证无法再从客户端应用程序调用该函数(我在响应中收到“403 Forbidden”)。
-
我创建了一个新的服务帐户,并将其添加为 GCP 上 helloWorld 权限面板中“云函数调用者”的成员。
-
我为此服务帐户创建了一个新的私有 json 密钥文件。
然后我按照documentation 设置客户端应用程序身份验证(参见下面的代码)。
const fetch = require('node-fetch');
const jwt = require('jsonwebtoken');
async function main(){
// get unix timestamp in seconds
const current_time = Math.floor(Date.now() / 1000)
// get the service account key file
const service_account = require('./service_account.json');
// create the jwt body
const token_body = {
"iss": service_account.client_email,
"scope": "https://www.googleapis.com/auth/cloud-platform",
"aud": "https://oauth2.googleapis.com/token",
"exp": current_time + 3600,
"iat": current_time
}
// sign the token with the private key
const signed_token = jwt.sign(
token_body, service_account.private_key, { algorithm: 'RS256' }
)
// get an access token from the authentication server
const access_token = await fetch(
'https://oauth2.googleapis.com/token',
{
method: 'POST',
body: ''
+ 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer'
+ '&'
+ 'assertion=' + signed_token,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}
).then(res => res.json()).then(body => body.access_token)
// call the firebase function with the Authorization header
return fetch(
url_hello_world, { headers: { 'Authorization': 'Bearer ' + access_token } }
).then(res => res.text()).then(console.log)
}
main().catch(console.error)
不幸的是,当我运行之前的代码时,我得到“401 Unauthorize”并带有以下标题:
www-authenticate: Bearer error="invalid_token" error_description="The access token could not be verified"
之后我尝试了另一种方法,使用以下tutorial(请参见下面的代码)。
const fetch = require('node-fetch');
const util = require('util');
const exec = util.promisify(require("child_process").exec)
async function main(){
// activate a service account with a key file
await exec('gcloud auth activate-service-account --key-file=' + key_file)
// retrieve an access token for the activated service account
const {stdout, stderr} = await exec("gcloud auth print-identity-token")
// get the access token from stdout and remove the new line character at the
// end of the string
const access_token = stdout.slice(0,-1)
// call the firebase function with the Authorization header
const response = await fetch(
url_hello_world,
{ headers: { 'Authorization': 'Bearer ' + access_token } }
)
// print the response
console.log(await response.text())
}
main().catch(console.error)
当我运行此代码时,我得到了预期的响应“Hello World”,因此前面的代码可以使用服务帐户权限调用 firebase 函数。
但是,我所针对的客户端应用程序不能依赖 gcloud cli,我被困在我试图了解上述第一个版本中什么不起作用以及我需要进行哪些更改以使其起作用的地步。
【问题讨论】:
标签: node.js firebase google-cloud-platform