You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

59 lines
1.4 KiB
JavaScript

const {RateLimiterPostgres, RateLimiterUnion} = require('rate-limiter-flexible');
const pg = require('../../db/pg')
const globalOptions = {
storeClient: pg,
tableName: 'sos.rate_limits',
tableCreated: true
}
function createRateLimit(maxTimes, duration, prefix) {
return new RateLimiterPostgres({
...globalOptions,
points: maxTimes,
inmemoryBlockOnConsumed: maxTimes,
keyPrefix: prefix,
duration
})
}
module.exports = {};
const loginRateLimits = [
// Once per ten seconds
createRateLimit(1, 10, 'logon1'),
// Ten tries in five minutes
createRateLimit(10, 5 * 60, 'logon2'),
// One hundred in a day
createRateLimit(100, 24 * 60 * 60, 'logon3')
]
const loginRateLimitPool = new RateLimiterUnion(...loginRateLimits)
module.exports.loginRateLimit = async (req, res) => {
try {
await loginRateLimitPool.consume(req.body.email)
return 'next';
} catch (limits) {
const wait = Math.max(...Object.values(limits).map(limit => limit?.msBeforeNext || 1));
res.status(429)
res.set({
'Retry-After': Math.ceil(wait / 1000)
})
res.json({errors: [{
param: 'email',
msg: `Too many password attempts, please wait ${Math.ceil(wait / 1000)} seconds`
},{
param: 'password',
msg: ' '
}]})
}
}
module.exports.loginRateLimit.reset = email => Promise.all(
loginRateLimits.map(rateLimit =>
rateLimit.delete(email)
)
)