directoryserver: leave it to client to decide totp check

initially, the idea was to make the server enforce it. this is more secure. however,
we have 3 kinds of clients - an external cloudron dashboard which needs totp,
an external cloudron app, which doesn't have totp and external apps that don't have totp either.

given that the directory server is IP restricted, this is a reasonable compromise until
we move wholesale to oidc.

a directoryserver setting like "enforce totp" also does not work since this policy will be
applied to all clients.
This commit is contained in:
Girish Ramakrishnan
2024-01-07 20:38:36 +01:00
parent 7bb68ea6b5
commit 4ddcd547ba
2 changed files with 12 additions and 4 deletions

View File

@@ -300,8 +300,12 @@ async function userAuth(req, res, next) {
const commonName = req.dn.rdns[0].attrs[cnAttributeName].value;
if (!commonName) return next(new ldap.NoSuchObjectError('Missing CN'));
// totptoken is passed as the "attribute" using the '+' separator in the first RDNS of the request DN
// when totptoken attribute is present, it signals that we must enforce totp check
// totp check is currently requested by the client. this is the only way to auth against external cloudron dashboard, external cloudron app and external apps
const TOTPTOKEN_ATTRIBUTE_NAME = 'totptoken'; // This has to be in-sync with externalldap.js
const totpToken = req.dn.rdns[0].attrs[TOTPTOKEN_ATTRIBUTE_NAME] ? req.dn.rdns[0].attrs[TOTPTOKEN_ATTRIBUTE_NAME].value : null;
const totpToken = TOTPTOKEN_ATTRIBUTE_NAME in req.dn.rdns[0].attrs ? req.dn.rdns[0].attrs[TOTPTOKEN_ATTRIBUTE_NAME].value : null;
const relaxedTotpCheck = !(TOTPTOKEN_ATTRIBUTE_NAME in req.dn.rdns[0].attrs);
let verifyFunc;
if (cnAttributeName === 'mail') {
@@ -314,7 +318,7 @@ async function userAuth(req, res, next) {
verifyFunc = users.verifyWithUsername;
}
const [error, user] = await safe(verifyFunc(commonName, req.credentials || '', '', { totpToken }));
const [error, user] = await safe(verifyFunc(commonName, req.credentials || '', '', { totpToken, relaxedTotpCheck }));
if (error && error.reason === BoxError.NOT_FOUND) return next(new ldap.NoSuchObjectError(error.message));
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(error.message));
if (error) return next(new ldap.OperationsError(error.message));