Added autofido2fa option in PasswordRequirements, #2952

This commit is contained in:
Ylian Saint-Hilaire 2021-07-28 10:35:33 -07:00
parent bbbe5e7d36
commit 15ddd3cd00
5 changed files with 30 additions and 5 deletions

View File

@ -385,7 +385,8 @@
"oldPasswordBan": { "type": "integer", "description": "Number of old passwords the server should remember and not allow the user to switch back to." },
"banCommonPasswords": { "type": "boolean", "default": false, "description": "Uses WildLeek to block use of the 10000 most commonly used passwords." },
"loginTokens": { "type": "boolean", "default": true, "description": "Allows users to create alternative username/passwords for their account." },
"twoFactorTimeout": { "type": "integer", "default": 300, "description": "Maximum about of time the to wait for a 2FA token on the login page in seconds." }
"twoFactorTimeout": { "type": "integer", "default": 300, "description": "Maximum about of time the to wait for a 2FA token on the login page in seconds." },
"autofido2fa": { "type": "boolean", "default": false, "description": "If true and user account has FIDO key setup, 2FA login screen will automatically request FIDO 2FA." }
}
},
"twoFactorCookieDurationDays": { "type": "integer", "default": 30, "description": "Number of days that a user is allowed to remember this device for when completing 2FA. Set this to 0 to remove this option." },

View File

@ -324,6 +324,7 @@
var currentpanel = 0;
var otpemail = ('{{{otpemail}}}' === 'true');
var otpsms = ('{{{otpsms}}}' === 'true');
var autofido = (decodeURIComponent('{{{autofido}}}') === 'true');
var twoFactorCookieDays = parseInt('{{{twoFactorCookieDays}}}');
var authStrategies = '{{{authStrategies}}}'.split(',');
var tokenTimeout = parseInt('{{{tokenTimeout}}}');
@ -405,15 +406,20 @@
if (loginMode == '4') {
if (tokenTimeout > 0) { setTimeout(function () { Q('hwtokenInput').value = '**timeout**'; QE('tokenOkButton', true); Q('tokenOkButton').click(); }, tokenTimeout); }
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
var twofakey = (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn');
QV('securityKeyButton', twofakey);
QV('emailKeyButton', otpemail && (messageid != 2) && (messageid != 4));
QV('smsKeyButton', otpsms && (messageid != 2) && (messageid != 4));
// If hardware key is an option, trigger it now
if (autofido && twofakey) { setTimeout(function () { useSecurityKey(1); }, 300); }
}
if (loginMode == '5') {
if (tokenTimeout > 0) { setTimeout(function () { Q('hwtokenInput').value = '**timeout**'; QE('tokenOkButton', true); Q('tokenOkButton').click(); }, tokenTimeout); }
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
var twofakey = (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn');
if (twofakey) {
if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }

View File

@ -323,6 +323,7 @@
var publicKeyCredentialRequestOptions = null;
var otpemail = (decodeURIComponent('{{{otpemail}}}') === 'true');
var otpsms = (decodeURIComponent('{{{otpsms}}}') === 'true');
var autofido = (decodeURIComponent('{{{autofido}}}') === 'true');
var twoFactorCookieDays = parseInt('{{{twoFactorCookieDays}}}');
var authStrategies = '{{{authStrategies}}}'.split(',');
var tokenTimeout = parseInt('{{{tokenTimeout}}}');
@ -435,17 +436,25 @@
if (loginMode == '4') {
if (tokenTimeout > 0) { setTimeout(function () { Q('hwtokenInput').value = '**timeout**'; QE('tokenOkButton', true); Q('tokenOkButton').click(); }, tokenTimeout); }
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
var twofakey = (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn');
QV('securityKeyButton', twofakey);
QV('emailKeyButton', otpemail && (messageid != 2) && (messageid != 4));
QV('smsKeyButton', otpsms && (messageid != 2) && (messageid != 4));
// If hardware key is an option, trigger it now
if (autofido && twofakey) { setTimeout(function () { useSecurityKey(1); }, 300); }
}
if (loginMode == '5') {
if (tokenTimeout > 0) { setTimeout(function () { Q('hwtokenInput').value = '**timeout**'; QE('tokenOkButton', true); Q('tokenOkButton').click(); }, tokenTimeout); }
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
QV('securityKeyButton2', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
var twofakey = (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn');
QV('securityKeyButton2', twofakey);
QV('emailKeyButton2', otpemail && (messageid != 2) && (messageid != 4));
QV('smsKeyButton2', otpsms && (messageid != 2) && (messageid != 4));
// If hardware key is an option, trigger it now
if (autofido && twofakey) { setTimeout(function () { useSecurityKey(2); }, 300); }
}
/*

View File

@ -356,6 +356,7 @@
var otpemail = (decodeURIComponent('{{{otpemail}}}') === 'true');
var otpsms = (decodeURIComponent('{{{otpsms}}}') === 'true');
var otppush = (decodeURIComponent('{{{otppush}}}') === 'true');
var autofido = (decodeURIComponent('{{{autofido}}}') === 'true');
var twoFactorCookieDays = parseInt('{{{twoFactorCookieDays}}}');
var authStrategies = '{{{authStrategies}}}'.split(',');
var tokenTimeout = parseInt('{{{tokenTimeout}}}');
@ -475,6 +476,9 @@
QV('smsKeyButton', smskey);
QV('pushKeyButton', pushkey);
QV('2farow', twofakey || emailkey || smskey || pushkey);
// If hardware key is an option, trigger it now
if (autofido && twofakey) { setTimeout(function () { useSecurityKey(1); }, 300); }
}
if (loginMode == '5') {
@ -489,6 +493,9 @@
QV('smsKeyButton2', smskey);
QV('pushKeyButton', pushkey);
QV('2farow2', twofakey || emailkey || smskey || pushkey);
// If hardware key is an option, trigger it now
if (autofido && twofakey) { setTimeout(function () { useSecurityKey(2); }, 300); }
}
if (loginMode == '8') {

View File

@ -2863,6 +2863,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.sms2factor == false)) { otpsms = false; }
var otppush = (parent.firebase != null) && (req.session != null) && (req.session.tpush === 1);
if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.push2factor == false)) { otppush = false; }
const autofido = ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.autofido2fa == true)); // See if FIDO should be automatically prompted if user account has it.
// See if we support two-factor trusted cookies
var twoFactorCookieDays = 30;
@ -2917,6 +2918,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
otpemail: otpemail,
otpsms: otpsms,
otppush: otppush,
autofido: autofido,
twoFactorCookieDays: twoFactorCookieDays,
authStrategies: authStrategies.join(','),
loginpicture: (typeof domain.loginpicture == 'string'),