reactjs - 刷新 firebase id token 服务器端

标签 reactjs firebase next.js firebase-authentication

我正在开发一个使用 Next.js 13 和带有 id token 的 firebase 身份验证的应用程序。

我想利用服务器端组件的 Next.JS 内置功能来更快地获取用户数据,因此我需要在初始请求时验证服务器上的 id token 。当没有用户登录 protected 路由时,我想重定向到登录页面。

当用户处于非事件状态超过 1 小时并且 ID token 已过期时,就会出现问题。下一个请求 header 将发​​送过期的 token ,导致 auth.verifyIdToken 拒绝它。这将在任何客户端代码有机会运行之前将用户重定向到登录页面,包括用于刷新 token 的 user.getIdToken

有没有办法在服务器端刷新 id token ?我读过here ,有一个使用 firebase REST API 的解决方法,这似乎不安全。

上下文

我使用 `firebaseui` [package][2] 进行登录,它创建初始 id token 和刷新 token 。然后我有一个 `AuthContextProvider` 来提供并刷新客户端上的 id token :
const ServerAuthContextProvider = ({
  children,
  user,
  cookie,
}: {
  children: ReactNode;
  user: UserRecord;
  cookie: Cookie;
}) => {
  useEffect(() => {
    if (typeof window !== "undefined") {
      (window as any).cookie = cookie;
    }
    return auth.onIdTokenChanged(async (snap) => {
      if (!snap) {
        cookie.remove("__session");
        cookie.set("__session", "", { path: "/" });
        return;
      }
      const token = await snap.getIdToken();
      cookie.remove("__session");
      cookie.set("__session", token, { path: "/" });
    });
  }, [cookie]);

  return (
    <serverAuthContext.Provider
      value={{
        user,
        auth,
      }}
    >
      {children}
    </serverAuthContext.Provider>
  );
};
  );
};

服务器端根组件

const RootLayout = async ({ children }: { children: React.ReactNode }) => {
  const { user } = await verifyAuthToken();
  if (!user) redirect("/login");

  return (
    <html lang="en">
      <body>
        <ServerAuthContextProvider user={user}>
          {children}
        </ServerAuthContextProvider>
      </body>
    </html>
  );
};

服务器端 token 验证

const verifyAuthToken = async () => {
  const auth = getAuth(firebaseAdmin);

  try {
    const session = cookies().get("__session");
    if (session?.value) {
      console.log("found token");
      const token = await auth.verifyIdToken(session.value);
      const { uid } = token;
      console.log("uid found: ", uid);
      const user = await auth.getUser(uid);
      return {
        auth,
        user,
      };
    }
  } catch (error: unknown) {
    if (typeof error === "string") {
      console.log("error", error);
      return {
        auth,
        error,
      };
    } else if (error instanceof Error) {
      console.log("error", error.message);

      return {
        auth,
        error: error.message,
      };
    }
  }
  return {
    auth,
  };
};

最佳答案

对于 SSR 应用程序,您应该使用 session cookies 。与 ID token 不同,它们不会在 1 小时内过期,您可以将它们配置为最长有效 14 天。
当用户使用 Firebase 客户端 SDK 登录时,您可以使用 getIdToken() 一次,并向其传递一个 API,该 API 会生成并设置可在后续请求中读取的 session Cookie。 这样您就不必使用监听器来更新 token 。

请确保通过设置 auth persistence 从客户端 SDK 注销用户。 none 或明确注销用户,这样万一您清除了他们的 cookie(使用注销 API),客户端就没有用户了。

关于reactjs - 刷新 firebase id token 服务器端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75365962/

相关文章:

next.js - 如何让我的 NextJS 应用接受 otf 和 ttf 字体?

reactjs - 运行命令 npm start 后,如何在开发模式下的特定路线上启动 React 应用程序,而不是从主路线启动

javascript - 为什么 JS/React 比 WebAssembly/Rust 快得多?

javascript - 如何使用 Web Audio API 添加 LFO 来过滤截止

npm - Next.js 项目未启动

django - 使用 Django 和 NextJS 进行用户身份验证

android - 适用于 IO 但不适用于 Android 的自定义字体

firebase - 安全 API 身份验证和 $ 变量不相等

使用 GCP 服务帐户登录 Firebase

firebase - 使用带有 vuefire 手动绑定(bind)的 Firebase 用户 UID