add duo authentication support (#6609)

Signed-off-by: si458 <simonsmith5521@gmail.com>
This commit is contained in:
Simon Smith
2024-12-21 13:52:54 +00:00
committed by GitHub
parent 59fcc0dbc6
commit e2362a0547
11 changed files with 2161 additions and 1893 deletions

View File

@@ -430,6 +430,7 @@
<div id="managePhoneNumber1"><div class="p2AccountActions"><span id="authPhoneNumberCheck"><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_managePhone()">Manage phone number</a><br /></span></div>
<div id="manageEmail2FA"><div class="p2AccountActions"><span id="authEmailSetupCheck"><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_manageAuthEmail()">Manage email authentication</a><br /></span></div>
<div id="manageAuthApp"><div class="p2AccountActions"><span id="authAppSetupCheck"><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_manageAuthApp()">Manage authenticator app</a><br /></span></div>
<div id="manageDuoApp"><div class="p2AccountActions"><span id="authDuoSetupCheck"><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_manageAuthDuo()">Manage Duo authentication</a><br /></span></div>
<div id="manageHardwareOtp"><div class="p2AccountActions"><span id="authKeySetupCheck"><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_manageHardwareOtp(0)">Manage security keys</a><br /></span></div>
<div id="managePushAuthDev"><div class="p2AccountActions"><span id="authPushAuthDevCheck"><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_managePushAuthDev()">Manage push authentication</a><br /></span></div>
<div id="manageMessaging1"><div class="p2AccountActions"><span id="authMessagingCheck"><strong>&#x2713;</strong></span></div><span><a href=# onclick="return account_manageMessaging()">Manage messaging</a><br /></span></div>
@@ -2357,6 +2358,7 @@
QV('authPhoneNumberCheck', (userinfo.phone != null));
QV('authMessagingCheck', (userinfo.msghandle != null));
QV('authEmailSetupCheck', (userinfo.otpekey == 1) && (userinfo.email != null) && (userinfo.emailVerified == true));
QV('authDuoSetupCheck', (userinfo.otpduo == 1));
QV('authAppSetupCheck', userinfo.otpsecret == 1);
QV('manageAuthApp', (serverinfo.lock2factor != true) && ((userinfo.otpsecret == 1) || ((features2 & 0x00020000) == 0)));
QV('authKeySetupCheck', userinfo.otphkeys > 0);
@@ -12881,6 +12883,14 @@
}, "When enabled, on each login, you will be given the option to receive a login token to you email account for added security." + '<br /><br /><label><input id=email2facheck type=checkbox ' + (emailU2Fenabled?'checked':'') + '/>' + "Enable email two-factor authentication." + '</label>');
}
function account_manageAuthDuo() {
if (xxdialogMode || ((features & 0x00800000) == 0)) return;
var duoU2Fenabled = ((userinfo.otpduo == 1));
setDialogMode(2, "Duo Authentication", 1, function () {
if (duoU2Fenabled != Q('duo2facheck').checked) { meshserver.send({ action: 'otpduo', enabled: Q('duo2facheck').checked }); }
}, "When enabled, on each login, you will be given the option to login using Duo for added security." + '<br /><br /><label><input id=duo2facheck type=checkbox ' + (duoU2Fenabled?'checked':'') + '/>' + "Enable Duo two-factor authentication." + '</label>');
}
function account_manageAuthApp() {
if (xxdialogMode || ((features & 4096) == 0)) return;
if (userinfo.otpsecret == 1) { account_removeOtp(); } else { account_addOtp(); }
@@ -15242,7 +15252,9 @@
156: "Verified messaging account of user {0}",
157: "Removed messaging account of user {0}",
158: "Displaying alert box, title=\"{0}\", message=\"{1}\"",
159: "Device Powered On"
159: "Device Powered On",
160: "Enabled Duo two-factor authentication",
161: "Disabled Duo two-factor authentication"
};
var eventsShortMessageId = {
@@ -15534,7 +15546,7 @@
if (userdomain != '') { username += ', <span style=color:#26F>' + userdomain + '</span>'; }
}
if ((user.otpsecret > 0) || (user.otphkeys > 0) || ((user.otpekey == 1) && (features & 0x00800000)) || ((user.phone != null) && (features & 0x04000000))) { username += ' <img src="images/key12.png" height=12 width=11 title="' + "2nd factor authentication enabled" + '" style="margin-top:2px" />'; }
if ((user.otpsecret > 0) || (user.otphkeys > 0) || ((user.otpekey == 1) && (features & 0x00800000)) || (user.otpduo == 1) || ((user.phone != null) && (features & 0x04000000))) { username += ' <img src="images/key12.png" height=12 width=11 title="' + "2nd factor authentication enabled" + '" style="margin-top:2px" />'; }
if (user.phone != null) { username += ' <img src="images/phone12.png" height=12 width=7 title="' + "Verified phone number" + '" style="margin-top:2px" />'; }
if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { username += ' <img src="images/padlock12.png" height=12 width=8 title="' + "Account is locked" + '" style="margin-top:2px" />'; }
if ((user.msghandle != null) && (features2 & 0x02000000)) { username += ' <img src="images/messaging12.png" height=12 width=12 title="' + "Verified messaging account" + '" style="margin-top:2px" />'; }
@@ -16717,12 +16729,13 @@
}
var multiFactor = 0;
if ((user.otpsecret > 0) || (user.otphkeys > 0) || (user.otpekey > 0)) {
if ((user.otpsecret > 0) || (user.otphkeys > 0) || (user.otpekey > 0) || (user.otpduo > 0)) {
multiFactor = 1;
var factors = [];
if (user.otpsecret > 0) { factors.push("Authentication App"); }
if (user.otphkeys > 0) { factors.push("Security Key"); }
if (user.otpekey > 0) { factors.push("Email"); }
if (user.otpduo > 0) { factors.push("Duo"); }
if (user.otpkeys > 0) { factors.push("Backup Codes"); }
if (user.otpdev > 0) { factors.push("Device Push"); }
if ((user.phone != null) && (features & 0x04000000)) { factors.push("SMS"); }

View File

@@ -590,6 +590,12 @@
id="authAppSetupCheck"><strong>&#x2713;</strong></span></div><span><a href=#
onclick="return account_manageAuthApp()">Manage authenticator
app</a><br /></span>
</div>
<div id="manageDuoApp">
<div class="p2AccountActions"><span
id="authDuoSetupCheck"><strong>&#x2713;</strong></span></div><span><a href=#
onclick="return account_manageAuthDuo()">Manage Duo
authentication</a><br /></span>
</div>
<div id="manageHardwareOtp">
<div class="p2AccountActions"><span
@@ -3018,6 +3024,7 @@
QV('authPhoneNumberCheck', (userinfo.phone != null));
QV('authMessagingCheck', (userinfo.msghandle != null));
QV('authEmailSetupCheck', (userinfo.otpekey == 1) && (userinfo.email != null) && (userinfo.emailVerified == true));
QV('authDuoSetupCheck', (userinfo.otpduo == 1));
QV('authAppSetupCheck', userinfo.otpsecret == 1);
QV('manageAuthApp', (serverinfo.lock2factor != true) && ((userinfo.otpsecret == 1) || ((features2 & 0x00020000) == 0)));
QV('authKeySetupCheck', userinfo.otphkeys > 0);
@@ -13994,6 +14001,15 @@
});
}
function account_manageAuthDuo() {
if (xxdialogMode || ((features & 0x00800000) == 0)) return;
var duoU2Fenabled = ((userinfo.otpduo == 1));
setModalContent('xxAddAgent', 'Duo Authentication', "When enabled, on each login, you will be given the option to login using Duo for added security." + '<br /><br /><label><input id=duo2facheck type=checkbox class="form-check-input me-2" ' + (duoU2Fenabled ? 'checked' : '') + '/>' + "Enable Duo two-factor authentication." + '</label>');
showModal('xxAddAgentModal', 'idx_dlgOkButton', function () {
if (duoU2Fenabled != Q('duo2facheck').checked) { meshserver.send({ action: 'otpduo', enabled: Q('duo2facheck').checked }); }
});
}
function account_manageAuthApp() {
if (xxdialogMode || ((features & 4096) == 0)) return;
if (userinfo.otpsecret == 1) { account_removeOtp(); } else { account_addOtp(); }
@@ -16578,7 +16594,9 @@
156: "Verified messaging account of user {0}",
157: "Removed messaging account of user {0}",
158: "Displaying alert box, title=\"{0}\", message=\"{1}\"",
159: "Device Powered On"
159: "Device Powered On",
160: "Enabled Duo two-factor authentication",
161: "Disabled Duo two-factor authentication"
};
var eventsShortMessageId = {
@@ -16881,7 +16899,7 @@
if (userdomain != '') { username += ', <span style=color:#26F>' + userdomain + '</span>'; }
}
if ((user.otpsecret > 0) || (user.otphkeys > 0) || ((user.otpekey == 1) && (features & 0x00800000)) || ((user.phone != null) && (features & 0x04000000))) { username += ' <i class="fa-solid fa-key" title="' + "2nd factor authentication enabled" + '" style="margin-top:2px"></i>'; }
if ((user.otpsecret > 0) || (user.otphkeys > 0) || ((user.otpekey == 1) && (features & 0x00800000)) || (user.otpduo == 1) || ((user.phone != null) && (features & 0x04000000))) { username += ' <i class="fa-solid fa-key" title="' + "2nd factor authentication enabled" + '" style="margin-top:2px"></i>'; }
if (user.phone != null) { username += ' <i class="fa-solid fa-mobile-screen" title="' + "Verified phone number" + '" style="margin-top:2px"></i>'; }
if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { username += ' <img src="images/padlock12.png" height=12 width=8 title="' + "Account is locked" + '" style="margin-top:2px" />'; }
if ((user.msghandle != null) && (features2 & 0x02000000)) { username += ' <i class="fa-solid fa-comment fa-xs" title="' + "Verified messaging account" + '" style="margin-top:2px" />'; }
@@ -18129,12 +18147,13 @@
}
var multiFactor = 0;
if ((user.otpsecret > 0) || (user.otphkeys > 0) || (user.otpekey > 0)) {
if ((user.otpsecret > 0) || (user.otphkeys > 0) || (user.otpekey > 0) || (user.otpduo > 0)) {
multiFactor = 1;
var factors = [];
if (user.otpsecret > 0) { factors.push("Authentication App"); }
if (user.otphkeys > 0) { factors.push("Security Key"); }
if (user.otpekey > 0) { factors.push("Email"); }
if (user.otpduo > 0) { factors.push("Duo"); }
if (user.otpkeys > 0) { factors.push("Backup Codes"); }
if (user.otpdev > 0) { factors.push("Device Push"); }
if ((user.phone != null) && (features & 0x04000000)) { factors.push("SMS"); }

View File

@@ -193,6 +193,7 @@
<input style="display:none;float:right" id=emailKeyButton type=button value="Email" onclick="useEmailToken(1)" />
<input style="display:none;float:right" id=smsKeyButton type=button value="SMS" onclick="useSMSToken(1)" />
<input style="display:none;float:right" id=msgKeyButton type=button value="Messaging" onclick="useMsgToken(1)" />
<input style="display:none;float:right" id=duoKeyButton type=button value="Duo" onclick="useDuoToken(1)" />
</div>
</td>
</tr>
@@ -221,6 +222,7 @@
<input style="display:none;float:right" id=emailKeyButton2 type=button value="Email" onclick="useEmailToken(2)" />
<input style="display:none;float:right" id=smsKeyButton2 type=button value="SMS" onclick="useSMSToken(2)" />
<input style="display:none;float:right" id=msgKeyButton2 type=button value="Messaging" onclick="useMsgToken(2)" />
<input style="display:none;float:right" id=duoKeyButton2 type=button value="Duo" onclick="useDuoToken(2)" />
</div>
</td>
</tr>
@@ -337,6 +339,7 @@
var webPageFullScreen = true;
var nightMode = (getstore('_nightMode', '0') == '1');
var publicKeyCredentialRequestOptions = null;
var otpduo = (decodeURIComponent('{{{otpduo}}}') === 'true');
var otpemail = (decodeURIComponent('{{{otpemail}}}') === 'true');
var otpsms = (decodeURIComponent('{{{otpsms}}}') === 'true');
var otpmsg = (decodeURIComponent('{{{otpmsg}}}') === 'true');
@@ -474,6 +477,7 @@
QV('emailKeyButton', otpemail && (messageid != 2) && (messageid != 4) && (messageid != 6));
QV('smsKeyButton', otpsms && (messageid != 2) && (messageid != 4) && (messageid != 6));
QV('msgKeyButton', otpmsg && (messageid != 2) && (messageid != 4) && (messageid != 6));
QV('duoKeyButton', otpduo && (messageid != 2) && (messageid != 4) && (messageid != 6));
// If hardware key is an option, trigger it now
if (autofido && twofakey) { setTimeout(function () { useSecurityKey(1); }, 300); }
@@ -487,6 +491,7 @@
QV('emailKeyButton2', otpemail && (messageid != 2) && (messageid != 4) && (messageid != 6));
QV('smsKeyButton2', otpsms && (messageid != 2) && (messageid != 4) && (messageid != 6));
QV('msgKeyButton2', otpmsg && (messageid != 2) && (messageid != 4) && (messageid != 6));
QV('duoKeyButton2', otpduo && (messageid != 2) && (messageid != 4) && (messageid != 6));
// If hardware key is an option, trigger it now
if (autofido && twofakey) { setTimeout(function () { useSecurityKey(2); }, 300); }
@@ -617,6 +622,18 @@
}
}
function useDuoToken(panelAction) {
if (panelAction == 1) {
Q('hwtokenInput').value = '**duo**';
QE('tokenOkButton', true);
Q('tokenOkButton').click();
} else if (panelAction == 2) {
Q('resetHwtokenInput').value = '**duo**';
QE('resetTokenOkButton', true);
Q('resetTokenOkButton').click();
}
}
function showPassHint(e) {
messagebox("Password Hint", passhint);
haltEvent(e);

View File

@@ -223,6 +223,7 @@
<img id=msgKeyButton src="images/login/2fa-messaging-48.png" srcset="images/login/2fa-messaging-96.png 2x" title="Messaging" loading="lazy" width="48" height="48" style="display:none;margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer;background-color:#FFF" onclick="useMsgToken(1)" />
<img id=emailKeyButton src="images/login/2fa-mail-48.png" srcset="images/login/2fa-mail-96.png 2x" title="Email" loading="lazy" width="48" height="48" style="display:none;margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer;background-color:#FFF" onclick="useEmailToken(1)" />
<img id=pushKeyButton src="images/login/2fa-push-48.png" srcset="images/login/2fa-push-96.png 2x" title="Device Authentication" loading="lazy" width="48" height="48" style="display:none;margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer;background-color:#FFF" onclick="usePushToken(1)" />
<img id=duoKeyButton src="images/login/2fa-duo-48.png" srcset="images/login/2fa-duo-96.png 2x" title="Duo Authentication" loading="lazy" width="48" height="48" style="display:none;margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer;background-color:#FFF" onclick="useDuoToken(1)" />
</div>
</td>
</tr>
@@ -258,6 +259,7 @@
<img id=msgKeyButton2 src="images/login/2fa-msg-48.png" srcset="images/login/2fa-msg-96.png 2x" title="SMS" loading="lazy" width="48" height="48" style="display:none;margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer;background-color:#FFF" onclick="useMsgToken(2)" />
<img id=emailKeyButton2 src="images/login/2fa-mail-48.png" srcset="images/login/2fa-mail-96.png 2x" title="Email" loading="lazy" width="48" height="48" style="display:none;margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer;background-color:#FFF" onclick="useEmailToken(2)" />
<img id=pushKeyButton2 src="images/login/2fa-push-48.png" srcset="images/login/2fa-push-96.png 2x" title="Device Authentication" loading="lazy" width="48" height="48" style="display:none;margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer;background-color:#FFF" onclick="usePushToken(2)" />
<img id=duoKeyButton2 src="images/login/2fa-duo-48.png" srcset="images/login/2fa-duo-96.png 2x" title="Duo Authentication" loading="lazy" width="48" height="48" style="display:none;margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer;background-color:#FFF" onclick="useDuoToken(2)" />
</div>
</td>
</tr>
@@ -393,6 +395,7 @@
var welcomeText = decodeURIComponent('{{{welcometext}}}');
var currentpanel = 0;
var publicKeyCredentialRequestOptions = null;
var otpduo = (decodeURIComponent('{{{otpduo}}}') === 'true');
var otpemail = (decodeURIComponent('{{{otpemail}}}') === 'true');
var otpsms = (decodeURIComponent('{{{otpsms}}}') === 'true');
var otpmsg = (decodeURIComponent('{{{otpmsg}}}') === 'true');
@@ -547,12 +550,14 @@
var smskey = otpsms && (messageid != 2) && (messageid != 4) && (messageid != 6);
var msgkey = otpmsg && (messageid != 2) && (messageid != 4) && (messageid != 6);
var pushkey = otppush && (messageid != 2) && (messageid != 4) && (messageid != 6);
var duokey = otpduo && (messageid != 2) && (messageid != 4) && (messageid != 6);
QV('securityKeyButton', twofakey);
QV('emailKeyButton', emailkey);
QV('smsKeyButton', smskey);
QV('msgKeyButton', msgkey);
QV('pushKeyButton', pushkey);
QV('2farow', twofakey || emailkey || smskey || msgkey || pushkey);
QV('duoKeyButton', duokey);
QV('2farow', twofakey || emailkey || smskey || msgkey || pushkey || duokey);
// If hardware key is an option, trigger it now
if (autofido && twofakey) { setTimeout(function () { useSecurityKey(1); }, 300); }
@@ -566,12 +571,14 @@
var smskey = otpsms && (messageid != 2) && (messageid != 4) && (messageid != 6);
var msgkey = otpmsg && (messageid != 2) && (messageid != 4) && (messageid != 6);
var pushkey = otppush && (messageid != 2) && (messageid != 4) && (messageid != 6);
var duokey = otpduo && (messageid != 2) && (messageid != 4) && (messageid != 6);
QV('securityKeyButton2', twofakey);
QV('emailKeyButton2', emailkey);
QV('smsKeyButton2', smskey);
QV('msgKeyButton2', msgkey);
QV('pushKeyButton', pushkey);
QV('2farow2', twofakey || emailkey || smskey || msgkey || pushkey);
QV('pushKeyButton2', pushkey);
QV('duoKeyButton2', duokey);
QV('2farow2', twofakey || emailkey || smskey || msgkey || pushkey || duokey);
// If hardware key is an option, trigger it now
if (autofido && twofakey) { setTimeout(function () { useSecurityKey(2); }, 300); }
@@ -723,6 +730,18 @@
}
}
function useDuoToken(panelAction) {
if (panelAction == 1) {
Q('hwtokenInput').value = '**duo**';
QE('tokenOkButton', true);
Q('tokenOkButton').click();
} else if (panelAction == 2) {
Q('resetHwtokenInput').value = '**duo**';
QE('resetTokenOkButton', true);
Q('resetTokenOkButton').click();
}
}
function showPassHint(e) {
messagebox("Password Hint", passhint);
haltEvent(e);