Commit 47ba3ae4 by Johannes Zellner

Consolidate user verification

1 parent 7af3d855
Showing with 193 additions and 145 deletions
......@@ -4,11 +4,6 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"accepts": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
......@@ -74,14 +69,14 @@
"integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
},
"asn1": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.1.tgz",
"integrity": "sha1-7Mc/ddMeo8btnUdCjbNf7Meyxtw="
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
},
"assert-plus": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz",
"integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA="
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"async": {
"version": "1.5.2",
......@@ -103,6 +98,14 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
},
"backoff": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz",
"integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=",
"requires": {
"precond": "0.2"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
......@@ -195,12 +198,14 @@
}
},
"bunyan": {
"version": "0.22.1",
"resolved": "https://registry.npmjs.org/bunyan/-/bunyan-0.22.1.tgz",
"integrity": "sha1-Agw4O+1iWvXGyINN2MSsoN0Pdlw=",
"version": "1.8.12",
"resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz",
"integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
"requires": {
"dtrace-provider": "0.2.8",
"mv": "0.0.5"
"dtrace-provider": "~0.8",
"moment": "^2.10.6",
"mv": "~2",
"safe-json-stringify": "~1"
}
},
"bytes": {
......@@ -430,10 +435,13 @@
"dev": true
},
"dtrace-provider": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.2.8.tgz",
"integrity": "sha1-4kPxkhmqlfvw2PL/sH9b1k6U/iA=",
"optional": true
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.7.tgz",
"integrity": "sha1-3JObTT4GIM/gwc2APQ0tftBP/QQ=",
"optional": true,
"requires": {
"nan": "^2.10.0"
}
},
"ecc-jsbn": {
"version": "0.1.1",
......@@ -554,9 +562,9 @@
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
},
"extsprintf": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.0.tgz",
"integrity": "sha1-TVi4Fazlvr/E6/A8+YsKdgSpm4Y="
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz",
"integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk="
},
"fast-deep-equal": {
"version": "1.0.0",
......@@ -861,11 +869,6 @@
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"json-schema": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz",
"integrity": "sha1-UDVPGfYDkXxpX3C4Wvp3w7DyNQY="
},
"json-schema-traverse": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
......@@ -876,37 +879,36 @@
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsprim": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-0.3.0.tgz",
"integrity": "sha1-zRNGbqJIDb2DlqVw1H0x3aR2+LE=",
"ldap-filter": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.2.2.tgz",
"integrity": "sha1-8rhCvguG2jNSeYUFsx68rlkNd9A=",
"requires": {
"extsprintf": "1.0.0",
"json-schema": "0.2.2",
"verror": "1.3.3"
"assert-plus": "0.1.5"
},
"dependencies": {
"verror": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.3.3.tgz",
"integrity": "sha1-impKw6jHdLb2h/7OSb3/14VS4s0=",
"requires": {
"extsprintf": "1.0.0"
}
"assert-plus": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz",
"integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA="
}
}
},
"ldapjs": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-0.7.1.tgz",
"integrity": "sha1-aEeYpodkC6sa+9gCz1MvMEkt+1Y=",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.2.tgz",
"integrity": "sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk=",
"requires": {
"asn1": "0.2.1",
"assert-plus": "0.1.5",
"bunyan": "0.22.1",
"dtrace-provider": "0.2.8",
"nopt": "2.1.1",
"pooling": "0.4.6"
"asn1": "0.2.3",
"assert-plus": "^1.0.0",
"backoff": "^2.5.0",
"bunyan": "^1.8.3",
"dashdash": "^1.14.0",
"dtrace-provider": "~0.8",
"ldap-filter": "0.2.2",
"once": "^1.4.0",
"vasync": "^1.6.4",
"verror": "^1.8.1"
}
},
"lru-cache": {
......@@ -1030,6 +1032,12 @@
}
}
},
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==",
"optional": true
},
"morgan": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz",
......@@ -1063,9 +1071,50 @@
}
},
"mv": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/mv/-/mv-0.0.5.tgz",
"integrity": "sha1-FerHWUeYhN8RMdbeVrziC2VPU5E=",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
"integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=",
"optional": true,
"requires": {
"mkdirp": "~0.5.1",
"ncp": "~2.0.0",
"rimraf": "~2.4.0"
},
"dependencies": {
"glob": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
"integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
"optional": true,
"requires": {
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "2 || 3",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"rimraf": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
"optional": true,
"requires": {
"glob": "^6.0.1"
}
}
}
},
"nan": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
"integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==",
"optional": true
},
"ncp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
"optional": true
},
"negotiator": {
......@@ -1073,14 +1122,6 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
},
"nopt": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.1.tgz",
"integrity": "sha1-ket8SwF+fACtytH9bWOUTQ/bdcE=",
"requires": {
"abbrev": "1"
}
},
"oauth-sign": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
......@@ -1140,15 +1181,6 @@
"passport-strategy": "1.x.x"
}
},
"passport-ldapjs": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/passport-ldapjs/-/passport-ldapjs-1.0.3.tgz",
"integrity": "sha512-pWyqehzK5IAtg53S6uIc9PHqgxL3xDcog3XDhtvidNd4+3z8XTGV2qQKPaUZnkkRLmWqZ7Dm3gnwnAtp6R1LNQ==",
"requires": {
"ldapjs": "^0.7.1",
"passport-strategy": "^1.0.0"
}
},
"passport-strategy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
......@@ -1202,24 +1234,10 @@
"pinkie": "^2.0.0"
}
},
"pooling": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/pooling/-/pooling-0.4.6.tgz",
"integrity": "sha1-dqMXNx6oo2O0hY+keZ5gJF8w5mQ=",
"requires": {
"assert-plus": "0.1.5",
"bunyan": "0.22.1",
"dtrace-provider": "0.2.8",
"once": "1.3.0",
"vasync": "1.4.0"
},
"dependencies": {
"once": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.0.tgz",
"integrity": "sha1-FRr4a/wfCMS58H0GqyUP/L61ZYE="
}
}
"precond": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz",
"integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw="
},
"proxy-addr": {
"version": "2.0.2",
......@@ -1357,6 +1375,12 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
},
"safe-json-stringify": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz",
"integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==",
"optional": true
},
"safetydance": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/safetydance/-/safetydance-0.1.1.tgz",
......@@ -1692,20 +1716,31 @@
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"vasync": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/vasync/-/vasync-1.4.0.tgz",
"integrity": "sha1-bqWmNYI1iGjYdDy91v+tyQg7kQ8=",
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz",
"integrity": "sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=",
"requires": {
"verror": "1.6.0"
},
"dependencies": {
"verror": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz",
"integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=",
"requires": {
"jsprim": "0.3.0",
"verror": "1.1.0"
"extsprintf": "1.2.0"
}
}
}
},
"verror": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.1.0.tgz",
"integrity": "sha1-KktOsUogcFHnWm+U7lExW/FzobA=",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"extsprintf": "1.0.0"
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"webdav-server": {
......
......@@ -33,12 +33,12 @@
"del": "^2.2.0",
"express": "^4.16.2",
"express-session": "^1.15.6",
"ldapjs": "^1.0.2",
"mkdirp": "^0.5.1",
"morgan": "^1.9.0",
"multiparty": "^4.1.2",
"passport": "^0.2.2",
"passport-http-bearer": "^1.0.1",
"passport-ldapjs": "^1.0.3",
"readline-sync": "^1.4.9",
"request": "^2.83.0",
"safetydance": "^0.1.1",
......
......@@ -7,13 +7,22 @@ var passport = require('passport'),
bcrypt = require('bcryptjs'),
uuid = require('uuid/v4'),
BearerStrategy = require('passport-http-bearer').Strategy,
LdapStrategy = require('passport-ldapjs').Strategy,
ldapjs = require('ldapjs'),
HttpError = require('connect-lastmile').HttpError,
HttpSuccess = require('connect-lastmile').HttpSuccess,
webdavErrors = require('webdav-server').v2.Errors;
const LDAP_URL = process.env.LDAP_URL;
const LDAP_USERS_BASE_DN = process.env.LDAP_USERS_BASE_DN;
const LOCAL_AUTH_FILE = path.resolve(process.env.LOCAL_AUTH_FILE || './.users.json');
const TOKENSTORE_FILE = path.resolve(process.env.TOKENSTORE_FILE || './.tokens.json');
const AUTH_METHOD = (LDAP_URL && LDAP_USERS_BASE_DN) ? 'ldap' : 'local';
if (AUTH_METHOD === 'ldap') {
console.log('Use ldap auth');
} else {
console.log(`Use local auth file ${LOCAL_AUTH_FILE}`);
}
var tokenStore = {
data: {},
......@@ -68,54 +77,62 @@ passport.deserializeUser(function (id, done) {
done(null, { uid: id });
});
var LDAP_URL = process.env.LDAP_URL;
var LDAP_USERS_BASE_DN = process.env.LDAP_USERS_BASE_DN;
function verifyUser(username, password, callback) {
if (AUTH_METHOD === 'ldap') {
var ldapClient = ldapjs.createClient({ url: process.env.LDAP_URL });
ldapClient.on('error', function (error) {
console.error('LDAP error', error);
});
ldapClient.bind(process.env.LDAP_BIND_DN, process.env.LDAP_BIND_PASSWORD, function (error) {
if (error) return callback(error);
if (LDAP_URL && LDAP_USERS_BASE_DN) {
console.log('Using ldap auth');
var filter = `(|(uid=${username})(mail=${username})(username=${username})(sAMAccountName=${username}))`;
ldapClient.search(process.env.LDAP_USERS_BASE_DN, { filter: filter }, function (error, result) {
if (error) return callback(error);
exports.login = [ passport.authenticate('ldap'), issueAccessToken() ];
} else {
console.log(`Using local user file: ${LOCAL_AUTH_FILE}`);
var items = [];
exports.login = [
function (req, res, next) {
result.on('searchEntry', function(entry) { items.push(entry.object); });
result.on('error', callback);
result.on('end', function (result) {
if (result.status !== 0 || items.length === 0) return callback(error);
// pick the first found
var user = items[0];
ldapClient.bind(user.dn, password, function (error) {
if (error) return callback('Invalid credentials');
callback(null, { username: username });
});
});
});
});
} else {
var users = safe.JSON.parse(safe.fs.readFileSync(LOCAL_AUTH_FILE));
if (!users) return res.send(401);
if (!users[req.body.username]) return res.send(401);
if (!users || !users[username]) return callback('Invalid credentials');
bcrypt.compare(req.body.password, users[req.body.username].passwordHash, function (error, valid) {
if (error || !valid) return res.send(401);
bcrypt.compare(password, users[username].passwordHash, function (error, valid) {
if (error || !valid) return callback('Invalid credentials');
req.user = {
username: req.body.username
};
callback(null, { username: username });
});
}
}
exports.login = [
function (req, res, next) {
verifyUser(req.body.username, req.body.password, function (error, user) {
if (error) return next(new HttpError(401, 'Invalid credentials'));
req.user = user;
next();
});
},
issueAccessToken()
];
}
var opts = {
server: {
url: LDAP_URL,
},
base: LDAP_USERS_BASE_DN,
search: {
filter: '(|(username={{username}})(mail={{username}}))',
attributes: ['displayname', 'username', 'mail', 'uid'],
scope: 'sub'
},
uidTag: 'cn',
usernameField: 'username',
passwordField: 'password',
};
passport.use(new LdapStrategy(opts, function (profile, done) {
done(null, profile);
}));
];
exports.verify = passport.authenticate('bearer', { session: false });
......@@ -162,18 +179,14 @@ WebdavUserManager.prototype.getDefaultUser = function (callback) {
};
WebdavUserManager.prototype.getUserByNamePassword = function (username, password, callback) {
var users = safe.JSON.parse(safe.fs.readFileSync(LOCAL_AUTH_FILE));
if (!users) return callback(webdavErrors.UserNotFound);
if (!users[username]) return callback(webdavErrors.UserNotFound);
bcrypt.compare(password, users[username].passwordHash, function (error, valid) {
if (error || !valid) return callback(webdavErrors.UserNotFound);
verifyUser(username, password, function (error, user) {
if (error) return callback(webdavErrors.UserNotFound);
callback(null, {
username: username,
username: user.username,
isAdministrator: true,
isDefaultUser: false,
uid: username
uid: user.username
});
});
};
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!