unify totp check

the totp check is done in several places causing errors like 3552232e99

* ldap (addon)
* accesscontrol (dashboard)
* proxyauth
* directoryserver (exposed ldap)
* externalldap (the connector)

The code also makes externalldap auto-create work now across all the cases where there is a username
This commit is contained in:
Girish Ramakrishnan
2023-03-12 15:09:20 +01:00
parent 8e0d1b61af
commit 53e9eccf72
11 changed files with 103 additions and 147 deletions

View File

@@ -12,10 +12,8 @@ const apps = require('../apps.js'),
tokens = require('../tokens.js'),
assert = require('assert'),
BoxError = require('../boxerror.js'),
externalLdap = require('../externalldap.js'),
HttpError = require('connect-lastmile').HttpError,
safe = require('safetydance'),
speakeasy = require('speakeasy'),
users = require('../users.js');
async function passwordAuth(req, res, next) {
@@ -29,29 +27,12 @@ async function passwordAuth(req, res, next) {
const verifyFunc = username.indexOf('@') === -1 ? users.verifyWithUsername : users.verifyWithEmail;
let [error, user] = await safe(verifyFunc(username, password, users.AP_WEBADMIN));
if (error && error.reason === BoxError.NOT_FOUND) {
[error, user] = await safe(externalLdap.maybeCreateUser(username.toLowerCase()));
if (error) return next(new HttpError(401, 'Unauthorized'));
[error] = await safe(externalLdap.verifyPassword(user, password));
if (error) return next(new HttpError(401, 'Unauthorized'));
}
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new HttpError(401, 'Unauthorized'));
let [error, user] = await safe(verifyFunc(username, password, users.AP_WEBADMIN, { totpToken }));
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new HttpError(401, error.message));
if (error && error.reason === BoxError.NOT_FOUND) return next(new HttpError(401, 'Unauthorized'));
if (error) return next(new HttpError(500, error));
if (!user) return next(new HttpError(401, 'Unauthorized'));
if (!user.ghost && !user.appPassword && user.twoFactorAuthenticationEnabled) {
if (!totpToken) return next(new HttpError(401, 'A totpToken must be provided'));
if (user.source === 'ldap') {
const [error] = await safe(externalLdap.verifyPasswordAndTotpToken(user, password, totpToken));
if (error) return next(new HttpError(401, 'Invalid totpToken'));
} else {
const verified = speakeasy.totp.verify({ secret: user.twoFactorAuthenticationSecret, encoding: 'base32', token: totpToken, window: 2 });
if (!verified) return next(new HttpError(401, 'Invalid totpToken'));
}
}
req.user = user;
next();