Preventing Brute Force Using Node and Express JS

brute force attack express
node js brute force prevention
express brute alternative
node js ratelimit
throttling in node js
express js best practices
node js limit number of requests
rate-limiter-flexible

I'm building a website using Node and Express JS and would like to throttle invalid login attempts. Both to prevent online cracking and to reduce unnecessary database calls. What are some ways in which I can implement this?

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 up
var MINS10 = 600000, MINS30 = 3 * MINS10;
setInterval(function() {
    for (var ip in failures) {
        if (Date.now() - failures[ip].nextTry > MINS10) {
            delete failures[ip];
        }
    }
}, MINS30);

Brute-force protection Node.js examples - Roman Voloboev, Maybe something like this might help you get started. var failures = {}; function tryToLogin() { var f = failures[remoteIp]; if (f && Date.now() < f.nextTry) { // Throttled​. There are several packages on NPM that are dedicated to this, if you are using the Express framework: express-rate-limiter; express-limiter; express-brute; These can be used for limiting by ip, but also by other information (e.g. by username for failed login attempts).

So after doing some searching, I wasn't able to find a solution I liked so I wrote my own based on Trevor's solution and express-brute. You can find it here.

bruteforce, points from the first part. Number of allowed failed attempts should be chosen depending on requirements and nature of an application. Block source of requests  Preventing Brute Force Attacks One of the most efficient way to help you to deal with brute force attacks, is to set limit to login attempts, or anything related to authentication that requires users to insert their passwords, special codes or PINs. Next up, and again, if you are using ExpressJS, you could implement express-rate-limit dependency.

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) => {
  const loggedIn = loginUser();
  if (!loggedIn) {
      // Consume 1 point for each failed login attempt
      rateLimiter.consume(req.connection.remoteAddress)
        .then((data) => {
          // Message to user
          res.status(400).send(data.remainingPoints + ' attempts left');
        })
        .catch((rejRes) => {
          // Blocked
          const secBeforeNext = Math.ceil(rejRes.msBeforeNext / 1000) || 1;
          res.set('Retry-After', String(secBeforeNext));
          res.status(429).send('Too Many Requests');
        });
  } else {
    // successful login
  }
});

How to make your NodeJS application or API secure, A brute-force protection middleware for express routes that rate limits incoming requests Rate limiting for hapi/hapi.js to prevent brute-force attacks  We can embed CAPTCHA in forms that can completely prevent bots from making brute force attacks and slow down brute force attacks made by humans. There is a middleware program for Express servers called express-brute that limits the rate of incoming requests based on several factors.

okk,i found the solution of max login attemp on wrong password in mongoose and expressjs.there is a solution. *first we will define the user schema *second we will define the max login on wrongpassword handler function. *third when we will create the login api then we will check this function that how many times user login with wrong password.so be ready for code

var config = require('../config');


var userSchema = new mongoose.Schema({
    email: { type: String, unique: true, required: true },
    password: String,
    verificationToken: { type: String, unique: true, required: true },
    isVerified: { type: Boolean, required: true, default: false },
    passwordResetToken: { type: String, unique: true },
    passwordResetExpires: Date,
    loginAttempts: { type: Number, required: true, default: 0 },
    lockUntil: Number,
    role: String
});

userSchema.virtual('isLocked').get(function() {
    return !!(this.lockUntil && this.lockUntil > Date.now());
});
userSchema.methods.incrementLoginAttempts = function(callback) {
    console.log("lock until",this.lockUntil)
    // if we have a previous lock that has expired, restart at 1
    var lockExpired = !!(this.lockUntil && this.lockUntil < Date.now());
console.log("lockExpired",lockExpired)
    if (lockExpired) {
        return this.update({
            $set: { loginAttempts: 1 },
            $unset: { lockUntil: 1 }
        }, callback);
    }
// otherwise we're incrementing
    var updates = { $inc: { loginAttempts: 1 } };
         // lock the account if we've reached max attempts and it's not locked already
    var needToLock = !!(this.loginAttempts + 1 >= config.login.maxAttempts && !this.isLocked);
console.log("needToLock",needToLock)
console.log("loginAttempts",this.loginAttempts)
    if (needToLock) {
        updates.$set = { lockUntil: Date.now() + config.login.lockoutHours };
        console.log("config.login.lockoutHours",Date.now() + config.login.lockoutHours)
    }
//console.log("lockUntil",this.lockUntil)
    return this.update(updates, callback);
};

