fix duo 2fa failing to add #2432
Signed-off-by: si458 <simonsmith5521@gmail.com>
si458 committed
Mar 11, 2025 at 19:24 UTC
1f83b7927a01614ce1cc56854f187c1d2f71d949
1 file changed
+67
-74
webserver.js
+67
-74
@@ -1433,6 +1433,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
1433
delete req.session.temail;
1434
delete req.session.tsms;
1435
delete req.session.tmsg;
1436
+ delete req.session.tduo;
1437
delete req.session.tpush;
1438
delete req.session.messageid;
1439
delete req.session.passhint;
@@ -7008,104 +7009,96 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
7009
res.redirect(domain.url + getQueryPortion(req)); // redirect back to main page
7010
return;
7011
} else {
7011
- // User credentials are stored in session, just check again and get userid
7012
- obj.authenticate(sec.tuser, sec.tpass, domain, function (err, userid, passhint, loginOptions) {
7013
- if ((userid != null) && (err == null)) {
7014
- // Login data correct, now exchange authorization code for 2FA
7015
- const duo = require('@duosecurity/duo_universal');
7016
- const client = new duo.Client({
7017
- clientId: domain.duo2factor.integrationkey,
7018
- clientSecret: domain.duo2factor.secretkey,
7019
- apiHost: domain.duo2factor.apihostname,
7020
- redirectUrl: obj.generateBaseURL(domain, req) + 'auth-duo' + (domain.loginkey != null ? ('?key=' + domain.loginkey) : '')
7021
- });
7022
- client.exchangeAuthorizationCodeFor2FAResult(req.query.duo_code, userid.split('/')[2]).then(function (data) {
7023
- const sec = parent.decryptSessionData(req.session.e);
7024
- if ((sec != null) && (sec.duoconfig == 1)) {
7025
- // Duo 2FA exchange success
7026
- parent.debug('web', 'handleRootRequest: Duo 2FA configuration success.');
7027
-
7028
- // Enable Duo for this user
7029
- var user = obj.users[userid];
7030
- if (user.otpduo == null) {
7031
- user.otpduo = {};
7032
- db.SetUser(user);
7033
-
7034
- // Notify change
7035
- var targets = ['*', 'server-users', user._id];
7036
- if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
7037
- var event = { etype: 'user', userid: user._id, username: user.name, account: obj.CloneSafeUser(user), action: 'accountchange', msgid: 160, msg: "Enabled duo two-factor authentication.", domain: domain.id };
7038
- if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
7039
- parent.DispatchEvent(targets, obj, event);
7040
- }
7041
-
7042
- // Clear the Duo state
7043
- delete sec.duostate;
7044
- delete sec.duoconfig;
7045
- req.session.e = parent.encryptSessionData(sec);
7046
-
7047
- var url = req.session.duorurl;
7048
- delete req.session.duorurl;
7049
- res.redirect(url ? url : domain.url); // Redirect back to the user's original page
7050
- } else {
7012
+ const duo = require('@duosecurity/duo_universal');
7013
+ const client = new duo.Client({
7014
+ clientId: domain.duo2factor.integrationkey,
7015
+ clientSecret: domain.duo2factor.secretkey,
7016
+ apiHost: domain.duo2factor.apihostname,
7017
+ redirectUrl: obj.generateBaseURL(domain, req) + 'auth-duo' + (domain.loginkey != null ? ('?key=' + domain.loginkey) : '')
7018
+ });
7019
+ if (sec.duoconfig == 1) {
7020
+ // Login data correct, now exchange authorization code for 2FA
7021
+ var userid = req.session.userid;
7022
+ client.exchangeAuthorizationCodeFor2FAResult(req.query.duo_code, userid.split('/')[2]).then(function (data) {
7023
+ // Duo 2FA exchange success
7024
+ parent.debug('web', 'handleRootRequest: Duo 2FA configuration success.');
7025
+ // Enable Duo for this user
7026
+ var user = obj.users[userid];
7027
+ if (user.otpduo == null) {
7028
+ user.otpduo = {};
7029
+ db.SetUser(user);
7030
+ // Notify change
7031
+ var targets = ['*', 'server-users', user._id];
7032
+ if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
7033
+ var event = { etype: 'user', userid: user._id, username: user.name, account: obj.CloneSafeUser(user), action: 'accountchange', msgid: 160, msg: "Enabled duo two-factor authentication.", domain: domain.id };
7034
+ if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
7035
+ parent.DispatchEvent(targets, obj, event);
7036
+ }
7037
+ // Clear the Duo state
7038
+ delete sec.duostate;
7039
+ delete sec.duoconfig;
7040
+ req.session.e = parent.encryptSessionData(sec);
7041
+ var url = req.session.duorurl;
7042
+ delete req.session.duorurl;
7043
+ res.redirect(url ? url : domain.url); // Redirect back to the user's original page
7044
+ }).catch(function (err) {
7045
+ const sec = parent.decryptSessionData(req.session.e);
7046
+ // Duo 2FA exchange success
7047
+ parent.debug('web', 'handleRootRequest: Duo 2FA configuration failed.');
7048
+ // Clear the Duo state
7049
+ delete sec.duostate;
7050
+ delete sec.duoconfig;
7051
+ req.session.e = parent.encryptSessionData(sec);
7052
+ var url = req.session.duorurl;
7053
+ delete req.session.duorurl;
7054
+ res.redirect(url ? url : domain.url); // Redirect back to the user's original page
7055
+ });
7056
+ } else {
7057
+ // User credentials are stored in session, just check again and get userid
7058
+ obj.authenticate(sec.tuser, sec.tpass, domain, function (err, userid, passhint, loginOptions) {
7059
+ if ((userid != null) && (err == null)) {
7060
+ // Login data correct, now exchange authorization code for 2FA
7061
+ client.exchangeAuthorizationCodeFor2FAResult(req.query.duo_code, userid.split('/')[2]).then(function (data) {
7062
+ const sec = parent.decryptSessionData(req.session.e);
7063
// Duo 2FA exchange success
7064
parent.debug('web', 'handleRootRequest: Duo 2FA authorization success.');
7065
req.session.userid = userid;
7066
delete req.session.currentNode;
7067
req.session.ip = req.clientIp; // Bind this session to the IP address of the request
7068
setSessionRandom(req);
7057
-
7058
- // Clear the Duo state
7069
+ // Clear the Duo state and user/pass
7070
delete sec.duostate;
7071
+ delete sec.tuser;
7072
+ delete sec.tpass;
7073
req.session.e = parent.encryptSessionData(sec);
7061
-
7074
obj.parent.authLog('https', 'Accepted Duo authentication for ' + userid + ' from ' + req.clientIp + ':' + req.connection.remotePort, { useragent: req.headers['user-agent'], sessionid: req.session.x });
7075
res.redirect(domain.url + getQueryPortion(req));
7064
- }
7065
- }).catch(function (err) {
7066
- console.log('err', err);
7067
- const sec = parent.decryptSessionData(req.session.e);
7068
- if ((sec != null) && (sec.duoconfig == 1)) {
7069
- // Duo 2FA exchange success
7070
- parent.debug('web', 'handleRootRequest: Duo 2FA configuration failed.');
7071
-
7072
- // Clear the Duo state
7073
- delete sec.duostate;
7074
- delete sec.duoconfig;
7075
- req.session.e = parent.encryptSessionData(sec);
7076
-
7077
- var url = req.session.duorurl;
7078
- delete req.session.duorurl;
7079
- res.redirect(url ? url : domain.url); // Redirect back to the user's original page
7080
- } else {
7076
+ }).catch(function (err) {
7077
+ const sec = parent.decryptSessionData(req.session.e);
7078
// Duo 2FA exchange failed
7079
parent.debug('web', 'handleRootRequest: Duo 2FA authorization failed.');
7083
-
7080
// Clear the Duo state
7081
delete sec.duostate;
7082
req.session.e = parent.encryptSessionData(sec);
7087
-
7083
req.session.loginmode = 1;
7084
req.session.messageid = 117; // Invalid security check
7085
res.redirect(domain.url + getQueryPortion(req));
7091
- }
7092
- });
7093
- } else {
7094
- // Login failed
7095
- parent.debug('web', 'handleRootRequest: login authorization failed when returning from Duo 2FA.');
7096
- req.session.loginmode = 1;
7097
- res.redirect(domain.url + getQueryPortion(req)); // redirect back to main page
7098
- return;
7099
- }
7100
- });
7086
+ });
7087
+ } else {
7088
+ // Login failed
7089
+ parent.debug('web', 'handleRootRequest: login authorization failed when returning from Duo 2FA.');
7090
+ req.session.loginmode = 1;
7091
+ res.redirect(domain.url + getQueryPortion(req)); // redirect back to main page
7092
+ return;
7093
+ }
7094
+ });
7095
+ }
7096
}
7097
});
7098
7099
// Configure Duo handler
7100
obj.app.get(url + 'add-duo', function (req, res) {
7101
var domain = getDomain(req);
7107
- const sec = parent.decryptSessionData(req.session.e);
7108
-
7102
if (req.session.userid == null) {
7103
res.sendStatus(404);
7104
} else {