I have a problem in logout in production phase in my Nuxt 3.15 app (MEVN stack)
Normal conditions:
- after successful login, the user is directed to
/dashboardwhere his data is loaded from database - after successful logout, the user is directed to
/auth/login
Problem: when I open the website, I found a logged in user from a previous session. I logout and be directed to /auth/login normally but the user is still logged in (I guess because the httpOnly cookie wasn't remove from the browser) and get the following error:
❌ Error fetching user (sidebar) :
{message: 'Unauthorized'}
message
:
"Unauthorized"
[[Prototype]]
:
Object
_CR8Ct8W.js:967
GET http://localhost:6500/api/auth/me 401 (Unauthorized)
BmvoPlmo.js:1 ❌ Error fetching user (dashboard):
{message: 'Unauthorized'}
message
:
"Unauthorized"
[[Prototype]]
:
Object
related codes:
(1) Back end codes:
server.js
---------
// ✅ Registered routes
app.use("/api/auth", authRoutes);
// ✅ logout endpoint
router.post("/logout", (req, res) => {
res.cookie("token", "", {
httpOnly: true,
secure: process.env.NODE_ENV === "production", // ✅ Secure in production
sameSite: "Strict",
expires: new Date(0), // ✅ Expire immediately
});
res.status(200).json({ message: "Logged out successfully" });
});
// ✅ Fetch logged-in user details
router.get("/me", authMiddleware, async (req, res) => {
try {
let user = await User.findById(req.user.id).select("-password");
if (!user) user = await serviceProvider.findById(req.user.id).select("-password");
if (!user) user = await Admin.findById(req.user.id).select("-password");
if (!user) user = await Moderator.findById(req.user.id).select("-password");
if (!user) return res.status(404).json({ message: "User not found" });
res.json(user);
} catch (error) {
res.status(500).json({ message: "Server error", error });
}
});
// ✅ Middleware to protect routes
const authMiddleware = (req, res, next) => {
const token = req.cookies.token;
if (!token) return res.status(401).json({ message: "Unauthorized" });
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded; // Attach user data to request
next();
} catch (error) {
res.status(401).json({ message: "Invalid Token", error });
}
};
(2) Front end codes:
// Logout function
async logout() {
try {
await axios.post(`${API_BASE_URL}/api/auth/logout`, {}, { // ✅ Correct API URL
withCredentials: true, // ✅ Send cookies
});
localStorage.removeItem("token"); // ✅ Remove from storage
this.user = null;
window.location.href = "/auth/login"; // ✅ Redirect after logout
} catch (error) {
console.error("❌ Error logging out:", error);
}
},
// fetch user data for the dashboard
const fetchUser = async () => {
try {
const response = await axios.get(`${API_BASE_URL}/api/auth/me`, {
withCredentials: true,
});
user.value = response.data || {};
// ✅ Force update authStore to ensure correct data is stored
authStore.setUser(response.data, authStore.token);
await fetchDashboardData(); // ✅ Fetch the correct dashboard data
} catch (err) {
console.error("❌ Error fetching user (dashboard):", err.response?.data || err.message);
user.value = {};
router.push('/auth/login'); // Redirect if not logged in
} finally {
loading.value = false;
}
};
// ✅ Fetch User Data in the sidebar
const fetchUser = async () => {
try {
const response = await axios.get(`${API_BASE_URL}/api/auth/me`, {
withCredentials: true, // ✅ Send cookies
});
user.value = response.data || {};
} catch (err) {
console.error("❌ Error fetching user (sidebar) :", err.response?.data || err.message);
} finally {
loading.value = false;
}
};
I debugged the code and found that the issue is from httpOnly cookie type which can't be removed using JS Although I fixed the logout function, but problem still exists in production
