Skip to content

Instantly share code, notes, and snippets.

@PraneshASP
Created July 22, 2021 17:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PraneshASP/b92a68d9fd79b9666919c1fe90633288 to your computer and use it in GitHub Desktop.
Save PraneshASP/b92a68d9fd79b9666919c1fe90633288 to your computer and use it in GitHub Desktop.
Basic rate limiter - In-memory implementation of NodeJS
const express = require("express");
const moment = require("moment");
const app = express();
const PORT = process.env.PORT || 5000;
app.use(express.json());
const MAX_ATTEMPTS = 3; // after which the account should be locked
const LOCK_WINDOW = 2; // in minutes
let lock = {
attempts: 0,
isLocked: false,
unlocksAt: null,
};
let locks = {};
app.post("/login", async (req, res) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.json({
error: true,
message: "Please enter email and password to continue",
status: 400,
});
}
if (
locks[email] &&
locks[email].isLocked &&
locks[email].unlocksAt > new Date()
)
return res.status(401).json({
error: true,
message:
"Account locked due to many invalid attempts. You account unlocks " +
moment(locks[email].unlocksAt).fromNow(),
});
// Not recommended ^^
const isValid = email == "test@gmail.com" && password == "complex_password";
//If the login attempt is invalid
if (!isValid) {
locks[email] = lock;
locks[email].attempts += 1;
if (locks[email].attempts >= MAX_ATTEMPTS) {
var d = new Date();
d.setMinutes(d.getMinutes() + LOCK_WINDOW);
locks[email].isLocked = true;
locks[email].unlocksAt = d;
}
return res.status(401).json({
error: true,
message:
"Sorry, please check whether you have entered the correct credentials.",
});
}
delete locks[email];
return res.send("Authentication success");
} catch (err) {
console.error("Login error", err);
return res.status(500).json({
error: true,
message:
"Sorry, couldn't process your request right now. Please try again later.",
});
}
});
// Returns all the locks -for testing purpose
app.get("/locks", async (req, res) => {
try {
return res.send(locks);
} catch (error) {
return res.status(500);
}
});
app.listen(PORT, () => console.log("Server started!"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment