Firebase 身份验证状态在客户端上持续存在,但在硬刷新时不存在

Firebase auth state persists on client, but not on hard refresh

我正在构建一个使用 Express 处理服务器请求的同构 React 应用程序。

当 运行 在客户端绑定 React 应用程序时,我的 Firebase 登录流程运行良好:

但是,硬刷新(来自服务器)不会持续存在,即使在客户端成功登录后也是如此。在服务器上下文中使用相同的 React 组件,ref.getAuth() returns null.

我是否遗漏了一个步骤来使它在服务器上以与在客户端上相同的方式工作(用例是站点的硬刷新)?

如果您在 isomorphic/universal 渲染过程中连接到服务器上的 Firebase(我假设您是),Firebase 无法知道哪个用户向您的服务器发起了请求,随后向 Firebase 发出请求——在客户端,用户的 cookie 可以被发送到 Firebase,但它是你的服务器,而不是客户端,它在服务器上发起请求,所以是未与任何给定用户相关联。

我的第一个想法是,为了从服务器发送身份验证,您需要在自己的服务器上进行某种登录;一旦您验证(使用 Firebase 或其他方式)用户是他们所说的那个人,您就可以 generate a token 您可以(安全地)保存在用户的会话中并发送回客户端。然后,在客户端上,andeach 服务器请求上,就在使用 React.render* 呈现 React 应用程序之前,您将调用 authWithCustomToken() 使用该用户的令牌。

然而,需要注意的是,对 Firebase 数据库的身份验证是全局的——当您对 Firebase 引用进行身份验证时(即使在 Node.js 中),指向同一数据库的所有其他引用都会通过这些引用进行身份验证证书;您不能使用单独的 refs 以不同的用户身份登录。因此,如果服务器上的 React 渲染管道在调用 auth 回调和渲染应用程序之间执行任何异步操作(例如,如果您使用 react-async 之类的东西或在渲染前进行其他花哨的异步数据加载),在您开始呈现您的应用程序时,针对您的 Firebase 进行身份验证的用户可能已经 更改 。但是,如果您的渲染管道是纯同步的,您应该能够摆脱这种策略(getAuth() 可以帮助确保您在渲染之前拥有正确的身份验证)。

除此之外,我认为最直接的解决方案如下:

  1. 通过您自己的服务器对您的用户进行身份验证,创建一个 secure token 并将其传回客户端以进行身份​​验证。将此令牌存储在用户的会话中,以便客户端可以请求它并根据需要在客户端上使用它进行身份验证。您还需要生成自己的身份验证数据(通常传递给 authWithPassword 的回调的内容)并将其存储在会话中。

  2. 对于您的 Firebase 的服务器请求,请使用 the recommended server authentication schemes:

    之一

    Using a Firebase app secret: All authentication methods can accept a Firebase app secret instead of a JWT token. This will grant the server complete read and write access to the entire Firebase database. This access will never expire unless it is revoked via the App Dashboard.

    Using a secure JWT with the optional admin claim set to true: This method will grant a server complete read and write access to the entire Firebase database. This token will expire normally, so it is important to set the expiration times accordingly.

    Using a secure JWT designed to give access to only the pieces of data a server needs to touch: This method is more complicated, but it is the safest way to authenticate a server as it lets the Security and Firebase Rules prevent the server from doing anything it's not supposed to, even if it becomes compromised in some way.

  3. 包括服务器逻辑以确保当前登录的用户只能访问适当的数据。由于上述身份验证方法将授予用户可能有权或可能无法访问的数据的访问权限,因此您需要采取自己的步骤来确保用户不会意外访问对于他们不应该做的事情。

  4. 将您在第一步中存储在会话中的身份验证数据作为 属性 传递给 React 应用程序,而不是依赖 ref.getAuth() 之类的东西来获取此数据在你的 React 应用程序中(因为它不能在服务器上运行),以在你的 UI.

  5. 中识别用户