我正在开发一个使用 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/