I'm trying to incorporate rate limiting into my site to prevent brute force but also prevent accounts from being locked by random users. I read this article to see the basics of how it works but the code is not working for me. I've looked through the documentation but I can't find anything mentioning the error I am getting and I can't find it anywhere else.
import { createClient } from 'redis';
import { RateLimiterRedis } from 'rate-limiter-flexible';
const maxWrongAttemptsByIPperMinute = 6;
const maxWrongAttemptsByIPperDay = 100;
const maxConsecutiveFailsByEmailAndIP = 12;
const redisPort = 6379;
const redisClient = createClient({
host: 'redis',
port: redisPort,
enable_offline_queue: false,
});
redisClient.on('error', (err) => console.log('Redis Client Error', err));
// Limit attempts by ip throughout the day
export const limiterSlowBruteByIP = new RateLimiterRedis({
redis: redisClient,
keyPrefix: 'login_fail_ip_per_day',
points: maxWrongAttemptsByIPperDay,
duration: 60 * 60 * 24,
blockDuration: 60 * 60 * 24 // Block for 1 day on 100 failed attempts per day
});
// Limit attempts by ip on a minute basis
export const limiterFastBruteByIP = new RateLimiterRedis({
redis: redisClient,
keyPrefix: 'login_fail_ip_per_minute',
points: maxWrongAttemptsByIPperMinute,
duration: 30,
blockDuration: 60 * 5, // Block ip for 5 minutes if 6 wrong attempts within 30 seconds
});
// Limit attempts by username and ip combo within 90 days
export const limiterConsecutiveFailsByEmailAndIP = new RateLimiterRedis({
redis: redisClient,
keyPrefix: 'login_fail_consecustive_username_and_ip',
points: maxConsecutiveFailsByEmailAndIP,
duration: 60 * 60 * 24 * 90, // Store number for 90 days since first fail
blockDuration: 60 * 60 * 24 * 365 // Block forever after max consecustive fails
});
// Get email and ip combination
export const getEmailIPkey = (email, ip) => `${email}_${ip}`;
export const loginRateLimitChecker = async (req, res, next) => {
const ipAddr = req.connection.remoteAddress;
const emailIPkey = getEmailIPkey(req.body.email, ipAddr);
const test = await limiterConsecutiveFailsByEmailAndIP.get(emailIPkey);
console.log('here');
I've only included the code up to where the error occurs because the rest is irrelevant for now. The error I am getting is from the .get() and the console.log is not being reached.
.pttl(rlKey)
^
TypeError: this.client.multi(...).get(...).pttl is not a function