diff --git a/src/routes/accesscontrol.js b/src/routes/accesscontrol.js index 1b8247198..1ba605eca 100644 --- a/src/routes/accesscontrol.js +++ b/src/routes/accesscontrol.js @@ -13,7 +13,8 @@ var accesscontrol = require('../accesscontrol.js'), BoxError = require('../boxerror.js'), externalLdap = require('../externalldap.js'), HttpError = require('connect-lastmile').HttpError, - users = require('../users.js'); + users = require('../users.js'), + speakeasy = require('speakeasy'); function passwordAuth(req, res, next) { assert.strictEqual(typeof req.body, 'object'); @@ -24,7 +25,21 @@ function passwordAuth(req, res, next) { const username = req.body.username; const password = req.body.password; - // TODO we should only do this for dashboard logins + function check2FA(user) { + assert.strictEqual(typeof user, 'object'); + + if (!user.ghost && !user.appPassword && user.twoFactorAuthenticationEnabled) { + if (!req.body.totpToken) return next(new HttpError(401, 'A totpToken must be provided')); + + let verified = speakeasy.totp.verify({ secret: user.twoFactorAuthenticationSecret, encoding: 'base32', token: req.body.totpToken, window: 2 }); + if (!verified) return next(new HttpError(401, 'Invalid totpToken')); + } + + req.user = user; + + next(); + } + function createAndVerifyUserIfNotExist(identifier, password) { assert.strictEqual(typeof identifier, 'string'); assert.strictEqual(typeof password, 'string'); @@ -37,9 +52,7 @@ function passwordAuth(req, res, next) { if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new HttpError(401, 'Unauthorized')); if (error) return next(new HttpError(500, error)); - req.user = result; - - next(); + check2FA(result); }); } @@ -50,9 +63,7 @@ function passwordAuth(req, res, next) { if (error) return next(new HttpError(500, error)); if (!result) return next(new HttpError(401, 'Unauthorized')); - req.user = result; - - next(); + check2FA(result); }); } else { users.verifyWithEmail(username, password, users.AP_WEBADMIN, function (error, result) { @@ -61,9 +72,7 @@ function passwordAuth(req, res, next) { if (error) return next(new HttpError(500, error)); if (!result) return next(new HttpError(401, 'Unauthorized')); - req.user = result; - - next(); + check2FA(result); }); } } diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index 8273a9473..97383541a 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -34,7 +34,6 @@ let assert = require('assert'), externalLdap = require('../externalldap.js'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess, - speakeasy = require('speakeasy'), sysinfo = require('../sysinfo.js'), system = require('../system.js'), tokendb = require('../tokendb.js'), @@ -47,13 +46,6 @@ function login(req, res, next) { var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - if (!req.user.ghost && !req.user.appPassword && req.user.twoFactorAuthenticationEnabled) { - if (!req.body.totpToken) return next(new HttpError(401, 'A totpToken must be provided')); - - let verified = speakeasy.totp.verify({ secret: req.user.twoFactorAuthenticationSecret, encoding: 'base32', token: req.body.totpToken, window: 2 }); - if (!verified) return next(new HttpError(401, 'Invalid totpToken')); - } - const auditSource = { authType: 'cli', ip: ip }; clients.issueDeveloperToken(req.user, auditSource, function (error, result) { if (error) return next(new HttpError(500, error)); diff --git a/src/routes/developer.js b/src/routes/developer.js index 7acf4f619..f1ce8b517 100644 --- a/src/routes/developer.js +++ b/src/routes/developer.js @@ -7,21 +7,13 @@ exports = module.exports = { let assert = require('assert'), clients = require('../clients.js'), HttpError = require('connect-lastmile').HttpError, - HttpSuccess = require('connect-lastmile').HttpSuccess, - speakeasy = require('speakeasy'); + HttpSuccess = require('connect-lastmile').HttpSuccess; function login(req, res, next) { assert.strictEqual(typeof req.user, 'object'); var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - if (!req.user.ghost && !req.user.appPassword && req.user.twoFactorAuthenticationEnabled) { - if (!req.body.totpToken) return next(new HttpError(401, 'A totpToken must be provided')); - - let verified = speakeasy.totp.verify({ secret: req.user.twoFactorAuthenticationSecret, encoding: 'base32', token: req.body.totpToken, window: 2 }); - if (!verified) return next(new HttpError(401, 'Invalid totpToken')); - } - const auditSource = { authType: 'cli', ip: ip }; clients.issueDeveloperToken(req.user, auditSource, function (error, result) { if (error) return next(new HttpError(500, error));