JAVASCRIPT
Implement Login Brute-Force Protection with Rate Limiting
Protect user accounts from brute-force login attacks by implementing server-side rate limiting to block excessive invalid login requests for a given user or IP.
// Install required packages: npm install express express-rate-limit
const express = require('express');
const rateLimit = require('express-rate-limit');
const app = express();
const PORT = 3000;
app.use(express.json()); // For parsing application/json
// --- Login Rate Limiter Configuration ---
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 from this IP, please try again after 15 minutes',
handler: (req, res, next, options) => {
// Optional: Log brute-force attempts
console.warn(`Brute-force attempt detected from IP: ${req.ip} for path: ${req.path}`);
res.status(options.statusCode).send(options.message);
},
// Customize key generator to apply rate limit per user (if logged in) or IP
// For login, usually per IP or username from POST body
keyGenerator: (req, res) => {
// If login endpoint has a username, use it for more granular limiting
// Otherwise, fallback to IP address
return req.body.username || req.ip;
},
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
});
// Apply the login rate limiter specifically to the login route
app.post('/login', loginLimiter, (req, res) => {
const { username, password } = req.body;
// --- Placeholder for actual authentication logic ---
if (username === 'admin' && password === 'securepassword') { // NOT for production!
res.status(200).json({ message: 'Login successful!' });
} else {
// IMPORTANT: Avoid giving specific error messages for security (e.g., 'username not found')
// Generic message helps prevent user enumeration attacks.
res.status(401).json({ message: 'Invalid credentials.' });
}
});
// A general rate limiter for other API routes (optional, but good practice)
const apiLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
max: 100, // Limit each IP to 100 requests per `windowMs`
message: 'Too many requests from this IP, please try again after an hour',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', apiLimiter); // Apply to all routes starting with /api/
// Example protected route
app.get('/api/data', (req, res) => {
res.status(200).json({ data: 'This is protected data.' });
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
How it works: This Node.js snippet uses the `express-rate-limit` middleware to implement brute-force protection on a login endpoint. It limits the number of login attempts an IP address (or a specific username) can make within a defined `windowMs` (e.g., 15 minutes) to a maximum (`max`) number of requests (e.g., 5). If the limit is exceeded, the client receives an error message and must wait. This mechanism significantly hinders automated brute-force attacks, protecting user accounts from unauthorized access. The `keyGenerator` can be customized for more granular limiting per user.