Created
July 22, 2021 17:57
-
-
Save PraneshASP/b92a68d9fd79b9666919c1fe90633288 to your computer and use it in GitHub Desktop.
Basic rate limiter - In-memory implementation of NodeJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 == "[email protected]" && 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