使用新的firebase云功能,我决定将一些HTTP端点移动到firebase。 一切都很好……但我有以下问题。我有两个端点构建HTTP触发器(云函数)

用于创建用户并返回自定义令牌的API端点 由Firebase Admin SDK生成。 获取特定用户详细信息的API端点。

虽然第一个端点很好,但对于第二个端点,我希望仅为经过身份验证的用户保护它。意思是拥有我之前生成的令牌的人。

我该怎么解呢?

我知道我们可以在云函数中使用Header参数

request.get('x-myheader')

但是有没有一种方法可以像保护实时数据库一样保护端点呢?


当前回答

在Firebase中,为了简化你的代码和工作,这只是一个架构设计的问题:

For public accessible sites/contents, use HTTPS triggers with Express. To restrict only samesite or specific site only, use CORS to control this aspect of security. This make sense because Express is useful for SEO due to its server-side rendering content. For apps that require user authentication, use HTTPS Callable Firebase Functions, then use the context parameter to save all the hassles. This also makes sense, because such as a Single Page App built with AngularJS -- AngularJS is bad for SEO, but since it's a password protected app, you don't need much of the SEO either. As for templating, AngularJS has built-in templating, so no need for sever-side template with Express. Then Firebase Callable Functions should be good enough.

有了以上的思想,没有更多的麻烦,让生活更容易。

其他回答

我一直在努力在golang GCP函数中获得正确的firebase身份验证。实际上没有这样的例子,所以我决定构建这个小库:https://github.com/Jblew/go-firebase-auth-in-gcp-functions

现在,您可以使用firebase-auth(它与gcp-authenticated-functions不同,并且身份识别代理不直接支持)轻松地对用户进行身份验证。

下面是一个使用实用程序的示例:

import (
  firebaseGcpAuth "github.com/Jblew/go-firebase-auth-in-gcp-functions"
  auth "firebase.google.com/go/auth"
)

func SomeGCPHttpCloudFunction(w http.ResponseWriter, req *http.Request) error {
   // You need to provide 1. Context, 2. request, 3. firebase auth client
  var client *auth.Client
    firebaseUser, err := firebaseGcpAuth.AuthenticateFirebaseUser(context.Background(), req, authClient)
    if err != nil {
    return err // Error if not authenticated or bearer token invalid
  }

  // Returned value: *auth.UserRecord
}

请记住,部署函数时使用——allow-unauthenticated标志(因为firebase身份验证是在函数执行过程中进行的)。

希望这能帮助你,就像它帮助了我一样。出于性能方面的考虑,我决定使用golang来实现云函数——jlddrzej

上述方法使用函数内部的逻辑对用户进行身份验证,因此仍然必须调用函数来进行检查。

这是一个非常好的方法,但为了全面起见,还有另一种选择:

你可以将一个函数设置为“私有”,这样除了注册用户(由你决定权限),它不能被调用。在这种情况下,在函数上下文中拒绝未经身份验证的请求,并且根本不会调用函数。

这里引用(a)将函数配置为公共/私有,然后(b)对最终用户进行函数的身份验证。

请注意,上面的文档是针对谷歌云平台的,实际上,这是可行的,因为每个Firebase项目也是一个GCP项目。与此方法相关的一个警告是,在撰写本文时,它仅适用于基于google帐户的身份验证。

正如@Doug所提到的,您可以使用firebase-admin来验证令牌。我举了一个简单的例子:

exports.auth = functions.https.onRequest((req, res) => {
  cors(req, res, () => {
    const tokenId = req.get('Authorization').split('Bearer ')[1];
    
    return admin.auth().verifyIdToken(tokenId)
      .then((decoded) => res.status(200).send(decoded))
      .catch((err) => res.status(401).send(err));
  });
});

在上面的例子中,我也启用了CORS,但这是可选的。首先,获取Authorization头并找出令牌。

然后,您可以使用firebase-admin来验证该令牌。您将在响应中获得该用户的解码信息。否则,如果令牌无效,它将抛出一个错误。

正如@Doug提到的, 你可以使用可调用函数来从你的客户端和服务器中排除一些样板代码。

示例可调用函数:

export const getData = functions.https.onCall((data, context) => {
  // verify Firebase Auth ID token
  if (!context.auth) {
    return { message: 'Authentication Required!', code: 401 };
  }

  /** This scope is reachable for authenticated users only */

  return { message: 'Some Data', code: 200 };
});

它可以直接从你的客户端调用,像这样:

firebase.functions().httpsCallable('getData')({query}).then(result => console.log(result));

你可以把它当作一个函数返回布尔值。如果用户验证与否,您将继续或停止您的API。此外,您还可以从变量decode返回声明或用户结果

const authenticateIdToken = async (
    req: functions.https.Request,
    res: functions.Response<any>
) => {
    try {
        const authorization = req.get('Authorization');
        if (!authorization) {
            res.status(400).send('Not Authorized User');
            return false;
        }
        const tokenId = authorization.split('Bearer ')[1];

        return await auth().verifyIdToken(tokenId)
            .then((decoded) => {
                return true;
            })
            .catch((err) => {
                res.status(401).send('Not Authorized User')
                return false;
            });
    } catch (e) {
        res.status(400).send('Not Authorized User')
        return false;
    }
}