mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-09-11 08:55:32 +03:00
Added remember for 30 days 2nd factor option.
This commit is contained in:
parent
664eb63c63
commit
3670f229b9
@ -778,7 +778,7 @@ function performAmtAgentPresenceAssert() {
|
||||
// Called after the agent is asserted
|
||||
function performAmtAgentPresenceAssertRetry(stack, name, response, status, watchdog) {
|
||||
if (status == 200) {
|
||||
debug(1, 'Succesful assert, sequence = ' + watchdog.Seq);
|
||||
debug(1, 'Successful assert, sequence = ' + watchdog.Seq);
|
||||
watchdog.Retry = 0;
|
||||
tempWatchdogTimer = setTimeout(performAmtAgentPresenceAssert, watchdog.Interval);
|
||||
} else {
|
||||
|
2
agents/meshcmd.min.js
vendored
2
agents/meshcmd.min.js
vendored
@ -778,7 +778,7 @@ function performAmtAgentPresenceAssert() {
|
||||
// Called after the agent is asserted
|
||||
function performAmtAgentPresenceAssertRetry(stack, name, response, status, watchdog) {
|
||||
if (status == 200) {
|
||||
debug(1, 'Succesful assert, sequence = ' + watchdog.Seq);
|
||||
debug(1, 'Successful assert, sequence = ' + watchdog.Seq);
|
||||
watchdog.Retry = 0;
|
||||
tempWatchdogTimer = setTimeout(performAmtAgentPresenceAssert, watchdog.Interval);
|
||||
} else {
|
||||
|
@ -326,7 +326,7 @@ module.exports.CreateRedirInterceptor = function (args) {
|
||||
obj.amt.digestQOP = obj.amt.acc.substring(12 + realmlen + noncelen, 12 + realmlen + noncelen + qoplen);
|
||||
}
|
||||
else if (authType != obj.AuthenticationType.QUERY && authstatus == obj.AuthenticationStatus.SUCCESS) {
|
||||
// Intel AMT relayed that authentication was succesful, go to direct relay mode in both directions.
|
||||
// Intel AMT relayed that authentication was successful, go to direct relay mode in both directions.
|
||||
obj.ws.direct = true;
|
||||
obj.amt.direct = true;
|
||||
}
|
||||
|
@ -864,7 +864,7 @@
|
||||
if (message.keys && message.keys.length > 0) {
|
||||
for (var i in message.keys) {
|
||||
var key = message.keys[i], type = (key.type == 2)?'OTP':'WebAuthn';
|
||||
x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Remove" + '" onclick=account_removehkey(" + key.i + ")></input>' + end;
|
||||
x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Remove" + '" onclick=account_removehkey(' + key.i + ')></input>' + end;
|
||||
}
|
||||
} else {
|
||||
x += start + '<tr style=text-align:center><td>' + "No Keys Configured" + end;
|
||||
|
@ -1888,7 +1888,7 @@
|
||||
if (message.keys && message.keys.length > 0) {
|
||||
for (var i in message.keys) {
|
||||
var key = message.keys[i], type = (key.type == 2)?'OTP':'WebAuthn';
|
||||
x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Remove" + '" onclick=account_removehkey(" + key.i + ")></input>' + end;
|
||||
x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Remove" + '" onclick=account_removehkey(' + key.i + ')></input>' + end;
|
||||
}
|
||||
} else {
|
||||
x += start + '<tr style=text-align:center><td>' + "No Keys Configured" + end;
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -156,9 +156,15 @@
|
||||
<input id=hwtokenInput type=text name=hwtoken style="display:none" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="align-content:center">
|
||||
<label><input id=tokenInputRemember name=remembertoken type=checkbox />Remember this device for 30 days.</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2>
|
||||
<div style=float:right><input id=tokenOkButton type=submit value="Login" disabled="disabled" /></div>
|
||||
<div style=float:right><input style="display:none;float:right" id=securityKeyButton type=button value="Use Security Key" onclick="useSecurityKey()" /></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -265,6 +271,7 @@
|
||||
if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
|
||||
var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
|
||||
var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
|
||||
var publicKeyCredentialRequestOptions = null;
|
||||
var currentpanel = 0;
|
||||
|
||||
// Display the right server message
|
||||
@ -322,41 +329,15 @@
|
||||
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
|
||||
var publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
|
||||
}
|
||||
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
|
||||
|
||||
var publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
@ -383,6 +364,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Use a hardware security key
|
||||
function useSecurityKey() {
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
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 }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function showPassHint() {
|
||||
if (passRequirements.hint === true) { messagebox("Password Hint", passhint); }
|
||||
}
|
||||
|
@ -147,13 +147,19 @@
|
||||
<tr>
|
||||
<td align=right width=100>Login token:</td>
|
||||
<td>
|
||||
<input id=tokenInput type=text name=token maxlength=50 onchange=checkToken(event) onpaste=resetCheckToken(event) onkeyup=checkToken(event) onkeydown=checkToken(event) />
|
||||
<input id=tokenInput type=text name=token maxlength=50 onchange=checkToken(event) onpaste=resetCheckToken(event) onkeyup=checkToken(event) onkeydown=checkToken(event) /><br />
|
||||
<input id=hwtokenInput type=text name=hwtoken style="display:none" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="align-content:center">
|
||||
<label><input id=tokenInputRemember name=remembertoken type=checkbox />Remember this device for 30 days.</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2>
|
||||
<div style=float:right><input id=tokenOkButton type=submit value="Login" disabled="disabled" /></div>
|
||||
<div style=float:right><input style="display:none;float:right" id=securityKeyButton type=button value="Use Security Key" onclick="useSecurityKey()" /></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -331,39 +337,13 @@
|
||||
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
|
||||
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
|
||||
}
|
||||
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
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 }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
@ -395,6 +375,37 @@
|
||||
userInterfaceSelectMenu();
|
||||
}
|
||||
|
||||
// Use a hardware security key
|
||||
function useSecurityKey() {
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
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 }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function showPassHint(e) {
|
||||
messagebox("Password Hint", passhint);
|
||||
haltEvent(e);
|
||||
|
@ -864,7 +864,7 @@
|
||||
if (message.keys && message.keys.length > 0) {
|
||||
for (var i in message.keys) {
|
||||
var key = message.keys[i], type = (key.type == 2)?'OTP':'WebAuthn';
|
||||
x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Retirer" + '" onclick=account_removehkey(" + key.i + ")></input>' + end;
|
||||
x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Retirer" + '" onclick=account_removehkey(' + key.i + ')></input>' + end;
|
||||
}
|
||||
} else {
|
||||
x += start + '<tr style=text-align:center><td>' + "No Keys Configured" + end;
|
||||
|
@ -1886,7 +1886,7 @@
|
||||
if (message.keys && message.keys.length > 0) {
|
||||
for (var i in message.keys) {
|
||||
var key = message.keys[i], type = (key.type == 2)?'OTP':'WebAuthn';
|
||||
x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Retirer" + '" onclick=account_removehkey(" + key.i + ")></input>' + end;
|
||||
x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Retirer" + '" onclick=account_removehkey(' + key.i + ')></input>' + end;
|
||||
}
|
||||
} else {
|
||||
x += start + '<tr style=text-align:center><td>' + "No Keys Configured" + end;
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -154,9 +154,15 @@
|
||||
<input id="hwtokenInput" type="text" name="hwtoken" style="display:none">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="align-content:center">
|
||||
<label><input id="tokenInputRemember" name="remembertoken" type="checkbox">Remember this device for 30 days.</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="tokenOkButton" type="submit" value="Login" disabled="disabled"></div>
|
||||
<div style="float:right"><input style="display:none;float:right" id="securityKeyButton" type="button" value="Use Security Key" onclick="useSecurityKey()"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
@ -263,6 +269,7 @@
|
||||
if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
|
||||
var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
|
||||
var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
|
||||
var publicKeyCredentialRequestOptions = null;
|
||||
var currentpanel = 0;
|
||||
|
||||
// Display the right server message
|
||||
@ -320,41 +327,15 @@
|
||||
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
|
||||
var publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
|
||||
}
|
||||
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
|
||||
|
||||
var publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
@ -381,6 +362,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Use a hardware security key
|
||||
function useSecurityKey() {
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
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 }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function showPassHint() {
|
||||
if (passRequirements.hint === true) { messagebox("Password Hint", passhint); }
|
||||
}
|
||||
|
@ -145,13 +145,19 @@
|
||||
<tbody><tr>
|
||||
<td align="right" width="100">Login token:</td>
|
||||
<td>
|
||||
<input id="tokenInput" type="text" name="token" maxlength="50" onchange="checkToken(event)" onpaste="resetCheckToken(event)" onkeyup="checkToken(event)" onkeydown="checkToken(event)">
|
||||
<input id="tokenInput" type="text" name="token" maxlength="50" onchange="checkToken(event)" onpaste="resetCheckToken(event)" onkeyup="checkToken(event)" onkeydown="checkToken(event)"><br>
|
||||
<input id="hwtokenInput" type="text" name="hwtoken" style="display:none">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="align-content:center">
|
||||
<label><input id="tokenInputRemember" name="remembertoken" type="checkbox">Remember this device for 30 days.</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="float:right"><input id="tokenOkButton" type="submit" value="Login" disabled="disabled"></div>
|
||||
<div style="float:right"><input style="display:none;float:right" id="securityKeyButton" type="button" value="Use Security Key" onclick="useSecurityKey()"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
@ -329,39 +335,13 @@
|
||||
|
||||
if (loginMode == '4') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
|
||||
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
|
||||
}
|
||||
|
||||
if (loginMode == '5') {
|
||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer;
|
||||
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 }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
@ -393,6 +373,37 @@
|
||||
userInterfaceSelectMenu();
|
||||
}
|
||||
|
||||
// Use a hardware security key
|
||||
function useSecurityKey() {
|
||||
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||
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 }
|
||||
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
|
||||
publicKeyCredentialRequestOptions.allowCredentials.push(
|
||||
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
|
||||
);
|
||||
}
|
||||
|
||||
// New WebAuthn hardware keys
|
||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||
function (rawAssertion) {
|
||||
var assertion = {
|
||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||
};
|
||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||
QE('tokenOkButton', true);
|
||||
Q('tokenOkButton').click();
|
||||
},
|
||||
function (error) { console.log('credentials-get error', error); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function showPassHint(e) {
|
||||
messagebox("Password Hint", passhint);
|
||||
haltEvent(e);
|
||||
|
30
webserver.js
30
webserver.js
@ -516,6 +516,18 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if ((req != null) && (req.ip != null) && (domain.passwordrequirements != null) && (domain.passwordrequirements.skip2factor != null)) {
|
||||
for (var i in domain.passwordrequirements.skip2factor) { if (require('ipcheck').match(req.ip, domain.passwordrequirements.skip2factor[i]) === true) return false; }
|
||||
}
|
||||
|
||||
// Check if a 2nd factor cookie is present
|
||||
if (typeof req.headers.cookie == 'string') {
|
||||
const cookies = req.headers.cookie.split('; ');
|
||||
for (var i in cookies) {
|
||||
if (cookies[i].startsWith('twofactor=')) {
|
||||
var twoFactorCookie = obj.parent.decodeCookie(decodeURIComponent(cookies[i].substring(10)), obj.parent.loginCookieEncryptionKey, (30 * 24 * 60)); // 30 day timeout
|
||||
if ((twoFactorCookie != null) && ((twoFactorCookie.ip == null) || (twoFactorCookie.ip === cleanRemoteAddr(req.ip))) && (twoFactorCookie.userid == user._id)) { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a 2nd factor is present
|
||||
return ((parent.config.settings.no2factorauth !== true) && ((user.otpsecret != null) || ((user.otphkeys != null) && (user.otphkeys.length > 0))));
|
||||
}
|
||||
@ -686,16 +698,22 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); }
|
||||
}, randomWaitTime);
|
||||
} else {
|
||||
// Login succesful
|
||||
parent.debug('web', 'handleLoginRequest: succesful 2FA login');
|
||||
// Check if we need to remember this device
|
||||
if (req.body.remembertoken === 'on') {
|
||||
const twoFactorCookie = obj.parent.encodeCookie({ userid: user._id /*, ip: cleanRemoteAddr(req.ip)*/ }, obj.parent.loginCookieEncryptionKey);
|
||||
res.cookie('twofactor', twoFactorCookie, { maxAge: (30 * 24 * 60 * 60 * 1000), httpOnly: true, sameSite: 'strict', secure: true });
|
||||
}
|
||||
|
||||
// Login successful
|
||||
parent.debug('web', 'handleLoginRequest: successful 2FA login');
|
||||
completeLoginRequest(req, res, domain, user, userid, xusername, xpassword, direct);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Login succesful
|
||||
parent.debug('web', 'handleLoginRequest: succesful login');
|
||||
// Login successful
|
||||
parent.debug('web', 'handleLoginRequest: successful login');
|
||||
completeLoginRequest(req, res, domain, user, userid, xusername, xpassword, direct);
|
||||
} else {
|
||||
// Login failed, wait a random delay
|
||||
@ -959,7 +977,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (obj.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
|
||||
obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, event);
|
||||
|
||||
// Login succesful
|
||||
// Login successful
|
||||
parent.debug('web', 'handleResetPasswordRequest: success');
|
||||
req.session.userid = userid;
|
||||
req.session.domainid = domain.id;
|
||||
@ -2570,7 +2588,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
var amtpassword = ((mesh.amt.password == '') ? getRandomAmtPassword() : mesh.amt.password);
|
||||
if (checkAmtPassword(amtpassword) == false) { ws.send(JSON.stringify({ errorText: 'Invalid Intel AMT password' })); ws.close(); return; } // Invalid Intel AMT password, this should never happen.
|
||||
|
||||
// Save some state, if activation is succesful, we need this to add the device
|
||||
// Save some state, if activation is successful, we need this to add the device
|
||||
ws.xxstate = { uuid: cmd.uuid, realm: cmd.realm, tag: cmd.tag, name: cmd.name, hostname: cmd.hostname, pass: amtpassword, flags: activationMode, ver: cmd.ver, sku: cmd.sku }; // Flags: 2 = CCM, 4 = ACM
|
||||
|
||||
if (activationMode == 4) {
|
||||
|
Loading…
Reference in New Issue
Block a user