具有Bearer令牌的具有Google Firebase身份验证和功能的REST API

问题描述 投票:0回答:1

快速背景:我正在编程一个被认为是“独立”使用的API,即不涉及任何前端。 API访问应直接来自例如邮递员或在身份验证标头中带有Bearer令牌的Curl。

我看着Google Firebase并认为它很合适,因为所有身份验证都已经“内置”并且与Google Cloud Functions直接兼容。但是,经过一个周末的实验之后,我似乎无法弄清楚如何实现REST API(使用Google Cloud Functions),用户可以在其中(在Web界面中)请求API令牌与API进行交互。我不想自己处理身份验证。我真的很想对API使用Firebase身份验证。

这是最终过程的样子:

  1. 用户使用标准Firebase身份验证过程登录到Web界面。
  2. 用户单击“请求API密钥”之类的内容,并在网络界面中显示密钥(例如abc ...)。由Firebase身份验证生成。
  3. 用户可以通过例如卷曲到Google Cloud Functions中托管的API,只需设置授权标头(Bearer abc ...),该令牌的“验证”将由Firebase身份验证处理。

这是我已经尝试生成的令牌:

admin.auth().createCustomToken(uid)
.then(function(customToken) {
    console.log(customToken);
})
.catch(function(error) {
    console.log('Error creating custom token:', error);
})

然后将登录到Postman中的控制台的令牌设置为Bearer Token,然后使用以下函数来验证令牌:

const authenticate = async (req, res, next) => {
if (!req.headers.authorization || !req.headers.authorization.startsWith('Bearer ')) {
  res.status(403).send('Unauthorized');
  return;
}
const idToken = req.headers.authorization.split('Bearer ')[1];
try {

  const decodedIdToken = await admin.auth().verifyIdToken(idToken);
  req.user = decodedIdToken;
  next();
  return;
} catch(e) {
  console.log(e);
  res.status(403).send('Unauthorized');
  return;
}
}

然后我收到此错误

message: 'verifyIdToken() expects an ID token, but was given a custom token. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.'

我知道,如果我要实现一个Web界面,我可以从devtools(?)中获取ID令牌,但是该令牌仅有效1小时……我需要的是“无限期”有效的令牌并可以生成并显示给用户。

[我想我知道我必须以某种方式使用自定义令牌,但无法弄清楚如何使它们工作...(https://firebase.google.com/docs/auth/admin/create-custom-tokens)。

非常感谢大家!

最佳瑞克

javascript firebase firebase-authentication google-cloud-functions firebase-admin
1个回答
0
投票

您正在尝试在Firebase和Cloud Functions的基础上构建API管理解决方案。自定义令牌和ID令牌不适用于此目的。自定义令牌仅旨在用作最终用户设备上的用户身份验证凭据,而ID令牌则表示成功的身份验证响应。两种令牌都将在一个小时后失效。

如果您需要长期的托管API密钥,则必须自己实现它们。 Firebase内置没有任何可以直接使用的东西。我曾经将这样的解决方案作为原型实现,每次用户登录并请求API密钥时,我都会生成一个Firestore文档。然后,我使用文档ID作为API密钥,可以在Cloud Function中对其进行验证。

const apiKey = req.headers.authorization.split('Bearer ')[1];
const doc = await admin.firestore().collection('apiKeys').doc(apiKey).get();
if (doc.exists) {
  next();
}

我还必须实现一些本地API密钥缓存,以使其高效地工作。

您可以使用Google Cloud Endpoints(https://cloud.google.com/endpoints)之类的解决方案来避免某些工作,尽管我对此没有任何个人经验。最后,还要研究开放源代码解决方案,例如https://wso2.com/api-management/,使您能够设置自己的API密钥管理和网关。

© www.soinside.com 2019 - 2024. All rights reserved.