More work on mobile 2FA.
Ylian Saint-Hilaire committed
Apr 13, 2021 at 23:23 UTC
c74a20760634a91195f1a215203a44fd9a5d41b4
11 files changed
+133
-10
MeshCentralServer.njsproj
+1
@@ -99,6 +99,7 @@
99
<Compile Include="amt\amt.js" />
100
<Compile Include="exeHandler.js" />
101
<Compile Include="amtprovisioningserver.js" />
102
+ <Compile Include="firebase.js" />
103
<Compile Include="letsencrypt.js" />
104
<Compile Include="mcrec.js" />
105
<Compile Include="meshaccelerator.js" />
firebase.js
+26
-1
@@ -90,8 +90,16 @@ module.exports.CreateFirebase = function (parent, senderid, serverkey) {
90
//var payload = { notification: { title: command.title, body: command.msg }, data: { url: obj.msgurl } };
91
//var options = { priority: 'High', timeToLive: 5 * 60 }; // TTL: 5 minutes, priority 'Normal' or 'High'
92
93
- // Send an outbound push notification
93
obj.sendToDevice = function (node, payload, options, func) {
94
+ if (typeof node == 'string') {
95
+ parent.db.Get(node, function (err, docs) { if ((err == null) && (docs != null) && (docs.length == 1)) { obj.sendToDeviceEx(docs[0], payload, options, func); } else { func(0, 'error'); } })
96
+ } else {
97
+ obj.sendToDeviceEx(node, payload, options, func);
98
+ }
99
+ }
100
+
101
+ // Send an outbound push notification
102
+ obj.sendToDeviceEx = function (node, payload, options, func) {
103
parent.debug('email', 'Firebase-sendToDevice');
104
if ((node == null) || (typeof node.pmt != 'string')) return;
105
obj.log('sendToDevice, node:' + node._id + ', payload: ' + JSON.stringify(payload) + ', options: ' + JSON.stringify(options));
@@ -270,6 +278,14 @@ module.exports.CreateFirebaseRelay = function (parent, url, key) {
278
}
279
280
obj.sendToDevice = function (node, payload, options, func) {
281
+ if (typeof node == 'string') {
282
+ parent.db.Get(node, function (err, docs) { if ((err == null) && (docs != null) && (docs.length == 1)) { obj.sendToDeviceEx(docs[0], payload, options, func); } else { func(0, 'error'); } })
283
+ } else {
284
+ obj.sendToDeviceEx(node, payload, options, func);
285
+ }
286
+ }
287
+
288
+ obj.sendToDeviceEx = function (node, payload, options, func) {
289
parent.debug('email', 'Firebase-sendToDevice-webSocket');
290
if ((node == null) || (typeof node.pmt != 'string')) { func(0, 'error'); return; }
291
obj.log('sendToDevice, node:' + node._id + ', payload: ' + JSON.stringify(payload) + ', options: ' + JSON.stringify(options));
@@ -298,7 +314,16 @@ module.exports.CreateFirebaseRelay = function (parent, url, key) {
314
} else if (relayUrl.protocol == 'https:') {
315
// Send an outbound push notification using an HTTPS POST
316
obj.pushOnly = true;
317
+
318
obj.sendToDevice = function (node, payload, options, func) {
319
+ if (typeof node == 'string') {
320
+ parent.db.Get(node, function (err, docs) { if ((err == null) && (docs != null) && (docs.length == 1)) { obj.sendToDeviceEx(docs[0], payload, options, func); } else { func(0, 'error'); } })
321
+ } else {
322
+ obj.sendToDeviceEx(node, payload, options, func);
323
+ }
324
+ }
325
+
326
+ obj.sendToDeviceEx = function (node, payload, options, func) {
327
parent.debug('email', 'Firebase-sendToDevice-httpPost');
328
if ((node == null) || (typeof node.pmt != 'string')) return;
329
meshagent.js
+1
@@ -1556,6 +1556,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1556
// Complete 2FA checking
1557
if (authCookie.a == 'checkAuth') {
1558
// TODO
1559
+ console.log(authCookie);
1560
}
1561
1562
break;
public/images/login/2fa-push-48.png
Binary files /dev/null and b/public/images/login/2fa-push-48.png differ
public/images/login/2fa-push-96.png
Binary files /dev/null and b/public/images/login/2fa-push-96.png differ
public/images/login/push-150.png
Binary files /dev/null and b/public/images/login/push-150.png differ
public/images/login/push-300.png
Binary files /dev/null and b/public/images/login/push-300.png differ
public/styles/style.css
+1
-1
@@ -394,7 +394,7 @@ body {
394
color: blue;
395
}
396
397
-#loginpanel, #createpanel, #resetpanel, #tokenpanel, #resettokenpanel, #resetpasswordpanel, #resetpasswordpanel, #checkemailpanel {
397
+#loginpanel, #createpanel, #resetpanel, #tokenpanel, #resettokenpanel, #resetpasswordpanel, #resetpasswordpanel, #checkemailpanel, #waitpushpanel {
398
display: inline-block;
399
margin: 0;
400
background-color: #979797;
views/default.handlebars
+1
@@ -2032,6 +2032,7 @@
2032
QV('authKeySetupCheck', userinfo.otphkeys > 0);
2033
QV('authPushAuthDevCheck', (userinfo.otpdev > 0) && ((features2 & 2) != 0));
2034
QV('authCodesSetupCheck', userinfo.otpkeys > 0);
2035
+ QV('managePushAuthDev', (features2 & 2) && (count2factoraAuths() > 0));
2036
mainUpdate(4 + 128 + 4096);
2037
2038
// Check if none or at least 2 factors are enabled.
views/login2.handlebars
+45
-5
@@ -186,6 +186,7 @@
186
<img id=securityKeyButton src="images/login/2fa-key-48.png" srcset="images/login/2fa-key-96.png 2x" 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)" />
187
<img id=smsKeyButton src="images/login/2fa-sms-48.png" srcset="images/login/2fa-sms-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="useSMSToken(1)" />
188
<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)" />
189
+ <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)" />
190
</div>
191
</td>
192
</tr>
@@ -219,6 +220,7 @@
220
<img id=securityKeyButton2 src="images/login/2fa-key-48.png" srcset="images/login/2fa-key-96.png 2x" 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)" />
221
<img id=smsKeyButton2 src="images/login/2fa-sms-48.png" srcset="images/login/2fa-sms-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="useSMSToken(2)" />
222
<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)" />
223
+ <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)" />
224
</div>
225
</td>
226
</tr>
@@ -281,6 +283,22 @@
283
<input id=checkemailformargs name="urlargs" type="hidden" value="" />
284
</form>
285
</div>
286
+ <div id=waitpushpanel style="display:none">
287
+ <div id=message8></div>
288
+ <table style="width:100%">
289
+ <tr>
290
+ <td style="align-content:center;padding-top:10px">
291
+ <img src="images/login/push-150.png" srcset="images/login/push-300.png 2x" loading="lazy" width="265" height="150" />
292
+ </td>
293
+ </tr>
294
+ <tr>
295
+ <td style="align-content:center;padding-top:10px">
296
+ <label id=tokenInputRememberLabel2><input id=tokenInputRemember2 name=remembertoken type=checkbox /><span id=tokenInputRememberSpan2></span></label>
297
+ </td>
298
+ </tr>
299
+ </table>
300
+ <hr /><a onclick="return xgo(1,event);" href="#" style=cursor:pointer>Back to login</a>
301
+ </div>
302
</td>
303
</tr>
304
<tr id="welcomeTextRow"><td><div id="welcomeText" style="color:white;text-align:center;margin-left:20px;margin-right:20px"></div></td></tr>
@@ -330,6 +348,7 @@
348
var publicKeyCredentialRequestOptions = null;
349
var otpemail = (decodeURIComponent('{{{otpemail}}}') === 'true');
350
var otpsms = (decodeURIComponent('{{{otpsms}}}') === 'true');
351
+ var otppush = (decodeURIComponent('{{{otppush}}}') === 'true');
352
var twoFactorCookieDays = parseInt('{{{twoFactorCookieDays}}}');
353
var authStrategies = '{{{authStrategies}}}'.split(',');
354
@@ -342,15 +361,16 @@
361
// Display the right server message
362
var i;
363
var messageid = parseInt('{{{messageid}}}');
345
- var okmessages = ['', "If valid, reset mail sent.", "Email sent.", "Email verification required, check your mailbox and click the confirmation link.", "SMS sent."];
346
- var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later.", "Server under maintenance."];
364
+ var okmessages = ['', "If valid, reset mail sent.", "Email sent.", "Email verification required, check your mailbox and click the confirmation link.", "SMS sent.", "Notification sent, {0}."];
365
+ var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later.", "Server under maintenance.", "Unable to send device notification."];
366
if (messageid > 0) {
367
var msg = '';
368
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
369
else if ((messageid >= 100) && ((messageid - 100) < failmessages.length)) { msg = failmessages[messageid - 100]; }
370
+ if (messageid == 5) { msg = format(msg, passhint); }
371
if (msg != '') {
372
if (messageid >= 100) { msg = ('<span class="msg error"><b style=color:#8C001A>' + msg + '<b></span><br /><br />'); } else { msg = ('<span class="msg success"><b>' + msg + '</b></span><br /><br />'); }
353
- for (i = 1; i < 8; i++) { QH('message' + i, msg); }
373
+ for (i = 1; i < 9; i++) { QH('message' + i, msg); }
374
}
375
}
376
@@ -369,8 +389,11 @@
389
if (twoFactorCookieDays > 0) {
390
QV('tokenInputRememberLabel', true);
391
QH('tokenInputRememberSpan', format("Remember this device for {0} days.", twoFactorCookieDays));
392
+ QV('tokenInputRememberLabel2', true);
393
+ QH('tokenInputRememberSpan2', format("Remember this device for {0} days.", twoFactorCookieDays));
394
} else {
395
QV('tokenInputRememberLabel', false);
396
+ QV('tokenInputRememberLabel2', false);
397
}
398
399
// If URL arguments are provided, add them to form posts
@@ -443,10 +466,12 @@
466
var twofakey = (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn');
467
var emailkey = otpemail && (messageid != 2) && (messageid != 4);
468
var smskey = otpsms && (messageid != 2) && (messageid != 4);
469
+ var pushkey = otppush && (messageid != 2) && (messageid != 4);
470
QV('securityKeyButton', twofakey);
471
QV('emailKeyButton', emailkey);
472
QV('smsKeyButton', smskey);
449
- QV('2farow', twofakey || emailkey || smskey);
473
+ QV('pushKeyButton', pushkey);
474
+ QV('2farow', twofakey || emailkey || smskey || pushkey);
475
}
476
477
if (loginMode == '5') {
@@ -454,10 +479,12 @@
479
var twofakey = (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn');
480
var emailkey = otpemail && (messageid != 2) && (messageid != 4);
481
var smskey = otpsms && (messageid != 2) && (messageid != 4);
482
+ var pushkey = otppush && (messageid != 2) && (messageid != 4);
483
QV('securityKeyButton2', twofakey);
484
QV('emailKeyButton2', emailkey);
485
QV('smsKeyButton2', smskey);
460
- QV('2farow2', twofakey || emailkey || smskey);
486
+ QV('pushKeyButton', pushkey);
487
+ QV('2farow2', twofakey || emailkey || smskey || pushkey);
488
}
489
490
/*
@@ -565,6 +592,18 @@
592
}
593
}
594
595
+ function usePushToken(panelAction) {
596
+ if (panelAction == 1) {
597
+ Q('hwtokenInput').value = '**push**';
598
+ QE('tokenOkButton', true);
599
+ Q('tokenOkButton').click();
600
+ } else if (panelAction == 2) {
601
+ Q('resetHwtokenInput').value = '**push**';
602
+ QE('resetTokenOkButton', true);
603
+ Q('resetTokenOkButton').click();
604
+ }
605
+ }
606
+
607
function showPassHint(e) {
608
messagebox("Password Hint", passhint);
609
haltEvent(e);
@@ -595,6 +634,7 @@
634
QV('resettokenpanel', x == 5);
635
QV('resetpasswordpanel', x == 6);
636
QV('checkemailpanel', x == 7);
637
+ QV('waitpushpanel', x == 8);
638
if (x == 1) { Q('username').focus(); }
639
if (x == 2) { if (features & 0x200000) { Q('aemail').focus(); } else { Q('ausername').focus(); } } // Email is username
640
if (x == 3) { Q('remail').focus(); }
webserver.js
+58
-3
@@ -924,6 +924,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
924
925
var email2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (domain.mailserver != null) && (user.email != null) && (user.emailVerified == true) && (user.otpekey != null));
926
var sms2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.sms2factor != false)) && (parent.smsserver != null) && (user.phone != null));
927
+ var push2fa = ((parent.firebase != null) && (user.otpdev != null));
928
929
// Check if this user has 2-step login active
930
if ((req.session.loginmode != '6') && checkUserOneTimePasswordRequired(domain, user, req)) {
@@ -951,6 +952,29 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
952
return;
953
}
954
955
+ if ((req.body.hwtoken == '**push**') && push2fa) {
956
+ // Cause push notification to device
957
+ const logincode = obj.common.zeroPad(getRandomSixDigitInteger(), 6);
958
+ const code = Buffer.from(logincode).toString('base64');
959
+ const authCookie = parent.encodeCookie({ a: 'checkAuth', c: code, u: user._id, n: user.otpdev });
960
+ var payload = { notification: { title: "MeshCentral", body: user.name + " authentication" }, data: { url: '2fa://auth?code=' + code + '&c=' + authCookie } };
961
+ var options = { priority: 'High', timeToLive: 60 }; // TTL: 1 minute
962
+ parent.firebase.sendToDevice(user.otpdev, payload, options, function (id, err, errdesc) {
963
+ if (err == null) {
964
+ // Request that the login page wait for device auth
965
+ req.session.messageid = 5; // "Notification sent." message
966
+ req.session.passhint = logincode;
967
+ req.session.loginmode = '8';
968
+ } else {
969
+ // Indicate the push notification failed
970
+ req.session.messageid = 116; // "Unable to send device notification." message
971
+ req.session.loginmode = '4';
972
+ }
973
+ if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); }
974
+ });
975
+ return;
976
+ }
977
+
978
checkUserOneTimePassword(req, domain, user, req.body.token, req.body.hwtoken, function (result) {
979
if (result == false) {
980
var randomWaitTime = 0;
@@ -973,6 +997,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
997
req.session.loginmode = '4';
998
req.session.tokenemail = ((user.email != null) && (user.emailVerified == true) && (domain.mailserver != null) && (user.otpekey != null));
999
req.session.tokensms = ((user.phone != null) && (parent.smsserver != null));
1000
+ req.session.tokenpush = ((user.otpdev != null) && (parent.firebase != null));
1001
req.session.tokenuserid = userid;
1002
req.session.tokenusername = xusername;
1003
req.session.tokenpassword = xpassword;
@@ -1097,6 +1122,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1122
delete req.session.tokenpassword;
1123
delete req.session.tokenemail;
1124
delete req.session.tokensms;
1125
+ delete req.session.tokenpush;
1126
delete req.session.messageid;
1127
delete req.session.passhint;
1128
delete req.session.cuserid;
@@ -1301,6 +1327,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1327
delete req.session.resettokenpassword;
1328
delete req.session.tokenemail;
1329
delete req.session.tokensms;
1330
+ delete req.session.tokenpush;
1331
delete req.session.messageid;
1332
delete req.session.passhint;
1333
delete req.session.cuserid;
@@ -1382,6 +1409,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1409
delete req.session.resettokenpassword;
1410
delete req.session.tokenemail;
1411
delete req.session.tokensms;
1412
+ delete req.session.tokenpush;
1413
delete req.session.messageid;
1414
delete req.session.passhint;
1415
delete req.session.cuserid;
@@ -2638,7 +2666,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2666
var passhint = null, msgid = 0;
2667
if (req.session != null) {
2668
msgid = req.session.messageid;
2641
- if ((loginmode == '7') || ((domain.passwordrequirements != null) && (domain.passwordrequirements.hint === true))) { passhint = EscapeHtml(req.session.passhint); }
2669
+ if ((msgid == 5) || (loginmode == '7') || ((domain.passwordrequirements != null) && (domain.passwordrequirements.hint === true))) { passhint = EscapeHtml(req.session.passhint); }
2670
delete req.session.messageid;
2671
delete req.session.passhint;
2672
}
@@ -2658,6 +2686,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2686
if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.email2factor == false)) { otpemail = false; }
2687
var otpsms = (parent.smsserver != null) && (req.session != null) && (req.session.tokensms == true);
2688
if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.sms2factor == false)) { otpsms = false; }
2689
+ var otppush = (parent.firebase != null) && (req.session != null) && (req.session.tokenpush == true);
2690
+ //if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.push2factor == false)) { otppush = false; }
2691
2692
// See if we support two-factor trusted cookies
2693
var twoFactorCookieDays = 30;
@@ -2704,6 +2734,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2734
hwstate: hwstate,
2735
otpemail: otpemail,
2736
otpsms: otpsms,
2737
+ otppush: otppush,
2738
twoFactorCookieDays: twoFactorCookieDays,
2739
authStrategies: authStrategies.join(','),
2740
loginpicture: (typeof domain.loginpicture == 'string')
@@ -5844,7 +5875,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
5875
// Figure out if email 2FA is allowed
5876
var email2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (domain.mailserver != null) && (user.otpekey != null));
5877
var sms2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.sms2factor != false)) && (parent.smsserver != null) && (user.phone != null));
5847
- if ((typeof command.token != 'string') || (command.token == '**email**') || (command.token == '**sms**')) {
5878
+ //var push2fa = ((parent.firebase != null) && (user.otpdev != null));
5879
+ if ((typeof command.token != 'string') || (command.token == '**email**') || (command.token == '**sms**')/* || (command.token == '**push**')*/) {
5880
if ((command.token == '**email**') && (email2fa == true)) {
5881
// Cause a token to be sent to the user's registered email
5882
user.otpekey = { k: obj.common.zeroPad(getRandomEightDigitInteger(), 8), d: Date.now() };
@@ -5861,6 +5893,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
5893
parent.smsserver.sendToken(domain, user.phone, user.otpsms.k, obj.getLanguageCodes(req));
5894
// Ask for a login token & confirm sms was sent
5895
try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa, sms2fa: sms2fa, sms2fasent: true, twoFactorCookieDays: twoFactorCookieDays })); ws.close(); } catch (e) { }
5896
+ /*
5897
+ } else if ((command.token == '**push**') && (push2fa == true)) {
5898
+ // Cause push notification to device
5899
+ const code = Buffer.from(obj.common.zeroPad(getRandomSixDigitInteger(), 6)).toString('base64');
5900
+ const authCookie = parent.encodeCookie({ a: 'checkAuth', c: code, u: user._id, n: user.otpdev });
5901
+ var payload = { notification: { title: "MeshCentral", body: user.name + " authentication" }, data: { url: '2fa://auth?code=' + code + '&c=' + authCookie } };
5902
+ var options = { priority: 'High', timeToLive: 60 }; // TTL: 1 minute
5903
+ parent.firebase.sendToDevice(user.otpdev, payload, options, function (id, err, errdesc) {
5904
+ if (err == null) { parent.debug('email', 'Successfully auth check send push message to device'); } else { parent.debug('email', 'Failed auth check push message to device, error: ' + errdesc); }
5905
+ });
5906
+ */
5907
} else {
5908
// Ask for a login token
5909
parent.debug('web', 'Asking for login token');
@@ -5965,7 +6008,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6008
// Figure out if email 2FA is allowed
6009
var email2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (domain.mailserver != null) && (user.otpekey != null));
6010
var sms2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.sms2factor != false)) && (parent.smsserver != null) && (user.phone != null));
5968
- if ((typeof req.query.token != 'string') || (req.query.token == '**email**') || (req.query.token == '**sms**')) {
6011
+ //var push2fa = ((parent.firebase != null) && (user.otpdev != null));
6012
+ if ((typeof req.query.token != 'string') || (req.query.token == '**email**') || (req.query.token == '**sms**')/* || (req.query.token == '**push**')*/) {
6013
if ((req.query.token == '**email**') && (email2fa == true)) {
6014
// Cause a token to be sent to the user's registered email
6015
user.otpekey = { k: obj.common.zeroPad(getRandomEightDigitInteger(), 8), d: Date.now() };
@@ -5982,6 +6026,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
6026
parent.smsserver.sendToken(domain, user.phone, user.otpsms.k, obj.getLanguageCodes(req));
6027
// Ask for a login token & confirm sms was sent
6028
try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa, sms2fa: sms2fa, sms2fasent: true, twoFactorCookieDays: twoFactorCookieDays })); ws.close(); } catch (e) { }
6029
+ /*
6030
+ } else if ((command.token == '**push**') && (push2fa == true)) {
6031
+ // Cause push notification to device
6032
+ const code = Buffer.from(obj.common.zeroPad(getRandomSixDigitInteger(), 6)).toString('base64');
6033
+ const authCookie = parent.encodeCookie({ a: 'checkAuth', c: code, u: user._id, n: user.otpdev });
6034
+ var payload = { notification: { title: "MeshCentral", body: user.name + " authentication" }, data: { url: '2fa://auth?code=' + code + '&c=' + authCookie } };
6035
+ var options = { priority: 'High', timeToLive: 60 }; // TTL: 1 minute
6036
+ parent.firebase.sendToDevice(user.otpdev, payload, options, function (id, err, errdesc) {
6037
+ if (err == null) { parent.debug('email', 'Successfully auth check send push message to device'); } else { parent.debug('email', 'Failed auth check push message to device, error: ' + errdesc); }
6038
+ });
6039
+ */
6040
} else {
6041
// Ask for a login token
6042
parent.debug('web', 'Asking for login token');