Skip to content

Commit ec62e29

Browse files
committed
fix: use custom handler for totp processing to introduce delay and handle parallel requests for security purposes
1 parent a5c7d86 commit ec62e29

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

lib/controllers.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ const validator = require.main.require('validator');
99
const async = require('async');
1010
const fs = require('fs');
1111
const path = require('path');
12+
const util = require('util');
1213
const base64url = require('base64url');
1314

15+
const db = require.main.require('./src/database');
1416
const groups = require.main.require('./src/groups');
1517
const user = require.main.require('./src/user');
1618
const meta = require.main.require('./src/meta');
1719
const helpers = require.main.require('./src/controllers/helpers');
1820

21+
const wait = util.promisify(setTimeout);
1922
const guard = (path) => {
2023
let url = new URL(path, nconf.get('url'));
2124
url = url.hostname === nconf.get('url_parsed').hostname ? url : nconf.get('url');
@@ -131,11 +134,24 @@ Controllers.renderAuthnChallenge = async (req, res, next) => {
131134
});
132135
};
133136

134-
Controllers.processTotpLogin = function (req, res, next) {
135-
passport.authenticate('totp', {
136-
failureRedirect: `${nconf.get('relative_path')}/login/2fa/totp`,
137-
failureFlash: '[[2factor:login.failure]]',
138-
keepSessionInfo: true,
137+
Controllers.processTotpLogin = async (req, res, next) => {
138+
const count = await db.incrObjectField('locks', `totp:${req.uid}`);
139+
if (count > 1) {
140+
req.flash('error', '[[error:api.429]]');
141+
await wait(10000); // 10s for spamming
142+
return res.redirect(`${nconf.get('relative_path')}/login/2fa/totp`);
143+
}
144+
145+
passport.authenticate('totp', async (err, user, info) => {
146+
if (err || !user) {
147+
req.flash('error', '[[2factor:login.failure]]');
148+
await wait(2000);
149+
await db.deleteObjectField('locks', `totp:${req.uid}`);
150+
return res.redirect(`${nconf.get('relative_path')}/login/2fa/totp`);
151+
}
152+
153+
await db.deleteObjectField('locks', `totp:${req.uid}`);
154+
return next();
139155
})(req, res, next);
140156
};
141157

0 commit comments

Comments
 (0)