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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs