From bac263c0974f3a0fb514858877885d01f0a9530f Mon Sep 17 00:00:00 2001 From: admin Date: Fri, 20 Mar 2026 20:12:03 +0700 Subject: [PATCH] 690320:2012 login #01 --- frontend/lib/auth.ts | 53 +++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/frontend/lib/auth.ts b/frontend/lib/auth.ts index fd72b46..726313a 100644 --- a/frontend/lib/auth.ts +++ b/frontend/lib/auth.ts @@ -11,15 +11,19 @@ const loginSchema = z.object({ password: z.string().min(1), }); -const baseUrl = (typeof window === "undefined" ? process.env.INTERNAL_API_URL : null) || process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001/api"; +// ✅ ใช้แบบ SSR-safe (ดีที่สุด) +const baseUrl = + (typeof window === "undefined" ? process.env.INTERNAL_API_URL : null) || + process.env.NEXT_PUBLIC_API_URL || + "http://localhost:3001/api"; // Helper to parse JWT expiry function getJwtExpiry(token: string): number { try { - const payload = JSON.parse(atob(token.split('.')[1])); - return payload.exp * 1000; // Convert to ms + const payload = JSON.parse(atob(token.split(".")[1])); + return payload.exp * 1000; } catch { - return Date.now(); // If invalid, treat as expired + return Date.now(); } } @@ -46,9 +50,7 @@ async function refreshAccessToken(token: JWT) { accessTokenExpires: getJwtExpiry(data.access_token), refreshToken: data.refresh_token ?? token.refreshToken, }; - } catch (error) { - // RefreshAccessTokenError - token will be invalidated - + } catch { return { ...token, error: "RefreshAccessTokenError", @@ -73,15 +75,15 @@ export const { if (!credentials?.username || !credentials?.password) return null; try { - // 1. Sanitize payload (Only send username and password) + // ✅ sanitize payload const payload = { username: credentials.username as string, password: credentials.password as string, }; console.log(`[AUTH] Attempting login at: ${baseUrl}/auth/login`); - console.log(`[AUTH] Current process.env.INTERNAL_API_URL: ${process.env.INTERNAL_API_URL}`); - console.log(`[AUTH] Current process.env.NEXT_PUBLIC_API_URL: ${process.env.NEXT_PUBLIC_API_URL}`); + console.log(`[AUTH] INTERNAL_API_URL: ${process.env.INTERNAL_API_URL}`); + console.log(`[AUTH] NEXT_PUBLIC_API_URL: ${process.env.NEXT_PUBLIC_API_URL}`); const res = await fetch(`${baseUrl}/auth/login`, { method: "POST", @@ -89,7 +91,7 @@ export const { headers: { "Content-Type": "application/json", }, - cache: 'no-store', // Disable caching for auth requests + cache: "no-store", }); if (!res.ok) { @@ -99,16 +101,21 @@ export const { return null; } - const data = await res.json(); - // Handling both { data: { ... } } and direct { ... } response formats - const backendData = data.data || data; + const responseJson = await res.json(); + console.log("[AUTH] Backend raw response:", JSON.stringify(responseJson)); + + const backendData = responseJson.data || responseJson; if (!backendData || !backendData.access_token) { - console.error("[AUTH] Login failed: Invalid response format from backend (missing access_token)"); + console.error("[AUTH] Invalid backend response:", backendData); return null; } - console.log(`[AUTH] Login Successful for user: ${backendData.user?.username || 'unknown'}`); + console.log( + `[AUTH] Login Successful for user: ${ + backendData.user?.username || "unknown" + }` + ); return { id: backendData.user.user_id.toString(), @@ -120,9 +127,8 @@ export const { accessToken: backendData.access_token, refreshToken: backendData.refresh_token, } as User; - } catch (error) { - console.error("[AUTH] Network/Fetch Error during authorize:", error); + console.error("[AUTH] Network Error:", error); return null; } }, @@ -138,7 +144,7 @@ export const { return { ...token, id: user.id, - username: user.username, // ✅ Save username + username: user.username, role: user.role, organizationId: user.organizationId, accessToken: user.accessToken, @@ -147,23 +153,20 @@ export const { }; } - // Return previous token if valid (minus 10s buffer) if (Date.now() < (token.accessTokenExpires as number) - 10000) { return token; } - // If existing token has an error, do not retry refresh (prevents infinite loop) if (token.error) { return token; } - // Token expired, refresh it return refreshAccessToken(token); }, async session({ session, token }) { if (token && session.user) { session.user.id = token.id as string; - session.user.username = token.username as string; // ✅ Restore username + session.user.username = token.username as string; session.user.role = token.role as string; session.user.organizationId = token.organizationId as number; @@ -176,8 +179,8 @@ export const { }, session: { strategy: "jwt", - maxAge: 24 * 60 * 60, // 24 hours + maxAge: 24 * 60 * 60, }, secret: process.env.AUTH_SECRET, debug: process.env.NODE_ENV === "development", -}); +}); \ No newline at end of file