Module dependency cleanup.
This commit is contained in:
parent
d63639fc62
commit
ac6c39dabe
|
@ -1606,23 +1606,16 @@ function InstallModules(modules, func) {
|
||||||
// Check if a module is present and install it if missing
|
// Check if a module is present and install it if missing
|
||||||
var InstallModuleChildProcess = null;
|
var InstallModuleChildProcess = null;
|
||||||
function InstallModule(modulename, func, tag1, tag2) {
|
function InstallModule(modulename, func, tag1, tag2) {
|
||||||
try {
|
console.log('Installing ' + modulename + '...');
|
||||||
var module = require(modulename);
|
var child_process = require('child_process');
|
||||||
} catch (e) {
|
|
||||||
console.log('Installing ' + modulename + '...');
|
|
||||||
var child_process = require('child_process');
|
|
||||||
|
|
||||||
// Looks like we need to keep a global reference to the child process object for this to work correctly.
|
|
||||||
InstallModuleChildProcess = child_process.exec('npm install ' + modulename + ' --no-optional --save', { maxBuffer: 512000, timeout: 10000 }, function (error, stdout, stderr) {
|
|
||||||
InstallModuleChildProcess = null;
|
|
||||||
if (error != null) { console.log('ERROR: Unable to install missing package \'' + modulename + '\', make sure npm is installed: ' + error); process.exit(); return; }
|
|
||||||
func(tag1, tag2);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// Looks like we need to keep a global reference to the child process object for this to work correctly.
|
||||||
|
InstallModuleChildProcess = child_process.exec('npm install ' + modulename + ' --no-optional --save', { maxBuffer: 512000, timeout: 10000 }, function (error, stdout, stderr) {
|
||||||
|
InstallModuleChildProcess = null;
|
||||||
|
if (error != null) { console.log('ERROR: Unable to install missing package \'' + modulename + '\', make sure npm is installed: ' + error); process.exit(); return; }
|
||||||
|
func(tag1, tag2);
|
||||||
return;
|
return;
|
||||||
}
|
});
|
||||||
func(tag1, tag2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect CTRL-C on Linux and stop nicely
|
// Detect CTRL-C on Linux and stop nicely
|
||||||
|
@ -1640,10 +1633,12 @@ function mainStart(args) {
|
||||||
var config = getConfig(false);
|
var config = getConfig(false);
|
||||||
if (config == null) { process.exit(); }
|
if (config == null) { process.exit(); }
|
||||||
|
|
||||||
// Check is Windows SSPI will be used
|
// Check is Windows SSPI and YubiKey OTP will be used
|
||||||
var sspi = false;
|
var sspi = false;
|
||||||
var allsspi = true;
|
var allsspi = true;
|
||||||
if (require('os').platform() == 'win32') { for (var i in config.domains) { if (config.domains[i].auth == 'sspi') { sspi = true; } else { allsspi = false; } } }
|
var yubikey = false;
|
||||||
|
if (require('os').platform() == 'win32') { for (var i in config.domains) { if (config.domains[i].auth == 'sspi') { sspi = true; } else { allsspi = false; } } } else { allsspi = false; }
|
||||||
|
for (var i in config.domains) { if (config.domains[i].yubikey != null) { yubikey = true; } }
|
||||||
|
|
||||||
// Build the list of required modules
|
// Build the list of required modules
|
||||||
var modules = ['ws', 'nedb', 'https', 'yauzl', 'xmldom', 'express', 'archiver', 'multiparty', 'node-forge', 'express-ws', 'compression', 'body-parser', 'connect-redis', 'express-handlebars'];
|
var modules = ['ws', 'nedb', 'https', 'yauzl', 'xmldom', 'express', 'archiver', 'multiparty', 'node-forge', 'express-ws', 'compression', 'body-parser', 'connect-redis', 'express-handlebars'];
|
||||||
|
@ -1651,6 +1646,7 @@ function mainStart(args) {
|
||||||
if (config.letsencrypt != null) { modules.push('greenlock'); modules.push('le-store-certbot'); modules.push('le-challenge-fs'); modules.push('le-acme-core'); } // Add Greenlock Modules
|
if (config.letsencrypt != null) { modules.push('greenlock'); modules.push('le-store-certbot'); modules.push('le-challenge-fs'); modules.push('le-acme-core'); } // Add Greenlock Modules
|
||||||
if (config.settings.mongodb != null) { modules.push('mongojs'); } // Add MongoDB
|
if (config.settings.mongodb != null) { modules.push('mongojs'); } // Add MongoDB
|
||||||
if (config.smtp != null) { modules.push('nodemailer'); } // Add SMTP support
|
if (config.smtp != null) { modules.push('nodemailer'); } // Add SMTP support
|
||||||
|
if (yubikey == true) { modules.push('yubikeyotp'); } // Add YubiKey OTP support
|
||||||
|
|
||||||
// Get the current node version
|
// Get the current node version
|
||||||
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
||||||
|
@ -1658,9 +1654,9 @@ function mainStart(args) {
|
||||||
// If running NodeJS < 8, install "util.promisify"
|
// If running NodeJS < 8, install "util.promisify"
|
||||||
if (nodeVersion < 8) { modules.push('util.promisify'); }
|
if (nodeVersion < 8) { modules.push('util.promisify'); }
|
||||||
|
|
||||||
// if running NodeJS 8 or higher, we can install WebAuthn/FIDO2 support
|
// if not all SSPI, WebAuthn/FIDO2 or U2F support depending on the NodeJS version. FIDO2 does not work below NodeJS 8.x
|
||||||
if ((nodeVersion >= 8) && (allsspi == false)) { modules.push('@davedoesdev/fido2-lib'); }
|
if (allsspi == false) { modules.push('otplib'); if (nodeVersion >= 8) { modules.push('@davedoesdev/fido2-lib'); } else { modules.push('authdog'); } }
|
||||||
|
|
||||||
// Install any missing modules and launch the server
|
// Install any missing modules and launch the server
|
||||||
InstallModules(modules, function () { meshserver = CreateMeshCentralServer(config, args); meshserver.Start(); });
|
InstallModules(modules, function () { meshserver = CreateMeshCentralServer(config, args); meshserver.Start(); });
|
||||||
});
|
});
|
||||||
|
@ -1670,4 +1666,4 @@ if (require.main === module) {
|
||||||
mainStart(require('minimist')(process.argv.slice(2))); // Called directly, launch normally.
|
mainStart(require('minimist')(process.argv.slice(2))); // Called directly, launch normally.
|
||||||
} else {
|
} else {
|
||||||
module.exports.mainStart = mainStart; // Required as a module, useful for winservice.js
|
module.exports.mainStart = mainStart; // Required as a module, useful for winservice.js
|
||||||
}
|
}
|
||||||
|
|
29
meshuser.js
29
meshuser.js
|
@ -1773,7 +1773,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
||||||
if (twoStepLoginSupported) {
|
if (twoStepLoginSupported) {
|
||||||
// Request a one time password to be setup
|
// Request a one time password to be setup
|
||||||
const otplib = require('otplib');
|
var otplib = null;
|
||||||
|
try { otplib = require('otplib'); } catch (ex) { }
|
||||||
|
if (otplib == null) { break; }
|
||||||
const secret = otplib.authenticator.generateSecret(); // TODO: Check the random source of this value.
|
const secret = otplib.authenticator.generateSecret(); // TODO: Check the random source of this value.
|
||||||
ws.send(JSON.stringify({ action: 'otpauth-request', secret: secret, url: otplib.authenticator.keyuri(user.name, parent.certificates.CommonName, secret) }));
|
ws.send(JSON.stringify({ action: 'otpauth-request', secret: secret, url: otplib.authenticator.keyuri(user.name, parent.certificates.CommonName, secret) }));
|
||||||
}
|
}
|
||||||
|
@ -1785,7 +1787,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
||||||
if (twoStepLoginSupported) {
|
if (twoStepLoginSupported) {
|
||||||
// Perform the one time password setup
|
// Perform the one time password setup
|
||||||
const otplib = require('otplib');
|
var otplib = null;
|
||||||
|
try { otplib = require('otplib'); } catch (ex) { }
|
||||||
|
if (otplib == null) { break; }
|
||||||
otplib.authenticator.options = { window: 2 }; // Set +/- 1 minute window
|
otplib.authenticator.options = { window: 2 }; // Set +/- 1 minute window
|
||||||
if (otplib.authenticator.check(command.token, command.secret) === true) {
|
if (otplib.authenticator.check(command.token, command.secret) === true) {
|
||||||
// Token is valid, activate 2-step login on this account.
|
// Token is valid, activate 2-step login on this account.
|
||||||
|
@ -1853,8 +1857,6 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
}
|
}
|
||||||
case 'otp-hkey-get':
|
case 'otp-hkey-get':
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
// Check is 2-step login is supported
|
// Check is 2-step login is supported
|
||||||
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
||||||
if (twoStepLoginSupported == false) break;
|
if (twoStepLoginSupported == false) break;
|
||||||
|
@ -1887,10 +1889,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
case 'otp-hkey-yubikey-add':
|
case 'otp-hkey-yubikey-add':
|
||||||
{
|
{
|
||||||
// Yubico API id and signature key can be requested from https://upgrade.yubico.com/getapikey/
|
// Yubico API id and signature key can be requested from https://upgrade.yubico.com/getapikey/
|
||||||
|
var yubikeyotp = null;
|
||||||
|
try { yubikeyotp = require('yubikeyotp'); } catch (ex) { }
|
||||||
|
|
||||||
// Check is 2-step login is supported
|
// Check is 2-step login is supported
|
||||||
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
||||||
if ((twoStepLoginSupported == false) || (typeof command.otp != 'string')) {
|
if ((yubikeyotp == null) || (twoStepLoginSupported == false) || (typeof command.otp != 'string')) {
|
||||||
ws.send(JSON.stringify({ action: 'otp-hkey-yubikey-add', result: false, name: command.name }));
|
ws.send(JSON.stringify({ action: 'otp-hkey-yubikey-add', result: false, name: command.name }));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1904,7 +1908,6 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
// TODO: Check if command.otp is modhex encoded, reject if not.
|
// TODO: Check if command.otp is modhex encoded, reject if not.
|
||||||
|
|
||||||
// Query the YubiKey server to validate the OTP
|
// Query the YubiKey server to validate the OTP
|
||||||
var yubikeyotp = require('yubikeyotp');
|
|
||||||
var request = { otp: command.otp, id: domain.yubikey.id, key: domain.yubikey.secret, timestamp: true }
|
var request = { otp: command.otp, id: domain.yubikey.id, key: domain.yubikey.secret, timestamp: true }
|
||||||
if (domain.yubikey.proxy) { request.requestParams = { proxy: domain.yubikey.proxy }; }
|
if (domain.yubikey.proxy) { request.requestParams = { proxy: domain.yubikey.proxy }; }
|
||||||
yubikeyotp.verifyOTP(request, function (err, results) {
|
yubikeyotp.verifyOTP(request, function (err, results) {
|
||||||
|
@ -1934,16 +1937,19 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
}
|
}
|
||||||
case 'otp-hkey-setup-request':
|
case 'otp-hkey-setup-request':
|
||||||
{
|
{
|
||||||
|
var authdoglib = null;
|
||||||
|
try { authdoglib = require('authdog'); } catch (ex) { }
|
||||||
|
|
||||||
// Check is 2-step login is supported
|
// Check is 2-step login is supported
|
||||||
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
||||||
if (twoStepLoginSupported == false) break;
|
if ((authdoglib == null) || (twoStepLoginSupported == false)) break;
|
||||||
|
|
||||||
// Build list of known keys
|
// Build list of known keys
|
||||||
var knownKeys = [];
|
var knownKeys = [];
|
||||||
if (user.otphkeys != null) { for (var i = 0; i < user.otphkeys.length; i++) { if (user.otphkeys[i].type == 1) { knownKeys.push(user.otphkeys[i]); } } }
|
if (user.otphkeys != null) { for (var i = 0; i < user.otphkeys.length; i++) { if (user.otphkeys[i].type == 1) { knownKeys.push(user.otphkeys[i]); } } }
|
||||||
|
|
||||||
// Build a key registration request and send it over
|
// Build a key registration request and send it over
|
||||||
require('authdog').startRegistration('https://' + parent.parent.certificates.CommonName, knownKeys, { requestId: 556, timeoutSeconds: 100 }).then(function (registrationRequest) {
|
authdoglib.startRegistration('https://' + parent.parent.certificates.CommonName, knownKeys, { requestId: 556, timeoutSeconds: 100 }).then(function (registrationRequest) {
|
||||||
// Save registration request to session for later use
|
// Save registration request to session for later use
|
||||||
obj.hardwareKeyRegistrationRequest = registrationRequest;
|
obj.hardwareKeyRegistrationRequest = registrationRequest;
|
||||||
|
|
||||||
|
@ -1957,12 +1963,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
}
|
}
|
||||||
case 'otp-hkey-setup-response':
|
case 'otp-hkey-setup-response':
|
||||||
{
|
{
|
||||||
|
var authdoglib = null;
|
||||||
|
try { authdoglib = require('authdog'); } catch (ex) { }
|
||||||
|
|
||||||
// Check is 2-step login is supported
|
// Check is 2-step login is supported
|
||||||
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
const twoStepLoginSupported = ((domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.lanonly !== true) && (args.nousers !== true));
|
||||||
if ((twoStepLoginSupported == false) || (command.response == null) || (command.name == null) || (obj.hardwareKeyRegistrationRequest == null)) break;
|
if ((authdoglib == null) || (twoStepLoginSupported == false) || (command.response == null) || (command.name == null) || (obj.hardwareKeyRegistrationRequest == null)) break;
|
||||||
|
|
||||||
// Check the key registration request
|
// Check the key registration request
|
||||||
require('authdog').finishRegistration(obj.hardwareKeyRegistrationRequest, command.response).then(function (registrationStatus) {
|
authdoglib.finishRegistration(obj.hardwareKeyRegistrationRequest, command.response).then(function (registrationStatus) {
|
||||||
var keyIndex = parent.crypto.randomBytes(4).readUInt32BE(0);
|
var keyIndex = parent.crypto.randomBytes(4).readUInt32BE(0);
|
||||||
ws.send(JSON.stringify({ action: 'otp-hkey-setup-response', result: true, name: command.name, index: keyIndex }));
|
ws.send(JSON.stringify({ action: 'otp-hkey-setup-response', result: true, name: command.name, index: keyIndex }));
|
||||||
if (user.otphkeys == null) { user.otphkeys = []; }
|
if (user.otphkeys == null) { user.otphkeys = []; }
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
{
|
||||||
|
"name": "meshcentral",
|
||||||
|
"version": "0.3.0-x",
|
||||||
|
"keywords": [
|
||||||
|
"Remote Management",
|
||||||
|
"Intel AMT",
|
||||||
|
"Active Management",
|
||||||
|
"Remote Desktop"
|
||||||
|
],
|
||||||
|
"homepage": "http://meshcommander.com",
|
||||||
|
"description": "Web based remote computer management and file server",
|
||||||
|
"author": "Ylian Saint-Hilaire <ysainthilaire@hotmail.com>",
|
||||||
|
"main": "meshcentral.js",
|
||||||
|
"bin": {
|
||||||
|
"meshcentral": "./bin/meshcentral"
|
||||||
|
},
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"files": [
|
||||||
|
"*.js",
|
||||||
|
"sample-config.json",
|
||||||
|
"license.txt",
|
||||||
|
"readme.txt",
|
||||||
|
"agents",
|
||||||
|
"public",
|
||||||
|
"views",
|
||||||
|
"bin"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"archiver": "^3.0.0",
|
||||||
|
"authdog": "^0.1.1",
|
||||||
|
"body-parser": "^1.18.2",
|
||||||
|
"compression": "^1.7.3",
|
||||||
|
"connect-redis": "^3.4.0",
|
||||||
|
"cookie-session": "^2.0.0-beta.3",
|
||||||
|
"express": "^4.16.4",
|
||||||
|
"express-handlebars": "^3.0.0",
|
||||||
|
"express-ws": "^4.0.0",
|
||||||
|
"ipcheck": "^0.1.0",
|
||||||
|
"meshcentral": "*",
|
||||||
|
"minimist": "^1.2.0",
|
||||||
|
"mongojs": "^2.6.0",
|
||||||
|
"multiparty": "^4.2.1",
|
||||||
|
"nedb": "^1.8.0",
|
||||||
|
"node-forge": "^0.7.6",
|
||||||
|
"otplib": "^10.0.1",
|
||||||
|
"ws": "^6.1.2",
|
||||||
|
"xmldom": "^0.1.27",
|
||||||
|
"yauzl": "^2.10.0",
|
||||||
|
"yubikeyotp": "^0.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Ylianst/MeshCentral.git"
|
||||||
|
},
|
||||||
|
"readme": "readme.txt"
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.3.0-u",
|
"version": "0.3.0-y",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
@ -27,7 +27,6 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"archiver": "^3.0.0",
|
"archiver": "^3.0.0",
|
||||||
"authdog": "^0.1.1",
|
|
||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.18.2",
|
||||||
"compression": "^1.7.3",
|
"compression": "^1.7.3",
|
||||||
"connect-redis": "^3.4.0",
|
"connect-redis": "^3.4.0",
|
||||||
|
@ -41,11 +40,9 @@
|
||||||
"multiparty": "^4.2.1",
|
"multiparty": "^4.2.1",
|
||||||
"nedb": "^1.8.0",
|
"nedb": "^1.8.0",
|
||||||
"node-forge": "^0.7.6",
|
"node-forge": "^0.7.6",
|
||||||
"otplib": "^10.0.1",
|
|
||||||
"ws": "^6.1.2",
|
"ws": "^6.1.2",
|
||||||
"xmldom": "^0.1.27",
|
"xmldom": "^0.1.27",
|
||||||
"yauzl": "^2.10.0",
|
"yauzl": "^2.10.0"
|
||||||
"yubikeyotp": "^0.2.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
npm install archiver authdog body-parser compression connect-redis cookie-session express express-handlebars express-ws ipcheck minimist mongojs multiparty nedb node-forge otplib ws xmldom yauzl yubikeyotp
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -287,7 +287,34 @@
|
||||||
|
|
||||||
if ('{{loginmode}}' == '4') {
|
if ('{{loginmode}}' == '4') {
|
||||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||||
if ((hardwareKeyChallenge != null) && u2fSupported()) {
|
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||||
|
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), c => c.charCodeAt(0)).buffer;
|
||||||
|
|
||||||
|
const 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]), c => 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); }
|
||||||
|
);
|
||||||
|
} else if ((hardwareKeyChallenge != null) && u2fSupported()) {
|
||||||
|
// Old U2F hardware keys
|
||||||
window.u2f.sign(hardwareKeyChallenge.appId, hardwareKeyChallenge.challenge, hardwareKeyChallenge.registeredKeys, function (authResponse) {
|
window.u2f.sign(hardwareKeyChallenge.appId, hardwareKeyChallenge.challenge, hardwareKeyChallenge.registeredKeys, function (authResponse) {
|
||||||
if ((currentpanel == 4) && authResponse.signatureData) {
|
if ((currentpanel == 4) && authResponse.signatureData) {
|
||||||
Q('hwtokenInput').value = JSON.stringify(authResponse);
|
Q('hwtokenInput').value = JSON.stringify(authResponse);
|
||||||
|
@ -300,7 +327,34 @@
|
||||||
|
|
||||||
if ('{{loginmode}}' == '5') {
|
if ('{{loginmode}}' == '5') {
|
||||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||||
if ((hardwareKeyChallenge != null) && u2fSupported()) {
|
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||||
|
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), c => c.charCodeAt(0)).buffer;
|
||||||
|
|
||||||
|
const 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]), c => 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('resetHwtokenInput').value = JSON.stringify(assertion);
|
||||||
|
QE('resetTokenOkButton', true);
|
||||||
|
Q('resetTokenOkButton').click();
|
||||||
|
},
|
||||||
|
function (error) { console.log('credentials-get error', error); }
|
||||||
|
);
|
||||||
|
} else if ((hardwareKeyChallenge != null) && u2fSupported()) {
|
||||||
|
// Old U2F hardware keys
|
||||||
window.u2f.sign(hardwareKeyChallenge.appId, hardwareKeyChallenge.challenge, hardwareKeyChallenge.registeredKeys, function (authResponse) {
|
window.u2f.sign(hardwareKeyChallenge.appId, hardwareKeyChallenge.challenge, hardwareKeyChallenge.registeredKeys, function (authResponse) {
|
||||||
if ((currentpanel == 5) && authResponse.signatureData) {
|
if ((currentpanel == 5) && authResponse.signatureData) {
|
||||||
Q('resetHwtokenInput').value = JSON.stringify(authResponse);
|
Q('resetHwtokenInput').value = JSON.stringify(authResponse);
|
||||||
|
|
|
@ -386,11 +386,11 @@
|
||||||
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
|
||||||
function (rawAssertion) {
|
function (rawAssertion) {
|
||||||
var assertion = {
|
var assertion = {
|
||||||
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))), //base64encode(rawAssertion.rawId),
|
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
|
||||||
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))), //arrayBufferToString(rawAssertion.response.clientDataJSON),
|
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
|
||||||
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))), //base64encode(rawAssertion.response.userHandle),
|
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
|
||||||
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))), //base64encode(rawAssertion.response.signature),
|
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
|
||||||
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))), //base64encode(rawAssertion.response.authenticatorData)
|
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
|
||||||
};
|
};
|
||||||
Q('hwtokenInput').value = JSON.stringify(assertion);
|
Q('hwtokenInput').value = JSON.stringify(assertion);
|
||||||
QE('tokenOkButton', true);
|
QE('tokenOkButton', true);
|
||||||
|
@ -412,7 +412,34 @@
|
||||||
|
|
||||||
if ('{{loginmode}}' == '5') {
|
if ('{{loginmode}}' == '5') {
|
||||||
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
|
||||||
if ((hardwareKeyChallenge != null) && u2fSupported()) {
|
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
|
||||||
|
hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), c => c.charCodeAt(0)).buffer;
|
||||||
|
|
||||||
|
const 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]), c => 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('resetHwtokenInput').value = JSON.stringify(assertion);
|
||||||
|
QE('resetTokenOkButton', true);
|
||||||
|
Q('resetTokenOkButton').click();
|
||||||
|
},
|
||||||
|
function (error) { console.log('credentials-get error', error); }
|
||||||
|
);
|
||||||
|
} else if ((hardwareKeyChallenge != null) && u2fSupported()) {
|
||||||
|
// Old U2F hardware keys
|
||||||
window.u2f.sign(hardwareKeyChallenge.appId, hardwareKeyChallenge.challenge, hardwareKeyChallenge.registeredKeys, function (authResponse) {
|
window.u2f.sign(hardwareKeyChallenge.appId, hardwareKeyChallenge.challenge, hardwareKeyChallenge.registeredKeys, function (authResponse) {
|
||||||
if ((currentpanel == 5) && authResponse.signatureData) {
|
if ((currentpanel == 5) && authResponse.signatureData) {
|
||||||
Q('resetHwtokenInput').value = JSON.stringify(authResponse);
|
Q('resetHwtokenInput').value = JSON.stringify(authResponse);
|
||||||
|
|
|
@ -62,7 +62,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
const constants = (obj.crypto.constants ? obj.crypto.constants : require('constants')); // require('constants') is deprecated in Node 11.10, use require('crypto').constants instead.
|
const constants = (obj.crypto.constants ? obj.crypto.constants : require('constants')); // require('constants') is deprecated in Node 11.10, use require('crypto').constants instead.
|
||||||
|
|
||||||
// Setup WebAuthn / FIDO2
|
// Setup WebAuthn / FIDO2
|
||||||
try { const { Fido2Lib } = require("@davedoesdev/fido2-lib"); obj.f2l = new Fido2Lib({ attestation: "none" }); } catch (ex) { console.log(ex); }
|
try { const { Fido2Lib } = require("@davedoesdev/fido2-lib"); obj.f2l = new Fido2Lib({ attestation: "none" }); } catch (ex) { }
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
obj.parent = parent;
|
obj.parent = parent;
|
||||||
|
|
Loading…
Reference in New Issue