Preventing Brute Force Using Node and Express JS
Maybe something like this might help you get started.
var failures = {};function tryToLogin() { var f = failures[remoteIp]; if (f && Date.now() < f.nextTry) { // Throttled. Can't try yet. return res.error(); } // Otherwise do login ...}function onLoginFail() { var f = failures[remoteIp] = failures[remoteIp] || {count: 0, nextTry: new Date()}; ++f.count; f.nextTry.setTime(Date.now() + 2000 * f.count); // Wait another two seconds for every failed attempt}function onLoginSuccess() { delete failures[remoteIp]; }// Clean up people that have given upvar MINS10 = 600000, MINS30 = 3 * MINS10;setInterval(function() { for (var ip in failures) { if (Date.now() - failures[ip].nextTry > MINS10) { delete failures[ip]; } }}, MINS30);
rate-limiter-flexible package with Redis or Mongo for distributed apps and in-Memory or with Cluster helps
Here is example with Redis
const { RateLimiterRedis } = require('rate-limiter-flexible');const Redis = require('ioredis');const redisClient = new Redis({ options: { enableOfflineQueue: false }});const opts = { redis: redisClient, points: 5, // 5 points duration: 15 * 60, // Per 15 minutes blockDuration: 15 * 60, // block for 15 minutes if more than points consumed };const rateLimiter = new RateLimiterRedis(opts);app.post('/auth', (req, res, next) => { // Consume 1 point for each login attempt rateLimiter.consume(req.connection.remoteAddress) .then((data) => { const loggedIn = loginUser(); if (!loggedIn) { // Message to user res.status(400).send(data.remainingPoints + ' attempts left'); } else { // successful login } }) .catch((rejRes) => { // Blocked const secBeforeNext = Math.ceil(rejRes.msBeforeNext / 1000) || 1; res.set('Retry-After', String(secBeforeNext)); res.status(429).send('Too Many Requests'); });});