WIP on OTP 2FA, stats, etc.

This commit is contained in:
Bryan Ashby 2019-05-07 21:36:33 -06:00
parent e960e2800d
commit e5398db07b
No known key found for this signature in database
GPG Key ID: B49EB437951D2542
2 changed files with 59 additions and 45 deletions

View File

@ -51,4 +51,5 @@ exports.ErrorReasons = {
Inactive : 'INACTIVE', Inactive : 'INACTIVE',
Locked : 'LOCKED', Locked : 'LOCKED',
NotAllowed : 'NOTALLOWED', NotAllowed : 'NOTALLOWED',
Invalid2FA : 'INVALID2FA',
}; };

View File

@ -22,6 +22,8 @@ const async = require('async');
const _ = require('lodash'); const _ = require('lodash');
exports.userLogin = userLogin; exports.userLogin = userLogin;
exports.recordLogin = recordLogin;
exports.transformLoginError = transformLoginError;
function userLogin(client, username, password, options, cb) { function userLogin(client, username, password, options, cb) {
if(!cb && _.isFunction(options)) { if(!cb && _.isFunction(options)) {
@ -50,20 +52,13 @@ function userLogin(client, username, password, options, cb) {
client.user.authenticateFactor1(authInfo, err => { client.user.authenticateFactor1(authInfo, err => {
if(err) { if(err) {
client.user.sessionFailedLoginAttempts = _.get(client.user, 'sessionFailedLoginAttempts', 0) + 1; return cb(transformLoginError(err, client, username));
const disconnect = config.users.failedLogin.disconnect;
if(disconnect > 0 && client.user.sessionFailedLoginAttempts >= disconnect) {
err = Errors.BadLogin('To many failed login attempts', ErrorReasons.TooMany);
}
client.log.info( { username, ip : client.remoteAddress, reason : err.message }, 'Failed login attempt');
return cb(err);
} }
const user = client.user; const user = client.user;
// Good login; reset any failed attempts // Good login; reset any failed attempts
delete user.sessionFailedLoginAttempts; delete client.sessionFailedLoginAttempts;
// //
// Ensure this user is not already logged in. // Ensure this user is not already logged in.
@ -104,23 +99,31 @@ function userLogin(client, username, password, options, cb) {
Events.emit(Events.getSystemEvents().UserLogin, { user } ); Events.emit(Events.getSystemEvents().UserLogin, { user } );
setClientTheme(client, user.properties[UserProps.ThemeId]);
if(user.authenticated) {
return recordLogin(client, cb);
}
// recordLogin() must happen after 2FA!
return cb(null);
});
}
function recordLogin(client, cb) {
const user = client.user;
async.parallel( async.parallel(
[ [
function setTheme(callback) { (callback) => {
setClientTheme(client, user.properties[UserProps.ThemeId]);
return callback(null);
},
function updateSystemLoginCount(callback) {
StatLog.incrementNonPersistentSystemStat(SysProps.LoginsToday, 1); StatLog.incrementNonPersistentSystemStat(SysProps.LoginsToday, 1);
return StatLog.incrementSystemStat(SysProps.LoginCount, 1, callback); return StatLog.incrementSystemStat(SysProps.LoginCount, 1, callback);
}, },
function recordLastLogin(callback) { (callback) => {
return StatLog.setUserStat(user, UserProps.LastLoginTs, StatLog.now, callback); return StatLog.setUserStat(user, UserProps.LastLoginTs, StatLog.now, callback);
}, },
function updateUserLoginCount(callback) { (callback) => {
return StatLog.incrementUserStat(user, UserProps.LoginCount, 1, callback); return StatLog.incrementUserStat(user, UserProps.LoginCount, 1, callback);
}, },
function recordLoginHistory(callback) { (callback) => {
const loginHistoryMax = Config().statLog.systemEvents.loginHistoryMax; const loginHistoryMax = Config().statLog.systemEvents.loginHistoryMax;
const historyItem = JSON.stringify({ const historyItem = JSON.stringify({
userId : user.userId, userId : user.userId,
@ -140,5 +143,15 @@ function userLogin(client, username, password, options, cb) {
return cb(err); return cb(err);
} }
); );
}); }
function transformLoginError(err, client, username) {
client.sessionFailedLoginAttempts = _.get(client, 'sessionFailedLoginAttempts', 0) + 1;
const disconnect = Config().users.failedLogin.disconnect;
if(disconnect > 0 && client.sessionFailedLoginAttempts >= disconnect) {
err = Errors.BadLogin('To many failed login attempts', ErrorReasons.TooMany);
}
client.log.info( { username, ip : client.remoteAddress, reason : err.message }, 'Failed login attempt');
return err;
} }