You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
4.9 KiB
JavaScript
123 lines
4.9 KiB
JavaScript
3 years ago
|
var common = require('../../common');
|
||
|
var connect = require('../../connect');
|
||
5 years ago
|
var logger = require('./logger');
|
||
3 years ago
|
const jwt = require("jsonwebtoken");
|
||
4 years ago
|
const otplib = require("otplib");
|
||
3 years ago
|
var crypto = require('crypto');
|
||
|
var ONE_MINUTE = 60000;
|
||
|
var LOCKING_PERIOD = 30 * ONE_MINUTE; // HALF AN HOUR
|
||
|
var ALLOWED_LOGIN_ATTEMPTS = 5;
|
||
|
var failedLoginAttempts = {};
|
||
|
|
||
|
setInterval(() => {
|
||
|
for (var ip in failedLoginAttempts) {
|
||
|
if (new Date().getTime() > (failedLoginAttempts[ip].lastTried + LOCKING_PERIOD)) {
|
||
|
delete failedLoginAttempts[ip];
|
||
|
}
|
||
|
}
|
||
|
}, LOCKING_PERIOD);
|
||
|
|
||
|
getFailedInfo = (reqIP, currentTime) => {
|
||
|
let failed = failedLoginAttempts[reqIP] ? failedLoginAttempts[reqIP] : failedLoginAttempts[reqIP] = {count: 0, lastTried: currentTime};
|
||
|
if (currentTime > (failed.lastTried + LOCKING_PERIOD)) {
|
||
|
failed = failedLoginAttempts[reqIP] = {count: 0, lastTried: currentTime};
|
||
|
}
|
||
|
return failed;
|
||
|
}
|
||
5 years ago
|
|
||
3 years ago
|
handleError = (failed, currentTime, errMsg) => {
|
||
|
if (failed.count >= ALLOWED_LOGIN_ATTEMPTS && (currentTime <= (failed.lastTried + LOCKING_PERIOD))) {
|
||
|
return {
|
||
|
message: "Multiple Failed Login Attempts!",
|
||
|
error: "Application locked for " + (LOCKING_PERIOD/ONE_MINUTE) + " minutes due to multiple failed login attempts! Try again after " + common.convertTimestampToLocalDate((failed.lastTried + LOCKING_PERIOD)/1000) + "!"
|
||
|
};
|
||
|
} else {
|
||
|
return {
|
||
|
message: "Authentication Failed!",
|
||
|
error: errMsg + "\nApplication will be locked after " + (ALLOWED_LOGIN_ATTEMPTS - failed.count) + " more unsuccessful attempts!"
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exports.verifyToken = (twoFAToken) => {
|
||
|
if (common.rtl_secret2fa && common.rtl_secret2fa !== '' && otplib.authenticator.check(twoFAToken, common.rtl_secret2fa)) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
|
||
5 years ago
|
exports.authenticateUser = (req, res, next) => {
|
||
5 years ago
|
if(+common.rtl_sso) {
|
||
3 years ago
|
if(req.body.authenticateWith === 'JWT' && jwt.verify(req.body.authenticationValue, common.secret_key)) {
|
||
5 years ago
|
res.status(200).json({ token: token });
|
||
|
} else if (req.body.authenticateWith === 'PASSWORD' && crypto.createHash('sha256').update(common.cookie).digest('hex') === req.body.authenticationValue) {
|
||
5 years ago
|
connect.refreshCookie(common.rtl_cookie_path);
|
||
5 years ago
|
const token = jwt.sign(
|
||
4 years ago
|
{ user: 'SSO_USER', configPath: common.nodes[0].config_path, macaroonPath: common.nodes[0].macaroon_path },
|
||
5 years ago
|
common.secret_key
|
||
5 years ago
|
);
|
||
5 years ago
|
res.status(200).json({ token: token });
|
||
5 years ago
|
} else {
|
||
4 years ago
|
logger.error({fileName: 'Authenticate', lineNum: 20, msg: 'SSO Authentication Failed!'});
|
||
4 years ago
|
res.status(406).json({
|
||
5 years ago
|
message: "Login Failure!",
|
||
|
error: "SSO Authentication Failed!"
|
||
5 years ago
|
});
|
||
|
}
|
||
|
} else {
|
||
3 years ago
|
const currentTime = new Date().getTime();
|
||
|
const reqIP = common.getRequestIP(req);
|
||
|
let failed = getFailedInfo(reqIP, currentTime);
|
||
5 years ago
|
const password = req.body.authenticationValue;
|
||
3 years ago
|
if (common.rtl_pass === password && failed.count < ALLOWED_LOGIN_ATTEMPTS) {
|
||
3 years ago
|
if (req.body.twoFAToken && req.body.twoFAToken !== '') {
|
||
|
if (!this.verifyToken(req.body.twoFAToken)) {
|
||
|
logger.error({fileName: 'Authenticate', lineNum: 61, msg: 'Invalid Token! Failed IP ' + reqIP});
|
||
|
failed.count = failed.count + 1;
|
||
|
failed.lastTried = currentTime;
|
||
|
return res.status(401).json(handleError(failed, currentTime, 'Invalid 2FA Token!'));
|
||
|
}
|
||
|
}
|
||
3 years ago
|
delete failedLoginAttempts[reqIP];
|
||
|
let rpcUser = 'NODE_USER';
|
||
4 years ago
|
const token = jwt.sign(
|
||
|
{ user: rpcUser, configPath: common.nodes[0].config_path, macaroonPath: common.nodes[0].macaroon_path },
|
||
|
common.secret_key
|
||
|
);
|
||
|
res.status(200).json({ token: token });
|
||
5 years ago
|
} else {
|
||
3 years ago
|
logger.error({fileName: 'Authenticate', lineNum: 85, msg: 'Invalid Password! Failed IP ' + reqIP});
|
||
3 years ago
|
failed.count = common.rtl_pass !== password ? (failed.count + 1) : failed.count;
|
||
|
failed.lastTried = common.rtl_pass !== password ? currentTime : failed.lastTried;
|
||
3 years ago
|
return res.status(401).json(handleError(failed, currentTime, 'Invalid Password!'));
|
||
5 years ago
|
}
|
||
5 years ago
|
}
|
||
5 years ago
|
};
|
||
4 years ago
|
|
||
|
exports.resetPassword = (req, res, next) => {
|
||
|
if(+common.rtl_sso) {
|
||
4 years ago
|
logger.error({fileName: 'Authenticate', lineNum: 47, msg: 'Password Reset Failed!'});
|
||
|
res.status(401).json({
|
||
|
message: "Password Reset Failed!",
|
||
4 years ago
|
error: "Password cannot be reset for SSO authentication!"
|
||
|
});
|
||
|
} else {
|
||
4 years ago
|
const currPassword = req.body.currPassword;
|
||
|
if (common.rtl_pass === currPassword) {
|
||
4 years ago
|
common.rtl_pass = connect.replacePasswordWithHash(req.body.newPassword);
|
||
|
var rpcUser = 'NODE_USER';
|
||
|
const token = jwt.sign(
|
||
|
{ user: rpcUser, configPath: common.nodes[0].config_path, macaroonPath: common.nodes[0].macaroon_path },
|
||
|
common.secret_key
|
||
|
);
|
||
|
res.status(200).json({ token: token });
|
||
|
} else {
|
||
4 years ago
|
logger.error({fileName: 'Authenticate', lineNum: 63, msg: 'Password Reset Failed!'});
|
||
|
res.status(401).json({
|
||
4 years ago
|
message: "Password Reset Failed!",
|
||
|
error: "Old password is not correct!"
|
||
|
});
|
||
|
}
|
||
|
}
|
||
4 years ago
|
};
|