refactor(auth): inline NextAuth v4 config and simplify AuthPlatform API

- Inline NextAuth v4 handler directly in `[...nextauth]/route.ts`, removing
  the `@/lib/auth/nextauth` abstraction layer
- Add Google/Facebook providers with JWT/session callbacks that expose
  `idToken` and `accessToken` on the session for backend exchange
- Refactor `AuthPlatform` from constructor-based to static methods
  (`googleSignIn()` / `facebookSignIn()`)
- Update `auth-machine.ts` and layout comment reference to match new structure
- Align with original Dart `nextauth-helpers.{googleLogin, facebookLogin}()`
  naming and keep persistence concerns (unstorage, backend, custom cookies)
  out of scope for this iteration
This commit is contained in:
2026-06-12 17:20:56 +08:00
parent 1f83171067
commit dbc9a0cd13
6 changed files with 69 additions and 93 deletions
+49 -10
View File
@@ -1,14 +1,53 @@
/**
* NextAuth App Router 入口(v4 模式
* NextAuth v4 配置(route 端
*
* v4 用单个 handler 函数,需手动 re-export 为 `GET` / `POST`
* /api/auth/signin/[provider]
* /api/auth/callback/[provider]
* /api/auth/signout
* /api/auth/session
* /api/auth/csrf
* /api/auth/providers
* 极简模式:参考 `auth.js` 官方示例的**精神**(不做任何持久化),但保留 v4 语法
* - 客户端点击登录按钮 → `AuthPlatform.googleSignIn()` / `AuthPlatform.facebookSignIn()`
* - NextAuth 重定向到 Google / Facebook OAuth
* - OAuth 回调 → NextAuth 写 `next-auth.session-token` (httpOnly) cookie
* - 重定向到 callbackUrl (默认 /chat)
* - 业务 token 持久化(unstorage / 后端 / 自定义 cookie**全部不在本轮 scope**
*
* v4 模式:`NextAuth(options)` 返回单个 handler 函数(v5 才返回 `{ handlers, signIn, signOut, auth }`)。
* 通过 `export { handler as GET, handler as POST }` 暴露给 Next.js 路由。
*/
import { GET, POST } from "@/lib/auth/nextauth";
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
import Facebook from "next-auth/providers/facebook";
export { GET, POST };
const handler = NextAuth({
providers: [
Google({
clientId: process.env.AUTH_GOOGLE_ID ?? "",
clientSecret: process.env.AUTH_GOOGLE_SECRET ?? "",
}),
Facebook({
clientId: process.env.AUTH_FACEBOOK_ID ?? "",
clientSecret: process.env.AUTH_FACEBOOK_SECRET ?? "",
}),
],
// 把 OAuth provider 的 token 塞进 NextAuth session,供前端取用:
// - Google: account.id_token → 调后端 /api/auth/google-login 换业务 token
// - Facebook: account.access_token → 调后端 /api/auth/facebook-login
// 仅在**首次 sign-in** 时把 `account` 注入到 JWT;后续请求 account=undefined
// (由 NextAuth 控制),所以下面的 `if (account)` 守卫是必要的。
callbacks: {
async jwt({ token, account }) {
if (account) {
token.provider = account.provider;
token.idToken = account.id_token;
token.accessToken = account.access_token;
}
return token;
},
async session({ session, token }) {
// 暴露给 `useSession()` —— 仅 client-side 派发 sync 事件时使用,不落 localStorage
session.provider = (token.provider as "google" | "facebook" | undefined) ?? undefined;
session.idToken = (token.idToken as string | undefined) ?? undefined;
session.accessToken = (token.accessToken as string | undefined) ?? undefined;
return session;
},
},
});
export { handler as GET, handler as POST };