2025-10-25 11:39:24 +02:00

133 lines
3.7 KiB
TypeScript

import { NextResponse } from "next/server";
import { decodeJwt } from "jose";
const BE_BASE_URL = process.env.BE_BASE_URL || "http://localhost:8583";
const COOKIE_NAME = "auth_token";
export async function POST(request: Request) {
try {
const { email, currentPassword, newPassword } = await request.json();
// Get the auth token from cookies first
const { cookies } = await import("next/headers");
const cookieStore = cookies();
const token = (await cookieStore).get(COOKIE_NAME)?.value;
if (!token) {
return NextResponse.json(
{ success: false, message: "No authentication token found" },
{ status: 401 }
);
}
// Check MustChangePassword flag from current token
let mustChangePassword = false;
try {
const payload = decodeJwt(token);
mustChangePassword = payload.MustChangePassword || false;
console.log(
"🔍 Current JWT MustChangePassword flag:",
mustChangePassword
);
} catch (err) {
console.error("❌ Failed to decode current JWT:", err);
}
// Skip currentPassword validation if MustChangePassword is true
if (!email || !newPassword || (!mustChangePassword && !currentPassword)) {
return NextResponse.json(
{
success: false,
message: "Email, current password, and new password are required",
},
{ status: 400 }
);
}
// 🔁 Call backend API with the correct payload
const requestBody: {
email: string;
new_password: string;
current_password?: string;
} = {
email,
new_password: newPassword,
};
// Only include current_password if MustChangePassword is false
if (!mustChangePassword && currentPassword) {
requestBody.current_password = currentPassword;
}
const resp = await fetch(`${BE_BASE_URL}/api/v1/auth/change-password`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(requestBody),
});
const data = await resp.json();
if (!resp.ok) {
console.log("[DEBUG] [CHANGE-PASSWORD] Error response:", {
status: resp.status,
data,
});
return NextResponse.json(
{ success: false, message: data?.message || "Password change failed" },
{ status: resp.status }
);
}
// ✅ Handle new token from backend
const newToken = data?.token;
const response = NextResponse.json({
success: true,
message: data?.message || "Password changed successfully",
});
if (newToken) {
try {
const payload = decodeJwt(newToken);
console.log("🔍 New JWT payload:", payload);
console.log(
"🔍 must_change_password flag:",
payload.must_change_password
);
} catch (err) {
console.error("❌ Failed to decode new JWT:", err);
}
// Derive maxAge from JWT exp if available; fallback to 12h
let maxAge = 60 * 60 * 12;
try {
const payload = decodeJwt(newToken);
if (payload?.exp) {
const secondsLeft = payload.exp - Math.floor(Date.now() / 1000);
if (secondsLeft > 0) maxAge = secondsLeft;
}
} catch {}
response.cookies.set({
name: COOKIE_NAME,
value: newToken,
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
path: "/",
maxAge,
});
}
return response;
} catch (error) {
console.error("❌ Change password proxy error:", error);
return NextResponse.json(
{ success: false, message: "Internal server error" },
{ status: 500 }
);
}
}