Secure auth flow with password verification via bcrypt.compare, JWT issuance for sessions, cookie-based storage, and logout that clears the token. Routes are protected with middleware that validates JWTs.
httpOnly)POST /login – validate credentials, issue JWT, set cookieGET /logout – clear auth cookie, redirect to loginGET /dashboard – protected; requires valid JWTapp.post("/login", async (req, res) => {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user || !(await bcrypt.compare(password, user.password))) {
return res.status(401).send("Invalid credentials");
}
const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, {
expiresIn: "1h",
});
res.cookie("token", token, { httpOnly: true, sameSite: "lax" });
res.redirect("/dashboard");
});
app.get("/logout", (req, res) => {
res.clearCookie("token");
res.redirect("/login");
});
const authenticate = (req, res, next) => {
const token = req.cookies.token;
if (!token) return res.status(401).send("Access denied");
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) return res.status(401).send("Invalid token");
req.user = decoded;
next();
});
};
app.get("/dashboard", authenticate, (req, res) => {
res.render("dashboard", { user: req.user });
});
bcrypt.comparehttpOnly cookie storage