Fixed account password reset when used with 2FA accounts.

Ylian Saint-Hilaire committed Sep 25, 2020 at 13:58 UTC 6411fbea42bbfe4c170eba1e50456d86afbf9615
5 files changed +130 -49
db.js
+3 -3
@@ -1012,8 +1012,8 @@ module.exports.CreateDB = function (parent, func) {
1012 };
1013 obj.GetAllType = function (type, func) { obj.file.find({ type: type }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1014 obj.GetAllIdsOfType = function (ids, domain, type, func) { obj.file.find({ type: type, domain: domain, _id: { $in: ids } }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1015 - obj.GetUserWithEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email }).project({ type: 0 }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1016 - obj.GetUserWithVerifiedEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email, emailVerified: true }).project({ type: 0 }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1015 + obj.GetUserWithEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1016 + obj.GetUserWithVerifiedEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email, emailVerified: true }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1017 obj.Remove = function (id, func) { obj.file.deleteOne({ _id: id }, func); };
1018 obj.RemoveAll = function (func) { obj.file.deleteMany({}, { multi: true }, func); };
1019 obj.RemoveAllOfType = function (type, func) { obj.file.deleteMany({ type: type }, { multi: true }, func); };
@@ -1166,7 +1166,7 @@ module.exports.CreateDB = function (parent, func) {
1166 obj.GetAllType = function (type, func) { obj.file.find({ type: type }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1167 obj.GetAllIdsOfType = function (ids, domain, type, func) { obj.file.find({ type: type, domain: domain, _id: { $in: ids } }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1168 obj.GetUserWithEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email }, { type: 0 }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1169 - obj.GetUserWithVerifiedEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email, emailVerified: true }, { type: 0 }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1169 + obj.GetUserWithVerifiedEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email, emailVerified: true }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); };
1170 obj.Remove = function (id, func) { obj.file.remove({ _id: id }, func); };
1171 obj.RemoveAll = function (func) { obj.file.remove({}, { multi: true }, func); };
1172 obj.RemoveAllOfType = function (type, func) { obj.file.remove({ type: type }, { multi: true }, func); };
translate/translate.json
+11 -4
@@ -13546,11 +13546,13 @@
13546 "login-mobile.handlebars->5->42",
13547 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->3",
13548 "login.handlebars->5->43",
13549 + "login.handlebars->container->column_l->centralTable->1->0->logincell->resettokenpanel->1->5->1->2->1->3",
13550 "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->4->1->3",
13551 "login2.handlebars->7->22",
13552 "login2.handlebars->7->44",
13553 "login2.handlebars->centralTable->1->0->logincell->resetpanel->1->7->1->0->1",
13554 "login2.handlebars->centralTable->1->0->logincell->resetpanel->1->7->1->0->1",
13555 + "login2.handlebars->centralTable->1->0->logincell->resettokenpanel->1->5->1->2farow2->1->3",
13556 "login2.handlebars->centralTable->1->0->logincell->tokenpanel->1->7->1->2farow->1->3"
13557 ]
13558 },
@@ -21235,6 +21237,7 @@
21237 "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->5->1",
21238 "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->7->1->4->3",
21239 "login2.handlebars->centralTable->1->0->logincell->loginpanel->1->5->1->6->1",
21240 + "login2.handlebars->centralTable->1->0->logincell->resettokenpanel->1->5->1->2->1->1",
21241 "login2.handlebars->centralTable->1->0->logincell->tokenpanel->1->7->1->2->1->1"
21242 ]
21243 },
@@ -21300,8 +21303,7 @@
21303 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resettokenpanel->1->5->1->2->1->1",
21304 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->1",
21305 "login.handlebars->container->column_l->centralTable->1->0->logincell->resettokenpanel->1->5->1->2->1->1",
21303 - "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->4->1->1",
21304 - "login2.handlebars->centralTable->1->0->logincell->resettokenpanel->1->5->1->2->1->1"
21306 + "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->4->1->1"
21307 ]
21308 },
21309 {
@@ -21388,8 +21390,7 @@
21390 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resettokenpanel->1->5->1->0->1",
21391 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->0->1",
21392 "login.handlebars->container->column_l->centralTable->1->0->logincell->resettokenpanel->1->5->1->0->1",
21391 - "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->0->1",
21392 - "login2.handlebars->centralTable->1->0->logincell->resettokenpanel->1->5->1->0->1"
21393 + "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->0->1"
21394 ]
21395 },
21396 {
@@ -30335,7 +30336,9 @@
30336 "default.handlebars->27->1905",
30337 "default.handlebars->27->1910",
30338 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->3",
30339 + "login.handlebars->container->column_l->centralTable->1->0->logincell->resettokenpanel->1->5->1->2->1->3",
30340 "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->4->1->3",
30341 + "login2.handlebars->centralTable->1->0->logincell->resettokenpanel->1->5->1->2farow2->1->3",
30342 "login2.handlebars->centralTable->1->0->logincell->tokenpanel->1->7->1->2farow->1->3"
30343 ]
30344 },
@@ -36193,6 +36196,8 @@
36196 "zh-chs": "代币",
36197 "zh-cht": "代幣",
36198 "xloc": [
36199 + "login2.handlebars->centralTable->1->0->logincell->resettokenpanel->1->5->1->0->1",
36200 + "login2.handlebars->centralTable->1->0->logincell->resettokenpanel->1->5->1->0->1",
36201 "login2.handlebars->centralTable->1->0->logincell->tokenpanel->1->7->1->0->1",
36202 "login2.handlebars->centralTable->1->0->logincell->tokenpanel->1->7->1->0->1"
36203 ]
@@ -37429,7 +37434,9 @@
37434 "zh-cht": "使用安全密鑰",
37435 "xloc": [
37436 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->3",
37437 + "login.handlebars->container->column_l->centralTable->1->0->logincell->resettokenpanel->1->5->1->2->1->3",
37438 "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->4->1->3",
37439 + "login2.handlebars->centralTable->1->0->logincell->resettokenpanel->1->5->1->2farow2->1->3",
37440 "login2.handlebars->centralTable->1->0->logincell->tokenpanel->1->7->1->2farow->1->3"
37441 ]
37442 },
views/login.handlebars
+52 -20
@@ -161,7 +161,7 @@
161 <tr>
162 <td align=right width=100>Login token:</td>
163 <td>
164 - <input id=tokenInput autocomplete="one-time-code" inputmode="numeric" type=text name=token maxlength=50 onchange=checkToken(event) onpaste=resetCheckToken(event) onkeyup=checkToken(event) onkeydown=checkToken(event) /><br />
164 + <input id=tokenInput autocomplete="one-time-code" inputmode="numeric" type=text name=token maxlength=50 onchange=checkToken(event) onpaste=checkToken(event) onkeyup=checkToken(event) onkeydown=checkToken(event) /><br />
165 <input id=hwtokenInput type=text name=hwtoken style="display:none" />
166 </td>
167 </tr>
@@ -174,9 +174,9 @@
174 <td colspan=2>
175 <div style=float:right><input id=tokenOkButton type=submit value="Login" disabled="disabled" /></div>
176 <div style=float:right>
177 - <input style="display:none;float:right" id=securityKeyButton type=button value="Use Security Key" onclick="useSecurityKey()" />
178 - <input style="display:none;float:right" id=emailKeyButton type=button value="Email" onclick="useEmailToken()" />
179 - <input style="display:none;float:right" id=smsKeyButton type=button value="SMS" onclick="useSMSToken()" />
177 + <input style="display:none;float:right" id=securityKeyButton type=button value="Use Security Key" onclick="useSecurityKey(1)" />
178 + <input style="display:none;float:right" id=emailKeyButton type=button value="Email" onclick="useEmailToken(1)" />
179 + <input style="display:none;float:right" id=smsKeyButton type=button value="SMS" onclick="useSMSToken(1)" />
180 </div>
181 </td>
182 </tr>
@@ -200,6 +200,11 @@
200 <tr>
201 <td colspan=2>
202 <div style=float:right><input id=resetTokenOkButton type=submit value="Login" disabled="disabled" /></div>
203 + <div style=float:right>
204 + <input style="display:none;float:right" id=securityKeyButton2 type=button value="Use Security Key" onclick="useSecurityKey(2)" />
205 + <input style="display:none;float:right" id=emailKeyButton2 type=button value="Email" onclick="useEmailToken(2)" />
206 + <input style="display:none;float:right" id=smsKeyButton2 type=button value="SMS" onclick="useSMSToken(2)" />
207 + </div>
208 </td>
209 </tr>
210 </table>
@@ -422,6 +427,14 @@
427 QV('smsKeyButton', otpsms && (messageid != 2) && (messageid != 4));
428 }
429
430 + if (loginMode == '5') {
431 + try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
432 + QV('securityKeyButton2', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
433 + QV('emailKeyButton2', otpemail && (messageid != 2) && (messageid != 4));
434 + QV('smsKeyButton2', otpsms && (messageid != 2) && (messageid != 4));
435 + }
436 +
437 + /*
438 if (loginMode == '5') {
439 try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
440 if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
@@ -452,13 +465,14 @@
465 );
466 }
467 }
468 + */
469
470 // Setup the user interface in the right mode
471 userInterfaceSelectMenu();
472 }
473
474 // Use a hardware security key
461 - function useSecurityKey() {
475 + function useSecurityKey(panelAction) {
476 if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
477 if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
478
@@ -479,35 +493,53 @@
493 signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
494 authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
495 };
482 - Q('hwtokenInput').value = JSON.stringify(assertion);
483 - QE('tokenOkButton', true);
484 - Q('tokenOkButton').click();
496 + if (panelAction == 1) {
497 + Q('hwtokenInput').value = JSON.stringify(assertion);
498 + QE('tokenOkButton', true);
499 + Q('tokenOkButton').click();
500 + } else if (panelAction == 2) {
501 + Q('resetHwtokenInput').value = JSON.stringify(assertion);
502 + QE('resetTokenOkButton', true);
503 + Q('resetTokenOkButton').click();
504 + }
505 },
506 function (error) { console.log('credentials-get error', error); }
507 );
508 }
509 }
510
491 - function useEmailToken() {
511 + function useEmailToken(panelAction) {
512 if (otpemail != true) return;
493 - setDialogMode(1, "Secure Login", 3, useEmailKeyEx, "Send token to registered email address?");
513 + setDialogMode(1, "Secure Login", 3, useEmailKeyEx, "Send token to registered email address?", panelAction);
514 }
515
496 - function useEmailKeyEx() {
497 - Q('hwtokenInput').value = '**email**';
498 - QE('tokenOkButton', true);
499 - Q('tokenOkButton').click();
516 + function useEmailKeyEx(b, panelAction) {
517 + if (panelAction == 1) {
518 + Q('hwtokenInput').value = '**email**';
519 + QE('tokenOkButton', true);
520 + Q('tokenOkButton').click();
521 + } else if (panelAction == 2) {
522 + Q('resetHwtokenInput').value = '**email**';
523 + QE('resetTokenOkButton', true);
524 + Q('resetTokenOkButton').click();
525 + }
526 }
527
502 - function useSMSToken() {
528 + function useSMSToken(panelAction) {
529 if (otpsms != true) return;
504 - setDialogMode(1, "Secure Login", 3, useSMSTokenEx, "Send token to registered phone number?");
530 + setDialogMode(1, "Secure Login", 3, useSMSTokenEx, "Send token to registered phone number?", panelAction);
531 }
532
507 - function useSMSTokenEx() {
508 - Q('hwtokenInput').value = '**sms**';
509 - QE('tokenOkButton', true);
510 - Q('tokenOkButton').click();
533 + function useSMSTokenEx(b, panelAction) {
534 + if (panelAction == 1) {
535 + Q('hwtokenInput').value = '**sms**';
536 + QE('tokenOkButton', true);
537 + Q('tokenOkButton').click();
538 + } else if (panelAction == 2) {
539 + Q('resetHwtokenInput').value = '**sms**';
540 + QE('resetTokenOkButton', true);
541 + Q('resetTokenOkButton').click();
542 + }
543 }
544
545 function showPassHint(e) {
views/login2.handlebars
+63 -21
@@ -180,9 +180,9 @@
180 <td>
181 <hr />
182 <div>
183 - <img id=securityKeyButton src="images/login/2fa-key-48.png" title="Use Security Key" 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="useSecurityKey()" />
184 - <img id=smsKeyButton src="images/login/2fa-sms-48.png" 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="useSMSToken()" />
185 - <img id=emailKeyButton src="images/login/2fa-mail-48.png" 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()" />
183 + <img id=securityKeyButton src="images/login/2fa-key-48.png" title="Use Security Key" 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="useSecurityKey(1)" />
184 + <img id=smsKeyButton src="images/login/2fa-sms-48.png" 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="useSMSToken(1)" />
185 + <img id=emailKeyButton src="images/login/2fa-mail-48.png" 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)" />
186 </div>
187 </td>
188 </tr>
@@ -195,17 +195,28 @@
195 <form method=post>
196 <input type=hidden name=action value=resetaccount />
197 <div id=message5></div>
198 - <table>
198 + <table style="width:100%">
199 <tr>
200 - <td align=right width=100>Login token:</td>
200 <td>
202 - <input id=resetTokenInput type=text name=token maxlength=50 onchange=resetCheckToken(event) onkeyup=resetCheckToken(event) onkeydown=resetCheckToken(event) />
201 + <input id=resetTokenInput autocomplete="one-time-code" title="Token" style="box-sizing:border-box;width:280px;border:0;border-radius:4px;padding:8px;background-color:#FFF8CC" placeholder="Token" type=text maxlength=50 name=token onchange=resetCheckToken(event) onpaste=resetCheckToken(event) onkeyup=resetCheckToken(event) onkeydown=resetCheckToken(event) /><br />
202 <input id=resetHwtokenInput type=text name=hwtoken style="display:none" />
203 </td>
204 </tr>
205 <tr>
206 + <td>
207 + <div>
208 + <input id=resetTokenOkButton style="box-sizing:border-box;width:280px;border:0;border-radius:4px;padding:6px" type=submit value="Log In" disabled="disabled" />
209 + </div>
210 + </td>
211 + </tr>
212 + <tr id="2farow2">
213 <td colspan=2>
208 - <div style=float:right><input id=resetTokenOkButton type=submit value="Login" disabled="disabled" /></div>
214 + <hr />
215 + <div>
216 + <img id=securityKeyButton2 src="images/login/2fa-key-48.png" title="Use Security Key" 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="useSecurityKey(2)" />
217 + <img id=smsKeyButton2 src="images/login/2fa-sms-48.png" 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="useSMSToken(2)" />
218 + <img id=emailKeyButton2 src="images/login/2fa-mail-48.png" 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)" />
219 + </div>
220 </td>
221 </tr>
222 </table>
@@ -427,6 +438,18 @@
438 QV('2farow', twofakey || emailkey || smskey);
439 }
440
441 + if (loginMode == '5') {
442 + try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
443 + var twofakey = (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn');
444 + var emailkey = otpemail && (messageid != 2) && (messageid != 4);
445 + var smskey = otpsms && (messageid != 2) && (messageid != 4);
446 + QV('securityKeyButton2', twofakey);
447 + QV('emailKeyButton2', emailkey);
448 + QV('smsKeyButton2', smskey);
449 + QV('2farow2', twofakey || emailkey || smskey);
450 + }
451 +
452 + /*
453 if (loginMode == '5') {
454 try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
455 if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
@@ -457,10 +480,11 @@
480 );
481 }
482 }
483 + */
484 }
485
486 // Use a hardware security key
463 - function useSecurityKey() {
487 + function useSecurityKey(panelAction) {
488 if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
489 if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
490
@@ -481,35 +505,53 @@
505 signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
506 authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
507 };
484 - Q('hwtokenInput').value = JSON.stringify(assertion);
485 - QE('tokenOkButton', true);
486 - Q('tokenOkButton').click();
508 + if (panelAction == 1) {
509 + Q('hwtokenInput').value = JSON.stringify(assertion);
510 + QE('tokenOkButton', true);
511 + Q('tokenOkButton').click();
512 + } else if (panelAction == 2) {
513 + Q('resetHwtokenInput').value = JSON.stringify(assertion);
514 + QE('resetTokenOkButton', true);
515 + Q('resetTokenOkButton').click();
516 + }
517 },
518 function (error) { console.log('credentials-get error', error); }
519 );
520 }
521 }
522
493 - function useEmailToken() {
523 + function useEmailToken(panelAction) {
524 if (otpemail != true) return;
525 setDialogMode(1, "Secure Login", 3, useEmailKeyEx, "Send token to registered email address?");
526 }
527
498 - function useEmailKeyEx() {
499 - Q('hwtokenInput').value = '**email**';
500 - QE('tokenOkButton', true);
501 - Q('tokenOkButton').click();
528 + function useEmailKeyEx(b, panelAction) {
529 + if (panelAction == 1) {
530 + Q('hwtokenInput').value = '**email**';
531 + QE('tokenOkButton', true);
532 + Q('tokenOkButton').click();
533 + } else if (panelAction == 2) {
534 + Q('resetHwtokenInput').value = '**email**';
535 + QE('resetTokenOkButton', true);
536 + Q('resetTokenOkButton').click();
537 + }
538 }
539
504 - function useSMSToken() {
540 + function useSMSToken(panelAction) {
541 if (otpsms != true) return;
542 setDialogMode(1, "Secure Login", 3, useSMSTokenEx, "Send token to registered phone number?");
543 }
544
509 - function useSMSTokenEx() {
510 - Q('hwtokenInput').value = '**sms**';
511 - QE('tokenOkButton', true);
512 - Q('tokenOkButton').click();
545 + function useSMSTokenEx(b, panelAction) {
546 + if (panelAction == 1) {
547 + Q('hwtokenInput').value = '**sms**';
548 + QE('tokenOkButton', true);
549 + Q('tokenOkButton').click();
550 + } else if (panelAction == 2) {
551 + Q('resetHwtokenInput').value = '**sms**';
552 + QE('resetTokenOkButton', true);
553 + Q('resetTokenOkButton').click();
554 + }
555 }
556
557 function showPassHint(e) {
webserver.js
+1 -1
@@ -2438,7 +2438,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2438 if (hardwareKeyChallenge) { hwstate = obj.parent.encodeCookie({ u: req.session.tokenusername, p: req.session.tokenpassword, c: req.session.u2fchallenge }, obj.parent.loginCookieEncryptionKey) }
2439
2440 // Check if we can use OTP tokens with email
2441 - var otpemail = (parent.mailserver != null) && (req.session != null) && (req.session.tokenemail == true);
2441 + var otpemail = (parent.mailserver != null) && (req.session != null) && ((req.session.tokenemail == true) || (typeof req.session.tokenemail == 'string'));
2442 if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.email2factor == false)) { otpemail = false; }
2443 var otpsms = (parent.smsserver != null) && (req.session != null) && (req.session.tokensms == true);
2444 if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.sms2factor == false)) { otpsms = false; }