Add support for LDAP cn=...+totptoken=.. support
This commit is contained in:
@@ -23,6 +23,7 @@ const assert = require('assert'),
|
||||
reverseproxy = require('./reverseproxy.js'),
|
||||
safe = require('safetydance'),
|
||||
settings = require('./settings.js'),
|
||||
speakeasy = require('speakeasy'),
|
||||
shell = require('./shell.js'),
|
||||
users = require('./users.js'),
|
||||
util = require('util'),
|
||||
@@ -173,12 +174,13 @@ async function userSearch(req, res, next) {
|
||||
displayname: displayName,
|
||||
givenName: firstName,
|
||||
username: user.username,
|
||||
twoFactorAuthenticationEnabled: user.twoFactorAuthenticationEnabled || undefined,
|
||||
samaccountname: user.username, // to support ActiveDirectory clients
|
||||
// memberof: user.groupIds.map(function (gid) { return `cn=${gid},ou=groups,dc=cloudron`; }) <- use cn=group.name instead of id
|
||||
}
|
||||
};
|
||||
|
||||
if (user.twoFactorAuthenticationEnabled) obj.attributes.twoFactorAuthenticationEnabled = true;
|
||||
|
||||
// http://www.zytrax.com/books/ldap/ape/core-schema.html#sn has 'name' as SUP which is a DirectoryString
|
||||
// which is required to have atleast one character if present
|
||||
if (lastName.length !== 0) obj.attributes.sn = lastName;
|
||||
@@ -235,12 +237,15 @@ async function groupSearch(req, res, next) {
|
||||
// Will attach req.user if successful
|
||||
async function userAuth(req, res, next) {
|
||||
// extract the common name which might have different attribute names
|
||||
const attributeName = Object.keys(req.dn.rdns[0].attrs)[0];
|
||||
const commonName = req.dn.rdns[0].attrs[attributeName].value;
|
||||
const cnAttributeName = Object.keys(req.dn.rdns[0].attrs)[0];
|
||||
const commonName = req.dn.rdns[0].attrs[cnAttributeName].value;
|
||||
if (!commonName) return next(new ldap.NoSuchObjectError(req.dn.toString()));
|
||||
|
||||
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;
|
||||
|
||||
let verifyFunc;
|
||||
if (attributeName === 'mail') {
|
||||
if (cnAttributeName === 'mail') {
|
||||
verifyFunc = users.verifyWithEmail;
|
||||
} else if (commonName.indexOf('@') !== -1) { // if mail is specified, enforce mail check
|
||||
verifyFunc = users.verifyWithEmail;
|
||||
@@ -255,6 +260,12 @@ async function userAuth(req, res, next) {
|
||||
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new ldap.InvalidCredentialsError(req.dn.toString()));
|
||||
if (error) return next(new ldap.OperationsError(error.message));
|
||||
|
||||
// currently this is only optional if totpToken is provided and user has 2fa enabled
|
||||
if (totpToken && user.twoFactorAuthenticationEnabled) {
|
||||
const verified = speakeasy.totp.verify({ secret: user.twoFactorAuthenticationSecret, encoding: 'base32', token: totpToken, window: 2 });
|
||||
if (!verified) return next(new ldap.InvalidCredentialsError(req.dn.toString()));
|
||||
}
|
||||
|
||||
req.user = user;
|
||||
|
||||
next();
|
||||
|
||||
Reference in New Issue
Block a user