我正在使用Next.js 13和firebase auth与id令牌开发一个应用程序。
我想利用Next.JS内置的服务器端组件功能来更快地获取用户数据,因此我需要在初始请求时验证服务器上的id令牌。当没有用户登录受保护的路由时,我想重定向到登录页面。
当用户处于非活动状态超过1小时并且id令牌已过期时,问题就会出现。下一个请求头将发送过期令牌,导致auth.verifyIdToken
拒绝它。这将在任何客户端代码有机会运行之前将用户重定向到登录页面,包括user.getIdToken
刷新令牌。
服务器端有没有刷新id token的方法?我在这里看到,有一个使用firebase REST API的解决方案,似乎不安全。
背景
我使用firebaseui
[package][2]进行登录,它创建了初始的id token和refresh 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>
);
};
服务器端令牌验证
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,
};
};
1条答案
按热度按时间jdzmm42g1#
对于SSR应用,您应该使用session cookies。与ID令牌不同,它们不会在1小时内过期,您可以将其配置为最多14天处于活动状态。
当用户使用Firebase客户端SDK登录时,您可以使用
getIdToken()
一次,并向其传递一个API,该API可以生成和设置可以在后续请求中读取的会话cookie。这样您就不必使用侦听器保持令牌更新。请确保您通过将auth persistence设置为
none
或显式注销用户来从客户端SDK注销用户,以便在您清除cookie(使用注销API)的情况下,客户端没有用户。