here is my login function where we have checked the max login attempt on wrong password.so we will call this function

User.findOne({ email: email }, function(err, user) {
        console.log("i am aurhebengdfhdbndbcxnvndcvb")
        if (!user) {
            return done(null, false, { msg: 'No user with the email ' + email + ' was found.' });
        }

        if (user.isLocked) {
            return user.incrementLoginAttempts(function(err) {
                if (err) {
                    return done(err);
                }

                return done(null, false, { msg: 'You have exceeded the maximum number of login attempts.  Your account is locked until ' + moment(user.lockUntil).tz(config.server.timezone).format('LT z') + '.  You may attempt to log in again after that time.' });
            });
        }

        if (!user.isVerified) {
            return done(null, false, { msg: 'Your email has not been verified.  Check your inbox for a verification email.<p><a href="/user/verify-resend/' + email + '" class="btn waves-effect white black-text"><i class="material-icons left">email</i>Re-send verification email</a></p>' });
        }

        user.comparePassword(password, function(err, isMatch) {
            if (isMatch) {
                return done(null, user);
            }
            else {
                user.incrementLoginAttempts(function(err) {
                    if (err) {
                        return done(err);
                    }

                    return done(null, false, { msg: 'Invalid password.  Please try again.' });
                });
            }
        });
    });
}));

Security Best Practices for Express in Production, How to make your NodeJS application or API secure Brute force attack is a method used to obtain sensitive data such as user password or personal How to prevent these attacks from happening in your own project? Right  Prior to that, you need to make sure that session middleware for cookies is configured as described earlier in this article. To install this Node.js module, run the command: npm install csurf 6. Protect your system against brute force. A brute force attack is the simplest and most common way to get access to a website or a server.

Have a look on this: https://github.com/AdamPflug/express-brute A brute-force protection middleware for express routes that rate-limits incoming requests, increasing the delay with each request in a fibonacci-like sequence.

Node.js – Protection from Brute Force and DDOS Attacks , Also ensure you are not using any of the vulnerable Express versions listed on npm install --save helmet Prevent brute-force attacks against authorization. A brute-force protection middleware for express routes that rate-limits incoming requests, increasing the delay with each request in a fibonacci-like sequence.

Preventing Brute Force Using Node and Express JS, Node.js – Protection from Brute Force and DDOS Attacks can use the express-​rate-limit middleware to protect Your solution from Brute Force and DDOS Attacks​. This middleware prevents website, public REST API, and/or endpoints such as  Deploy rate-limit to prevent brute-force attacks against authentication. One way to do this is to use StrongLoop API Gateway to enforce a rate-limiting policy or middleware such as express-limiter. Use csurf middleware to CSRF Protection.

Limit login attempts · Issue #186 · goldbergyoni/nodebestpractices , I'm building a website using Node and Express JS and would like to throttle invalid login attempts. Both to prevent online cracking and to reduce unnecessary​  Security best practices for Express applications in production include: Don’t use deprecated or vulnerable versions of Express. Use TLS. Use Helmet. Use cookies securely. Prevent brute-force attacks against authorization. Ensure your dependencies are secure. Avoid other known vulnerabilities.

Node.js rate-limiter-flexible. Brute-force protection, lirantal @js-kyle @BrunoScheufler Should we add this (login The express-​brute supports redis, couldn't see support for out-of-process cache on the later require('rate-limit-redis'); //Prevent Brute Forcing with Rate Limiting  Node.js rate limiter by key and protection from DDoS and Brute-Force attacks in process Memory, Redis, MongoDb, Memcached, MySQL, PostgreSQL, Cluster or PM Keywords authorization

Comments
  • This will slowly fill up your RAM since the failed IPs are never deleted from failures if a login never actually succeeds.
  • @josh3736 Good point. Added a function to clean it up every 30 minutes.
  • What do you think of solutions such as express-brute? npmjs.org/package/express-brute
  • I actually like your solution a lot more!
  • The problem with @TrevorDixon solution is the cleanup function is blocking code. Let's say failures object has 2000 entries you have a for loop blocking it until all 2000 entries are processed. Use each with callback to make it non blocking.
  • my config.js file is here
  • ohhh this is smart