
Handling Passwords in Your Web Application
- Arjit Sharma
- 02 Mins
- Development
When building a web app, securing user passwords is crucial. Here are some practical tips to protect them.
1. Hash & Salt Your Passwords 🔑
Never store passwords as plain text! Always hash them using algorithms like bcrypt
or argon2
, which are designed for passwords. Hashing is one-way, meaning the original password can’t be easily retrieved. Before hashing, add a unique salt to each password. This ensures even if two users have the same password, their hashes are different. This blocks attacks using rainbow tables.
const express = require('express');
const bcrypt = require('bcrypt');
const app = express();
const port = 3000;
const SALT_ROUNDS = 10; // Typically a value between 10 and 12
// Middleware to parse JSON bodies
app.use(express.json());
app.post('/register', async (req,res) => {
const { password } = req.body;
// This function will hash the password with the salt
const hashedPassword = await bcrypt.hash(password, SALT_ROUNDS)
// Save the hashed password in your database
res.status(201).json({ hashedPassword: hashedPassword });
})
app.listen(port, ()=>{
console.log(`secure-password-application running on port ${port}`);
})
Note: Salting adds a extra layer of protection. Try sending the same password repeatedly and you will notice the hash of each one is different.
2. Limit Login Attempts 🚫
Stop brute-force attacks by limiting the number of login attempts. After 3-5 failed tries, lock the account or slow down responses.
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 login requests per windowMs
message: 'Too many login attempts, please try again after 15 minutes.'
});
app.post('/login', loginLimiter, (req,res)=>{
res.send('Logged In');
});
3. Secure Password Recovery 🔄
Use a token-based password recovery system. Generate a temporary token, send it via email, and make it expire after 15 minutes.
const crypto = require('crypto');
const nodemailer = require('nodemailer');
app.post('/forgot-password', async (req, res) => {
const token = crypto.randomBytes(32).toString('hex');
// Check in Database
const user = await User.findOne({ email: req.body.email });
if (user) {
user.resetToken = token;
user.resetTokenExpiry = Date.now() + 15 * 60 * 1000; // 15 min expiry
await user.save();
// Send email with token
const transporter = nodemailer.createTransport({
service: 'Gmail',
auth: { user: 'test@gmail.com', pass: 'testpass' }
});
await transporter.sendMail({
from: 'test@gmail.com',
to: user.email,
subject: 'Password Reset',
text: `Reset your password using this token: ${token}`
});
res.json({ message: 'Check your email for the reset token!' });
} else {
res.status(404).json({ message: 'User not found!' });
}
});
5. Use HTTPS 🔒
Passwords should never travel over an insecure connection. Always use HTTPS for pages handling sensitive actions, such as login, registration, or password recovery. This encrypts the data in transit and keeps it safe from man-in-the-middle attacks.
Tip: Implement HSTS (HTTP Strict Transport Security) to ensure browsers always connect via HTTPS
6. Add Two-Factor Authentication (2FA) 🔑
Add an extra security layer by requiring both a password and a one-time code (via SMS, email, or an app). This stops unauthorized access, even if passwords are stolen.
7. Monitor & Audit 👀
Track login activity and unusual patterns. Regular audits help identify weaknesses before attackers do.
8. Use OAuth or SSO 🔗
Consider using trusted third-party authentication methods like OAuth or SSO (Google, Facebook, etc.) instead of handling passwords yourself. This shifts the responsibility of securing passwords to these providers, reducing your liability and improving user convenience.
By following these simple practices, you can significantly improve password security in your web app. Protect your users and your app with these quick wins!