【问题标题】:Cloud Function & client authentication during HTTPS Call using firebase admin Auth在 HTTPS 调用期间使用 firebase admin Auth 进行云功能和客户端身份验证
【发布时间】:2021-10-17 05:28:58
【问题描述】:

背景: 我有三个实体(语言: JS):

  1. 浏览器上的客户端
  2. 谷歌云函数
  3. HTTP 服务器 [具有 Firebase 管理员身份验证中间件]

所以,从 1 和 2,我想使用 HTTPS 调用与 3 通信。 因为 3 已经有管理员身份验证,所以我可以授权来自客户端的调用 (1)。

但我想知道如何授权来自谷歌云功能的调用(2),以便我可以安全地与两个实体通信。

令牌认证中间件:

const validateFirebaseIdToken = async (req: any, res: any, next: any) => {
  console.log(await auth.getCredentials());
  if (
    (!req.headers.authorization ||
      !req.headers.authorization.startsWith("Bearer ")) &&
    !(req.cookies && req.cookies.__session)
  ) {
    console.log(
      "No Firebase ID token was passed as a Bearer token in the Authorization header." +
        "Make sure you authorize your request by providing the following HTTP header:" +
        "Authorization: Bearer <Firebase ID Token>" +
        'or by passing a "__session" cookie.'
    );
    res.status(403).send("Unauthorized 1");
    return;
  }

  let idToken;
  if (
    req.headers.authorization &&
    req.headers.authorization.startsWith("Bearer ")
  ) {
    console.log('Found "Authorization" header');
    // Read the ID Token from the Authorization header.
    idToken = req.headers.authorization.split("Bearer ")[1];
  } else if (req.cookies) {
    console.log('Found "__session" cookie');
    // Read the ID Token from cookie.
    idToken = req.cookies.__session;
  } else {
    // No cookie
    res.status(403).send("Unauthorized 2");
    return;
  }

  try {
    const decodedIdToken = await admin.auth().verifyIdToken(idToken);
    req.user = decodedIdToken;
    next();
    return;
  } catch (error) {
    console.log("Error while verifying Firebase ID token:" + error);
    res.status(403).send("Unauthorized 3");
    return;
  }
};

【问题讨论】:

    标签: node.js firebase firebase-authentication google-cloud-functions authorization


    【解决方案1】:

    听起来您正试图从云函数对您的服务器进行 API 调用。如果您正在使用 functions.https.onCall 可调用函数,该函数会自动反序列化请求正文并验证身份验证令牌。因此,除非您明确传递它们,否则您不会获得实际的 ID 令牌。

    要将用户信息传递到您的服务器,您可以尝试以下任一方法:

    1. 将 ID Token 显式传递给云函数,然后传递给您的 API,该 API 将再次验证 ID Token。

    2. 如前所述,可调用的云函数将自动验证用户并将DecodedIdToken 添加到context.auth.token。由于用户已经通过身份验证,您可以简单地将用户的 UID(以及其他必要的声明)传递给您的服务器以进行进一步处理。但是,这意味着您必须配置中间件,使其接受 UID 而不是令牌,通过直接向具有某些 UID 的服务器发出随机请求,可能会被滥用。

    如果您使用方法 2,则必须确保请求仅来自您的云功能。这可以通过在云功能和服务器之间共享一个秘密来完成,您可以将该秘密附加到您向服务器发出的每个 HTTP 请求中,类似于 API 密钥。

    【讨论】:

    • 感谢您的回复。实际上,我正在尝试从客户端进行调用以及从函数中进行一些调用,所以我想可能需要 2 种身份验证方法。有没有一种方法可以将一个服务帐户验证到另一个服务帐户。希望你明白我的意思
    • @AkashSrivastava 如果您使用的是同一个 Firebase 项目,我猜您应该只有 1 个服务帐户。当您从客户端直接调用服务器时,您可以像现在一样在授权标头中传递 ID 令牌。但是,当从云函数调用 API 时,您首先需要知道哪个用户调用了可调用函数,以便将 ID 令牌传递到那里。您能否更清楚地了解这些功能是如何触发的?如果它们被任何客户端用户调用,那么您可以获得 ID 令牌,正如我的回答所解释的那样。还是Firestore触发器之类的后台功能?
    • 嘿@Dharmaraj,我明白了传递令牌ID的目的。这些调用是内部的,但我们有与每个函数调用相关联的用户,所以我想它可以通过这种方式实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    • 2022-10-30
    • 2018-12-29
    • 1970-01-01
    • 2015-10-29
    相关资源
    最近更新 更多