Exponential backoff using redis. Designed specifically for passwords.
var backoff = require('redis-backoff')({
client: require('then-redis').createClient('tcp://localhost')
});
app.use(function* (next) {
var credentials = yield parse(this);
var username = credentials.username;
// keys to limit against
var keys = [
username, // limit by the username
this.ip, // limit by the ip
];
// tell the client it needs to wait
var retryAfter = yield backoff.check(keys);
if (retryAFter) {
this.status = 403;
this.response.set('Retry-After', Math.ceil(retryAfter / 1000));
return;
}
var password = credentials.password;
var user = yield User.getByUsername(username);
var valid = yield User.checkPassword(user, password);
if (!valid) {
// give a bad response and push and remember this bad try
yield backoff.push(keys);
this.status = 400;
return;
}
// if the password is valid, clear the retries
yield backoff.clear(keys)
this.status = 200; // log the user in or something
})
client
- athen-redis
clientbackoff
- a custom backoff function of the form#retries -> millisecond timeout
.
Checks all the keys whether to backoff. Returns the time to wait in milliseconds.
Add a bad try to all the keys. The lock period starts from the current time.
Clear all retries from the keys.