This commit is contained in:
+27
-24
@@ -11,15 +11,19 @@ const loginSchema = z.object({
|
|||||||
password: z.string().min(1),
|
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
|
// Helper to parse JWT expiry
|
||||||
function getJwtExpiry(token: string): number {
|
function getJwtExpiry(token: string): number {
|
||||||
try {
|
try {
|
||||||
const payload = JSON.parse(atob(token.split('.')[1]));
|
const payload = JSON.parse(atob(token.split(".")[1]));
|
||||||
return payload.exp * 1000; // Convert to ms
|
return payload.exp * 1000;
|
||||||
} catch {
|
} 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),
|
accessTokenExpires: getJwtExpiry(data.access_token),
|
||||||
refreshToken: data.refresh_token ?? token.refreshToken,
|
refreshToken: data.refresh_token ?? token.refreshToken,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch {
|
||||||
// RefreshAccessTokenError - token will be invalidated
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...token,
|
...token,
|
||||||
error: "RefreshAccessTokenError",
|
error: "RefreshAccessTokenError",
|
||||||
@@ -73,15 +75,15 @@ export const {
|
|||||||
if (!credentials?.username || !credentials?.password) return null;
|
if (!credentials?.username || !credentials?.password) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 1. Sanitize payload (Only send username and password)
|
// ✅ sanitize payload
|
||||||
const payload = {
|
const payload = {
|
||||||
username: credentials.username as string,
|
username: credentials.username as string,
|
||||||
password: credentials.password as string,
|
password: credentials.password as string,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(`[AUTH] Attempting login at: ${baseUrl}/auth/login`);
|
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] 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] NEXT_PUBLIC_API_URL: ${process.env.NEXT_PUBLIC_API_URL}`);
|
||||||
|
|
||||||
const res = await fetch(`${baseUrl}/auth/login`, {
|
const res = await fetch(`${baseUrl}/auth/login`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -89,7 +91,7 @@ export const {
|
|||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
cache: 'no-store', // Disable caching for auth requests
|
cache: "no-store",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@@ -99,16 +101,21 @@ export const {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await res.json();
|
const responseJson = await res.json();
|
||||||
// Handling both { data: { ... } } and direct { ... } response formats
|
console.log("[AUTH] Backend raw response:", JSON.stringify(responseJson));
|
||||||
const backendData = data.data || data;
|
|
||||||
|
const backendData = responseJson.data || responseJson;
|
||||||
|
|
||||||
if (!backendData || !backendData.access_token) {
|
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;
|
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 {
|
return {
|
||||||
id: backendData.user.user_id.toString(),
|
id: backendData.user.user_id.toString(),
|
||||||
@@ -120,9 +127,8 @@ export const {
|
|||||||
accessToken: backendData.access_token,
|
accessToken: backendData.access_token,
|
||||||
refreshToken: backendData.refresh_token,
|
refreshToken: backendData.refresh_token,
|
||||||
} as User;
|
} as User;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[AUTH] Network/Fetch Error during authorize:", error);
|
console.error("[AUTH] Network Error:", error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -138,7 +144,7 @@ export const {
|
|||||||
return {
|
return {
|
||||||
...token,
|
...token,
|
||||||
id: user.id,
|
id: user.id,
|
||||||
username: user.username, // ✅ Save username
|
username: user.username,
|
||||||
role: user.role,
|
role: user.role,
|
||||||
organizationId: user.organizationId,
|
organizationId: user.organizationId,
|
||||||
accessToken: user.accessToken,
|
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) {
|
if (Date.now() < (token.accessTokenExpires as number) - 10000) {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If existing token has an error, do not retry refresh (prevents infinite loop)
|
|
||||||
if (token.error) {
|
if (token.error) {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Token expired, refresh it
|
|
||||||
return refreshAccessToken(token);
|
return refreshAccessToken(token);
|
||||||
},
|
},
|
||||||
async session({ session, token }) {
|
async session({ session, token }) {
|
||||||
if (token && session.user) {
|
if (token && session.user) {
|
||||||
session.user.id = token.id as string;
|
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.role = token.role as string;
|
||||||
session.user.organizationId = token.organizationId as number;
|
session.user.organizationId = token.organizationId as number;
|
||||||
|
|
||||||
@@ -176,7 +179,7 @@ export const {
|
|||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
strategy: "jwt",
|
strategy: "jwt",
|
||||||
maxAge: 24 * 60 * 60, // 24 hours
|
maxAge: 24 * 60 * 60,
|
||||||
},
|
},
|
||||||
secret: process.env.AUTH_SECRET,
|
secret: process.env.AUTH_SECRET,
|
||||||
debug: process.env.NODE_ENV === "development",
|
debug: process.env.NODE_ENV === "development",
|
||||||
|
|||||||
Reference in New Issue
Block a user