mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 06:05:53 -05:00
More work on mobile 2FA.
This commit is contained in:
parent
da33f1dfb1
commit
c74a207606
@ -99,6 +99,7 @@
|
||||
<Compile Include="amt\amt.js" />
|
||||
<Compile Include="exeHandler.js" />
|
||||
<Compile Include="amtprovisioningserver.js" />
|
||||
<Compile Include="firebase.js" />
|
||||
<Compile Include="letsencrypt.js" />
|
||||
<Compile Include="mcrec.js" />
|
||||
<Compile Include="meshaccelerator.js" />
|
||||
|
27
firebase.js
27
firebase.js
@ -90,8 +90,16 @@ module.exports.CreateFirebase = function (parent, senderid, serverkey) {
|
||||
//var payload = { notification: { title: command.title, body: command.msg }, data: { url: obj.msgurl } };
|
||||
//var options = { priority: 'High', timeToLive: 5 * 60 }; // TTL: 5 minutes, priority 'Normal' or 'High'
|
||||
|
||||
// Send an outbound push notification
|
||||
obj.sendToDevice = function (node, payload, options, func) {
|
||||
if (typeof node == 'string') {
|
||||
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'); } })
|
||||
} else {
|
||||
obj.sendToDeviceEx(node, payload, options, func);
|
||||
}
|
||||
}
|
||||
|
||||
// Send an outbound push notification
|
||||
obj.sendToDeviceEx = function (node, payload, options, func) {
|
||||
parent.debug('email', 'Firebase-sendToDevice');
|
||||
if ((node == null) || (typeof node.pmt != 'string')) return;
|
||||
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) {
|
||||
}
|
||||
|
||||
obj.sendToDevice = function (node, payload, options, func) {
|
||||
if (typeof node == 'string') {
|
||||
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'); } })
|
||||
} else {
|
||||
obj.sendToDeviceEx(node, payload, options, func);
|
||||
}
|
||||
}
|
||||
|
||||
obj.sendToDeviceEx = function (node, payload, options, func) {
|
||||
parent.debug('email', 'Firebase-sendToDevice-webSocket');
|
||||
if ((node == null) || (typeof node.pmt != 'string')) { func(0, 'error'); return; }
|
||||
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) {
|
||||
} else if (relayUrl.protocol == 'https:') {
|
||||
// Send an outbound push notification using an HTTPS POST
|
||||
obj.pushOnly = true;
|
||||
|
||||
obj.sendToDevice = function (node, payload, options, func) {
|
||||
if (typeof node == 'string') {
|
||||
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'); } })
|
||||
} else {
|
||||
obj.sendToDeviceEx(node, payload, options, func);
|
||||
}
|
||||
}
|
||||
|
||||
obj.sendToDeviceEx = function (node, payload, options, func) {
|
||||
parent.debug('email', 'Firebase-sendToDevice-httpPost');
|
||||
if ((node == null) || (typeof node.pmt != 'string')) return;
|
||||
|
||||
|
@ -1556,6 +1556,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
// Complete 2FA checking
|
||||
if (authCookie.a == 'checkAuth') {
|
||||
// TODO
|
||||
console.log(authCookie);
|
||||
}
|
||||
|
||||
break;
|
||||
|
BIN
public/images/login/2fa-push-48.png
Normal file
BIN
public/images/login/2fa-push-48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
public/images/login/2fa-push-96.png
Normal file
BIN
public/images/login/2fa-push-96.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
public/images/login/push-150.png
Normal file
BIN
public/images/login/push-150.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
public/images/login/push-300.png
Normal file
BIN
public/images/login/push-300.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
@ -394,7 +394,7 @@ body {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
#loginpanel, #createpanel, #resetpanel, #tokenpanel, #resettokenpanel, #resetpasswordpanel, #resetpasswordpanel, #checkemailpanel {
|
||||
#loginpanel, #createpanel, #resetpanel, #tokenpanel, #resettokenpanel, #resetpasswordpanel, #resetpasswordpanel, #checkemailpanel, #waitpushpanel {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
background-color: #979797;
|
||||
|
@ -2032,6 +2032,7 @@
|
||||
QV('authKeySetupCheck', userinfo.otphkeys > 0);
|
||||
QV('authPushAuthDevCheck', (userinfo.otpdev > 0) && ((features2 & 2) != 0));
|
||||
QV('authCodesSetupCheck', userinfo.otpkeys > 0);
|
||||
QV('managePushAuthDev', (features2 & 2) && (count2factoraAuths() > 0));
|
||||
mainUpdate(4 + 128 + 4096);
|
||||
|
||||
// Check if none or at least 2 factors are enabled.
|
||||
|
@ -186,6 +186,7 @@
|
||||
<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)" />
|
||||
<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)" />
|
||||
<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)" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -219,6 +220,7 @@
|
||||
<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)" />
|
||||
<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)" />
|
||||
<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)" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -281,6 +283,22 @@
|
||||
<input id=checkemailformargs name="urlargs" type="hidden" value="" />
|
||||
</form>
|
||||
</div>
|
||||
<div id=waitpushpanel style="display:none">
|
||||
<div id=message8></div>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td style="align-content:center;padding-top:10px">
|
||||
<img src="images/login/push-150.png" srcset="images/login/push-300.png 2x" loading="lazy" width="265" height="150" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="align-content:center;padding-top:10px">
|
||||
<label id=tokenInputRememberLabel2><input id=tokenInputRemember2 name=remembertoken type=checkbox /><span id=tokenInputRememberSpan2></span></label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr /><a onclick="return xgo(1,event);" href="#" style=cursor:pointer>Back to login</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<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 @@
|
||||
var publicKeyCredentialRequestOptions = null;
|
||||
var otpemail = (decodeURIComponent('{{{otpemail}}}') === 'true');
|
||||
var otpsms = (decodeURIComponent('{{{otpsms}}}') === 'true');
|
||||
var otppush = (decodeURIComponent('{{{otppush}}}') === 'true');
|
||||
var twoFactorCookieDays = parseInt('{{{twoFactorCookieDays}}}');
|
||||
var authStrategies = '{{{authStrategies}}}'.split(',');
|
||||
|
||||
@ -342,15 +361,16 @@
|
||||
// Display the right server message
|
||||
var i;
|
||||
var messageid = parseInt('{{{messageid}}}');
|
||||
var okmessages = ['', "If valid, reset mail sent.", "Email sent.", "Email verification required, check your mailbox and click the confirmation link.", "SMS sent."];
|
||||
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."];
|
||||
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}."];
|
||||
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."];
|
||||
if (messageid > 0) {
|
||||
var msg = '';
|
||||
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
||||
else if ((messageid >= 100) && ((messageid - 100) < failmessages.length)) { msg = failmessages[messageid - 100]; }
|
||||
if (messageid == 5) { msg = format(msg, passhint); }
|
||||
if (msg != '') {
|
||||
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 />'); }
|
||||
for (i = 1; i < 8; i++) { QH('message' + i, msg); }
|
||||
for (i = 1; i < 9; i++) { QH('message' + i, msg); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,8 +389,11 @@
|
||||
if (twoFactorCookieDays > 0) {
|
||||
QV('tokenInputRememberLabel', true);
|
||||
QH('tokenInputRememberSpan', format("Remember this device for {0} days.", twoFactorCookieDays));
|
||||
QV('tokenInputRememberLabel2', true);
|
||||
QH('tokenInputRememberSpan2', format("Remember this device for {0} days.", twoFactorCookieDays));
|
||||
} else {
|
||||
QV('tokenInputRememberLabel', false);
|
||||
QV('tokenInputRememberLabel2', false);
|
||||
}
|
||||
|
||||
// If URL arguments are provided, add them to form posts
|
||||
@ -443,10 +466,12 @@
|
||||
var twofakey = (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn');
|
||||
var emailkey = otpemail && (messageid != 2) && (messageid != 4);
|
||||
var smskey = otpsms && (messageid != 2) && (messageid != 4);
|
||||
var pushkey = otppush && (messageid != 2) && (messageid != 4);
|
||||
QV('securityKeyButton', twofakey);
|
||||
QV('emailKeyButton', emailkey);
|
||||
QV('smsKeyButton', smskey);
|
||||
QV('2farow', twofakey || emailkey || smskey);
|
||||
QV('pushKeyButton', pushkey);
|
||||
QV('2farow', twofakey || emailkey || smskey || pushkey);
|
||||
}
|
||||
|
||||
if (loginMode == '5') {
|
||||
@ -454,10 +479,12 @@
|
||||
var twofakey = (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn');
|
||||
var emailkey = otpemail && (messageid != 2) && (messageid != 4);
|
||||
var smskey = otpsms && (messageid != 2) && (messageid != 4);
|
||||
var pushkey = otppush && (messageid != 2) && (messageid != 4);
|
||||
QV('securityKeyButton2', twofakey);
|
||||
QV('emailKeyButton2', emailkey);
|
||||
QV('smsKeyButton2', smskey);
|
||||
QV('2farow2', twofakey || emailkey || smskey);
|
||||
QV('pushKeyButton', pushkey);
|
||||
QV('2farow2', twofakey || emailkey || smskey || pushkey);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -565,6 +592,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
function usePushToken(panelAction) {
|
||||
if (panelAction == 1) {
|
||||
Q('hwtokenInput').value = '**push**';
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
} else if (panelAction == 2) {
|
||||
Q('resetHwtokenInput').value = '**push**';
|
||||
QE('resetTokenOkButton', true);
|
||||
Q('resetTokenOkButton').click();
|
||||
}
|
||||
}
|
||||
|
||||
function showPassHint(e) {
|
||||
messagebox("Password Hint", passhint);
|
||||
haltEvent(e);
|
||||
@ -595,6 +634,7 @@
|
||||
QV('resettokenpanel', x == 5);
|
||||
QV('resetpasswordpanel', x == 6);
|
||||
QV('checkemailpanel', x == 7);
|
||||
QV('waitpushpanel', x == 8);
|
||||
if (x == 1) { Q('username').focus(); }
|
||||
if (x == 2) { if (features & 0x200000) { Q('aemail').focus(); } else { Q('ausername').focus(); } } // Email is username
|
||||
if (x == 3) { Q('remail').focus(); }
|
||||
|
61
webserver.js
61
webserver.js
@ -924,6 +924,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
|
||||
var email2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (domain.mailserver != null) && (user.email != null) && (user.emailVerified == true) && (user.otpekey != null));
|
||||
var sms2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.sms2factor != false)) && (parent.smsserver != null) && (user.phone != null));
|
||||
var push2fa = ((parent.firebase != null) && (user.otpdev != null));
|
||||
|
||||
// Check if this user has 2-step login active
|
||||
if ((req.session.loginmode != '6') && checkUserOneTimePasswordRequired(domain, user, req)) {
|
||||
@ -951,6 +952,29 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((req.body.hwtoken == '**push**') && push2fa) {
|
||||
// Cause push notification to device
|
||||
const logincode = obj.common.zeroPad(getRandomSixDigitInteger(), 6);
|
||||
const code = Buffer.from(logincode).toString('base64');
|
||||
const authCookie = parent.encodeCookie({ a: 'checkAuth', c: code, u: user._id, n: user.otpdev });
|
||||
var payload = { notification: { title: "MeshCentral", body: user.name + " authentication" }, data: { url: '2fa://auth?code=' + code + '&c=' + authCookie } };
|
||||
var options = { priority: 'High', timeToLive: 60 }; // TTL: 1 minute
|
||||
parent.firebase.sendToDevice(user.otpdev, payload, options, function (id, err, errdesc) {
|
||||
if (err == null) {
|
||||
// Request that the login page wait for device auth
|
||||
req.session.messageid = 5; // "Notification sent." message
|
||||
req.session.passhint = logincode;
|
||||
req.session.loginmode = '8';
|
||||
} else {
|
||||
// Indicate the push notification failed
|
||||
req.session.messageid = 116; // "Unable to send device notification." message
|
||||
req.session.loginmode = '4';
|
||||
}
|
||||
if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
checkUserOneTimePassword(req, domain, user, req.body.token, req.body.hwtoken, function (result) {
|
||||
if (result == false) {
|
||||
var randomWaitTime = 0;
|
||||
@ -973,6 +997,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
req.session.loginmode = '4';
|
||||
req.session.tokenemail = ((user.email != null) && (user.emailVerified == true) && (domain.mailserver != null) && (user.otpekey != null));
|
||||
req.session.tokensms = ((user.phone != null) && (parent.smsserver != null));
|
||||
req.session.tokenpush = ((user.otpdev != null) && (parent.firebase != null));
|
||||
req.session.tokenuserid = userid;
|
||||
req.session.tokenusername = xusername;
|
||||
req.session.tokenpassword = xpassword;
|
||||
@ -1097,6 +1122,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
delete req.session.tokenpassword;
|
||||
delete req.session.tokenemail;
|
||||
delete req.session.tokensms;
|
||||
delete req.session.tokenpush;
|
||||
delete req.session.messageid;
|
||||
delete req.session.passhint;
|
||||
delete req.session.cuserid;
|
||||
@ -1301,6 +1327,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
delete req.session.resettokenpassword;
|
||||
delete req.session.tokenemail;
|
||||
delete req.session.tokensms;
|
||||
delete req.session.tokenpush;
|
||||
delete req.session.messageid;
|
||||
delete req.session.passhint;
|
||||
delete req.session.cuserid;
|
||||
@ -1382,6 +1409,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
delete req.session.resettokenpassword;
|
||||
delete req.session.tokenemail;
|
||||
delete req.session.tokensms;
|
||||
delete req.session.tokenpush;
|
||||
delete req.session.messageid;
|
||||
delete req.session.passhint;
|
||||
delete req.session.cuserid;
|
||||
@ -2638,7 +2666,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
var passhint = null, msgid = 0;
|
||||
if (req.session != null) {
|
||||
msgid = req.session.messageid;
|
||||
if ((loginmode == '7') || ((domain.passwordrequirements != null) && (domain.passwordrequirements.hint === true))) { passhint = EscapeHtml(req.session.passhint); }
|
||||
if ((msgid == 5) || (loginmode == '7') || ((domain.passwordrequirements != null) && (domain.passwordrequirements.hint === true))) { passhint = EscapeHtml(req.session.passhint); }
|
||||
delete req.session.messageid;
|
||||
delete req.session.passhint;
|
||||
}
|
||||
@ -2658,6 +2686,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.email2factor == false)) { otpemail = false; }
|
||||
var otpsms = (parent.smsserver != null) && (req.session != null) && (req.session.tokensms == true);
|
||||
if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.sms2factor == false)) { otpsms = false; }
|
||||
var otppush = (parent.firebase != null) && (req.session != null) && (req.session.tokenpush == true);
|
||||
//if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.push2factor == false)) { otppush = false; }
|
||||
|
||||
// See if we support two-factor trusted cookies
|
||||
var twoFactorCookieDays = 30;
|
||||
@ -2704,6 +2734,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
hwstate: hwstate,
|
||||
otpemail: otpemail,
|
||||
otpsms: otpsms,
|
||||
otppush: otppush,
|
||||
twoFactorCookieDays: twoFactorCookieDays,
|
||||
authStrategies: authStrategies.join(','),
|
||||
loginpicture: (typeof domain.loginpicture == 'string')
|
||||
@ -5844,7 +5875,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
// Figure out if email 2FA is allowed
|
||||
var email2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (domain.mailserver != null) && (user.otpekey != null));
|
||||
var sms2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.sms2factor != false)) && (parent.smsserver != null) && (user.phone != null));
|
||||
if ((typeof command.token != 'string') || (command.token == '**email**') || (command.token == '**sms**')) {
|
||||
//var push2fa = ((parent.firebase != null) && (user.otpdev != null));
|
||||
if ((typeof command.token != 'string') || (command.token == '**email**') || (command.token == '**sms**')/* || (command.token == '**push**')*/) {
|
||||
if ((command.token == '**email**') && (email2fa == true)) {
|
||||
// Cause a token to be sent to the user's registered email
|
||||
user.otpekey = { k: obj.common.zeroPad(getRandomEightDigitInteger(), 8), d: Date.now() };
|
||||
@ -5861,6 +5893,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
parent.smsserver.sendToken(domain, user.phone, user.otpsms.k, obj.getLanguageCodes(req));
|
||||
// Ask for a login token & confirm sms was sent
|
||||
try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa, sms2fa: sms2fa, sms2fasent: true, twoFactorCookieDays: twoFactorCookieDays })); ws.close(); } catch (e) { }
|
||||
/*
|
||||
} else if ((command.token == '**push**') && (push2fa == true)) {
|
||||
// Cause push notification to device
|
||||
const code = Buffer.from(obj.common.zeroPad(getRandomSixDigitInteger(), 6)).toString('base64');
|
||||
const authCookie = parent.encodeCookie({ a: 'checkAuth', c: code, u: user._id, n: user.otpdev });
|
||||
var payload = { notification: { title: "MeshCentral", body: user.name + " authentication" }, data: { url: '2fa://auth?code=' + code + '&c=' + authCookie } };
|
||||
var options = { priority: 'High', timeToLive: 60 }; // TTL: 1 minute
|
||||
parent.firebase.sendToDevice(user.otpdev, payload, options, function (id, err, errdesc) {
|
||||
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); }
|
||||
});
|
||||
*/
|
||||
} else {
|
||||
// Ask for a login token
|
||||
parent.debug('web', 'Asking for login token');
|
||||
@ -5965,7 +6008,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
// Figure out if email 2FA is allowed
|
||||
var email2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (domain.mailserver != null) && (user.otpekey != null));
|
||||
var sms2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.sms2factor != false)) && (parent.smsserver != null) && (user.phone != null));
|
||||
if ((typeof req.query.token != 'string') || (req.query.token == '**email**') || (req.query.token == '**sms**')) {
|
||||
//var push2fa = ((parent.firebase != null) && (user.otpdev != null));
|
||||
if ((typeof req.query.token != 'string') || (req.query.token == '**email**') || (req.query.token == '**sms**')/* || (req.query.token == '**push**')*/) {
|
||||
if ((req.query.token == '**email**') && (email2fa == true)) {
|
||||
// Cause a token to be sent to the user's registered email
|
||||
user.otpekey = { k: obj.common.zeroPad(getRandomEightDigitInteger(), 8), d: Date.now() };
|
||||
@ -5982,6 +6026,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
parent.smsserver.sendToken(domain, user.phone, user.otpsms.k, obj.getLanguageCodes(req));
|
||||
// Ask for a login token & confirm sms was sent
|
||||
try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa, sms2fa: sms2fa, sms2fasent: true, twoFactorCookieDays: twoFactorCookieDays })); ws.close(); } catch (e) { }
|
||||
/*
|
||||
} else if ((command.token == '**push**') && (push2fa == true)) {
|
||||
// Cause push notification to device
|
||||
const code = Buffer.from(obj.common.zeroPad(getRandomSixDigitInteger(), 6)).toString('base64');
|
||||
const authCookie = parent.encodeCookie({ a: 'checkAuth', c: code, u: user._id, n: user.otpdev });
|
||||
var payload = { notification: { title: "MeshCentral", body: user.name + " authentication" }, data: { url: '2fa://auth?code=' + code + '&c=' + authCookie } };
|
||||
var options = { priority: 'High', timeToLive: 60 }; // TTL: 1 minute
|
||||
parent.firebase.sendToDevice(user.otpdev, payload, options, function (id, err, errdesc) {
|
||||
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); }
|
||||
});
|
||||
*/
|
||||
} else {
|
||||
// Ask for a login token
|
||||
parent.debug('web', 'Asking for login token');
|
||||
|
Loading…
Reference in New Issue
Block a user