refactor(auth): centralize auth routing via proxy and marker cookie

This commit is contained in:
2026-06-10 12:47:47 +08:00
parent 1db3e3ae31
commit 2066934094
7 changed files with 156 additions and 38 deletions
+43
View File
@@ -52,6 +52,13 @@ export async function logout(): Promise<Result<void>> {
// 清理业务层 token
await SpAsyncUtil.remove(StorageKeys.loginToken);
await SpAsyncUtil.remove(StorageKeys.refreshToken);
// 同步清路由信号 cookieclient 端走 marker API,让 server 端设 Max-Age=0
// fail-softfetch 失败不影响登出主流程(localStorage 已清,业务不可用)
try {
await fetch("/api/auth/marker", { method: "DELETE" });
} catch (e) {
console.warn("[nextauth-helpers] failed to clear auth cookie", e);
}
return Result.ok(undefined);
}
@@ -124,9 +131,39 @@ interface SocialSession {
userId: string;
}
/** 路由信号 cookie 配置(与 `src/app/api/auth/marker/route.ts` 保持一致) */
const AUTH_COOKIE_NAME = "cozsweet_authed";
const AUTH_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
/**
* server 端设路由信号 cookie(由 signIn callback 调用)
*
* 必须在 server 上下文运行(使用 `next/headers` 的 `cookies()`)。
* 本函数被 `persistBackendSession` 调用,后者仅在 NextAuth signIn callback
* 内被触发,那是 server 上下文。
*
* dynamic import next/headers 避免 client bundle 误报。
*/
async function setAuthCookieServerSide(): Promise<void> {
const { cookies } = await import("next/headers");
(await cookies()).set({
name: AUTH_COOKIE_NAME,
value: "1",
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
path: "/",
maxAge: AUTH_COOKIE_MAX_AGE,
});
}
/**
* 把后端返回的 LoginResponse 写入 NextAuth 可访问的临时存储。
* jwt callback 中会从这里读取。
*
* 同时设路由信号 cookie`cozsweet_authed`)供 `src/router/proxy.ts` 读取。
* cookie 写失败仅记录 warn,不阻断主流程(业务 token 已落 unstorage,下一次
* 请求仍可走业务自检)。
*/
async function persistBackendSession(data: {
token: string;
@@ -139,6 +176,12 @@ async function persistBackendSession(data: {
}
// userId 写入 unstorage(其他业务模块通过 useUserState 读)
await SpAsyncUtil.setString(StorageKeys.userId, data.user.id);
// 路由信号 cookieserver 端 next/headers 写)
try {
await setAuthCookieServerSide();
} catch (e) {
console.warn("[nextauth-helpers] failed to set auth cookie", e);
}
}
export async function getSocialSession(): Promise<SocialSession | null> {