diff --git a/meshuser.js b/meshuser.js index ce7d7b89..16e46eb9 100644 --- a/meshuser.js +++ b/meshuser.js @@ -3191,18 +3191,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use case 'otpauth-request': { // Do not allow this command if 2FA's are locked - if ((domain.passwordrequirements) && (domain.passwordrequirements.lock2factor == true)) return; + if ((domain.passwordrequirements) && (domain.passwordrequirements.lock2factor == true)) { ws.send(JSON.stringify({ action: 'otpauth-request', err: 1 })); return; } // Do not allow this command if backup codes are not allowed - if ((domain.passwordrequirements) && (domain.passwordrequirements.backupcode2factor == false)) return; + if ((domain.passwordrequirements) && (domain.passwordrequirements.backupcode2factor == false)) { ws.send(JSON.stringify({ action: 'otpauth-request', err: 2 })); return; } // Do not allow this command when logged in using a login token - if (req.session.loginToken != null) break; + if (req.session.loginToken != null) { ws.send(JSON.stringify({ action: 'otpauth-request', err: 3 })); return; } // Check of OTP 2FA is allowed - if ((domain.passwordrequirements) && (domain.passwordrequirements.otp2factor == false)) break; + if ((domain.passwordrequirements) && (domain.passwordrequirements.otp2factor == false)) { ws.send(JSON.stringify({ action: 'otpauth-request', err: 4 })); return; } - if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here. + if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) { ws.send(JSON.stringify({ action: 'otpauth-request', err: 5 })); return; } // If this account is settings locked, return here. // Check if 2-step login is supported const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true)); @@ -3210,7 +3210,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Request a one time password to be setup var otplib = null; try { otplib = require('otplib'); } catch (ex) { } - if (otplib == null) { break; } + if (otplib == null) { ws.send(JSON.stringify({ action: 'otpauth-request', err: 6 })); return; } const secret = otplib.authenticator.generateSecret(); // TODO: Check the random source of this value. var domainName = parent.certificates.CommonName; diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index b45d1406..a35c321f 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -1604,13 +1604,18 @@ } case 'otpauth-request': { if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-request')) { - var secret = message.secret; - if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); } - else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '
' + secret.substring(20) } - QH('d2optinfo', format("Install Google Authenticator or a compatible application, use this link or enter the secret below. Then, enter the current 6 digit token to activate 2-Step login.", message.url) + '

' + secret + '

Token: = 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text>
'); - QV('idx_dlgOkButton', true); - QE('idx_dlgOkButton', false); - Q('d2otpauthinput').focus(); + if (message.err != null) { + var otpauthErrors = ['', "2FA is locked", "Backup codes are locked", "Login token in use", "OTP 2FA not allowed", "Account is locked", "Unable to load OTPLIB"]; + if ((message.err > 0) && (message.err < otpauthErrors.length)) { QH('d2optinfo', otpauthErrors[message.err]); } else { QH('d2optinfo', format("Error #{0}", message.err)); } + } else { + var secret = message.secret; + if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); } + else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '
' + secret.substring(20) } + QH('d2optinfo', format("Install Google Authenticator or a compatible application, use this link or enter the secret below. Then, enter the current 6 digit token to activate 2-Step login.", message.url) + '

' + secret + '

Token: = 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text>
'); + QV('idx_dlgOkButton', true); + QE('idx_dlgOkButton', false); + Q('d2otpauthinput').focus(); + } } break; } diff --git a/views/default.handlebars b/views/default.handlebars index 6b2ce17b..2f4dd70b 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -2704,14 +2704,19 @@ } case 'otpauth-request': { if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-request')) { - var secret = message.secret; - if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); } - else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '
' + secret.substring(20) } - QH('d2optinfo', '
' + format("Install Google Authenticator or a compatible application and scan the barcode, use this link or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login.", message.url) + '

' + "Secret" + '
' + secret + '


' + "Enter the token here for 2-step login:" + '
'); - new QRCode(Q('qrcode'), { text: message.url, width: 128, height: 128, colorDark: '#000000', colorLight: '#EEE', correctLevel: QRCode.CorrectLevel.H }); - QV('idx_dlgOkButton', true); - QE('idx_dlgOkButton', false); - Q('d2otpauthinput').focus(); + if (message.err != null) { + var otpauthErrors = [ '', "2FA is locked", "Backup codes are locked", "Login token in use", "OTP 2FA not allowed", "Account is locked", "Unable to load OTPLIB" ]; + if ((message.err > 0) && (message.err < otpauthErrors.length)) { QH('d2optinfo', otpauthErrors[message.err]); } else { QH('d2optinfo', format("Error #{0}", message.err)); } + } else { + var secret = message.secret; + if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); } + else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '
' + secret.substring(20) } + QH('d2optinfo', '
' + format("Install Google Authenticator or a compatible application and scan the barcode, use this link or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login.", message.url) + '

' + "Secret" + '
' + secret + '


' + "Enter the token here for 2-step login:" + '
'); + new QRCode(Q('qrcode'), { text: message.url, width: 128, height: 128, colorDark: '#000000', colorLight: '#EEE', correctLevel: QRCode.CorrectLevel.H }); + QV('idx_dlgOkButton', true); + QE('idx_dlgOkButton', false); + Q('d2otpauthinput').focus(); + } } break; }