This guide details the logic for implementing a secure, session-based user login system using Node.js, Mongoose and Bcrypt.
📝 Step-by-Step Implementation:
1. Database Lookup
When a user submits their credentials, the system queries MongoDB to locate the user profile.
-
Method:
findOne({ username })via Mongoose. - Security Rule: If the username does not exist, halt execution immediately. Return a 401 Unauthorized status.
2. Password Verification
If the user account exists, the system compares the plain-text input password against the hashed password stored in the database.
-
Method:
await bcrypt.compare(password, user.password). -
Security Rule: If the comparison returns
false, halt execution. Return a 401 Unauthorized status.
3. Session Management
Once both checks pass, the system initializes a secure session to keep the user authenticated across subsequent requests.
-
State Flags:
req.session.isLoggedIn = truereq.session.userId = user._id
- Response: Return a 200 OK status with a success message.
🔒 Security Best Practices Implemented:
-
Generic Error Messages: Both missing usernames and incorrect passwords return the exact same message:
"Invalid username or password". This prevents attackers from brute-forcing and enumerating valid usernames. - Cryptographic Hashing: Passwords are never stored or compared in plain text. Bcrypt handles salt generation automatically to protect against rainbow table attacks.
- Stateful Sessions: Using server-side sessions keeps user identity secure and reduces the risk of token theft common in purely client-side storage.
💻 Quick Code Example:
app.post('/login', async (req, res) => {
const { username, password } = req.body;
try {
// 1. Check if the user exists
const user = await User.findOne({ username });
if (!user) {
return res.status(401).json({ message: "Invalid username or password" });
}
// 2. Verify the password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(401).json({ message: "Invalid username or password" });
}
// 3. Establish session data
req.session.isLoggedIn = true;
req.session.userId = user._id;
return res.status(200).json({ message: "Congrats! You are logged in!" });
} catch (error) {
return res.status(500).json({ message: "Internal server error" });
}
});
If you found this guide helpful, please consider giving it a like!
Thanks for reading!
Top comments (0)