@ideem/zsm-client-sdk 2.4.1 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -6
- package/EventCoordinator.js +267 -0
- package/FIDO2Client.js +15 -0
- package/FIDO2ClientBase.js +117 -0
- package/GlobalScoping.js +8 -0
- package/IdentityIndexing.js +51 -0
- package/PluginManager.js +111 -0
- package/RelyingParty.js +15 -0
- package/RelyingPartyBase.js +197 -0
- package/UMFAClient.js +15 -0
- package/UMFAClientBase.js +125 -0
- package/Utils.js +44 -0
- package/WASMRustInterface.js +1458 -0
- package/WebAuthnClient.js +29 -0
- package/WebAuthnClientBase.js +429 -0
- package/ZSMClientSDK.js +28 -485
- package/package.json +19 -50
- package/shims/VanillaJSLoader.js +96 -0
- package/shims/es-module-shims.js +1067 -0
- package/worker.js +0 -2508
package/ZSMClientSDK.js
CHANGED
|
@@ -1,495 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class WorkerError extends Error {
|
|
10
|
-
constructor(name, message, ...details) {
|
|
11
|
-
super(message);
|
|
12
|
-
this.name = name ? `Worker ${name} Error` : 'Worker Error';
|
|
13
|
-
if (details.length) this.details = details;
|
|
14
|
-
if (Error.captureStackTrace) {
|
|
15
|
-
Error.captureStackTrace(this, WorkerError);
|
|
16
|
-
} else {
|
|
17
|
-
this.stack = (new Error(message)).stack;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
class ZSMClientBase {
|
|
23
|
-
constructor(config) {
|
|
24
|
-
GLOBAL.zsmClient = null;
|
|
25
|
-
this.clientWorker = null;
|
|
26
|
-
this.timeoutTimer = null;
|
|
27
|
-
this.clientType = null;
|
|
28
|
-
this.ready = false;
|
|
29
|
-
this.config = config;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
onReady(onReadyFn=null) {
|
|
33
|
-
return new Promise((resolve) => {
|
|
34
|
-
if(this.ready) return resolve(true);
|
|
35
|
-
window.addEventListener(`${this.clientType}Ready`, async (e) => {
|
|
36
|
-
this.ready = true;
|
|
37
|
-
if(onReadyFn) await onReadyFn?.();
|
|
38
|
-
resolve(this);
|
|
39
|
-
}, { once: true });
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @name init
|
|
45
|
-
* @description Initializes the ZSMClient instance and sets up the worker.
|
|
46
|
-
* @param {String} clientType The type of client to initialize [default: 'UMFAClient']
|
|
47
|
-
* @param {Object} config The configuration object for the client [default: this.config]
|
|
48
|
-
* @returns {Promise<ZSMClientBase>} A promise that resolves to the initialized ZSMClient instance.
|
|
49
|
-
*/
|
|
50
|
-
async init(clientType='UMFAClient', config=this.config) {
|
|
51
|
-
this.onReady();
|
|
52
|
-
this.ready = false;
|
|
53
|
-
this.clientType = clientType;
|
|
54
|
-
|
|
55
|
-
const workerPath = GLOBAL?.workerPath ? GLOBAL.workerPath
|
|
56
|
-
: config?.workerPath ? config.workerPath
|
|
57
|
-
: './worker.js';
|
|
58
|
-
const pathResolver = (import.meta && import.meta?.resolve) ? import.meta?.resolve(workerPath)
|
|
59
|
-
: (import.meta && import.meta?.url) ? import.meta?.url.replace(/\/[^\/]+$/, '/' + workerPath)
|
|
60
|
-
: document?.currentScript ? document?.currentScript?.src?.replace(/\/[^\/]+$/, '/' + workerPath)
|
|
61
|
-
: workerPath;
|
|
62
|
-
GLOBAL.clientWorker = this.clientWorker = new Worker(new URL(pathResolver));
|
|
63
|
-
GLOBAL.zsmClient = this;
|
|
64
|
-
await this.callWorkerFunction("init", {config, clientType}, false);
|
|
65
|
-
return this;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @name callWorkerFunction
|
|
70
|
-
* @description Calls a function in the worker and returns a promise that resolves with the result.
|
|
71
|
-
* @param {String} functionName The name of the function to call in the worker.
|
|
72
|
-
* @param {Object} data The data to pass to the worker function.
|
|
73
|
-
* @param {Boolean} responseExpected Whether an acknowledgement is expected [Default: true]
|
|
74
|
-
* @returns {Promise<Object>} A promise that resolves with the result of the worker function.
|
|
75
|
-
*/
|
|
76
|
-
async callWorkerFunction(functionName, data, responseExpected=true) {
|
|
77
|
-
if (functionName !== 'init' && !this.ready) await this.onReady();
|
|
78
|
-
if(!this.clientWorker) {
|
|
79
|
-
console.error('Worker not initialized. Please call init() before using this method.');
|
|
80
|
-
return Promise.reject(new WorkerError('Worker', 'Worker not initialized. Please call init() before using this method.'));
|
|
81
|
-
}
|
|
82
|
-
let workerPromise = new Promise((resolve, reject) => {
|
|
83
|
-
this.clientWorker.postMessage({functionName, data });
|
|
84
|
-
if(responseExpected) this.timeoutTimer = GLOBAL.setTimeout(() => reject(new WorkerError('Transaction', 'Transaction timed out after 60 seconds!')), 60000);
|
|
85
|
-
|
|
86
|
-
this.clientWorker.onmessage = (event) => {
|
|
87
|
-
GLOBAL.clearTimeout(this.timeoutTimer);
|
|
88
|
-
|
|
89
|
-
let workerResponse = event.data;
|
|
90
|
-
|
|
91
|
-
if((GLOBAL.showWorkerTelemetry) && (workerResponse.result || workerResponse.error)) {
|
|
92
|
-
console.groupCollapsed(`%cWorker posted to Main Thread a response to invocation:`, 'font-weight:bold; color:#F60;', functionName)
|
|
93
|
-
console.log(`%c Function Invoked:`, 'font-weight:100; color:#AAA;', workerResponse.functionName);
|
|
94
|
-
console.log(`%c Success Status:`, 'font-weight:100; color:#AAA;', workerResponse.success ? 'true' : 'false');
|
|
95
|
-
console.log(`%c Result value:`, 'font-weight:100; color:#AAA;', (workerResponse.success ? workerResponse.result : workerResponse.error));
|
|
96
|
-
console.log(`%c Response Object:`, 'font-weight:100; color:#AAA;', workerResponse);
|
|
97
|
-
console.groupEnd();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (workerResponse instanceof Error || workerResponse.error || !workerResponse.success) {
|
|
101
|
-
return reject(workerResponse.error);
|
|
102
|
-
}
|
|
103
|
-
resolve(workerResponse.result);
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
this.clientWorker.onerror = (err) => { GLOBAL.clearTimeout(this.timeoutTimer); reject(new WorkerError('', err.message)); };
|
|
107
|
-
this.clientWorker.onmessageerror = (err) => { GLOBAL.clearTimeout(this.timeoutTimer); reject(new WorkerError('Message', err.message)); };
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* @event workerEvent
|
|
112
|
-
* @description Event triggered when the worker posts an event to the main thread.
|
|
113
|
-
* @param {String} eventName The name of the event.
|
|
114
|
-
* @param {Object} eventData The data associated with the event.
|
|
115
|
-
* @returns {void}
|
|
116
|
-
* @emits {CustomEvent} event The event object containing the received event name and data.
|
|
117
|
-
* @example GLOBAL.addEventListener('workerEvent', (event) => {
|
|
118
|
-
* @ console.log('Received event from worker:', event.detail.eventName, event.detail.eventData);
|
|
119
|
-
* @ });
|
|
120
|
-
*/
|
|
121
|
-
this.clientWorker.addEventListener('message', (event) => {
|
|
122
|
-
if(!event.data || !event.data.eventName) return;
|
|
123
|
-
const { eventName, eventData } = event.data;
|
|
124
|
-
if(GLOBAL.showWorkerTelemetry) console.log(`%cWorker posted to Main Thread an event:`, 'font-weight:bold; color:#F60;', eventName, eventData);
|
|
125
|
-
GLOBAL.dispatchEvent(new CustomEvent(eventName, { detail: eventData }));
|
|
126
|
-
});
|
|
127
|
-
return workerPromise;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
class UMFAClient extends ZSMClientBase {
|
|
1
|
+
import eventCoordinator from './EventCoordinator.js';
|
|
2
|
+
import {UMFAClient as UMFAClientCore} from './UMFAClient.js';
|
|
3
|
+
import {FIDO2Client as FIDO2ClientCore} from './FIDO2Client.js';
|
|
4
|
+
import RelyingParty from './RelyingParty.js';
|
|
5
|
+
import WebAuthnClient from './WebAuthnClient.js';
|
|
6
|
+
import {zsmPluginManager} from './PluginManager.js';
|
|
7
|
+
|
|
8
|
+
class UMFAClient {
|
|
132
9
|
constructor(config) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
this.checkEnrollment = this.checkEnrollment.bind(this);
|
|
139
|
-
this.enroll = this.enroll.bind(this);
|
|
140
|
-
this.authenticate = this.authenticate.bind(this);
|
|
141
|
-
this.unenroll = this.unenroll.bind(this);
|
|
142
|
-
this.init('UMFAClient');
|
|
10
|
+
zsmPluginManager.freezePlugins();
|
|
11
|
+
const UMFAClientClass = zsmPluginManager.classes('UMFAClient');
|
|
12
|
+
const umfaInstance = new UMFAClientClass(config);
|
|
13
|
+
eventCoordinator.setCoreSDKClass('UMFAClient', umfaInstance);
|
|
14
|
+
return umfaInstance;
|
|
143
15
|
}
|
|
144
|
-
|
|
145
|
-
checkEnrollment(user) { return this.callWorkerFunction('checkEnrollment', user); }
|
|
146
|
-
enroll(user) { return this.callWorkerFunction('enroll', user); }
|
|
147
|
-
authenticate(user) { return this.callWorkerFunction('authenticate', user); }
|
|
148
|
-
unenroll(user) { return this.callWorkerFunction('unenroll', user); }
|
|
149
16
|
}
|
|
150
17
|
|
|
151
|
-
class FIDO2Client
|
|
18
|
+
class FIDO2Client {
|
|
152
19
|
constructor(config) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.checkIdentity = this.checkIdentity.bind(this);
|
|
159
|
-
this.checkEnrollment = this.checkEnrollment.bind(this);
|
|
160
|
-
this.webauthnCreate = this.webauthnCreate.bind(this);
|
|
161
|
-
this.webauthnGet = this.webauthnGet.bind(this);
|
|
162
|
-
this.webauthnRetrieve = this.webauthnRetrieve.bind(this);
|
|
163
|
-
this.webauthnDelete = this.webauthnDelete.bind(this);
|
|
164
|
-
this.init('FIDO2Client');
|
|
20
|
+
zsmPluginManager.freezePlugins();
|
|
21
|
+
const FIDO2ClientClass = zsmPluginManager.classes('FIDO2Client');
|
|
22
|
+
const fido2Instance = new FIDO2ClientClass(config);
|
|
23
|
+
eventCoordinator.setCoreSDKClass('FIDO2Client', fido2Instance);
|
|
24
|
+
return fido2Instance;
|
|
165
25
|
}
|
|
166
|
-
|
|
167
|
-
checkIdentity = (user, auto=true) => this.callWorkerFunction('checkIdentity', [user, auto]);
|
|
168
|
-
checkEnrollment = (user) => this.callWorkerFunction('checkEnrollment', user);
|
|
169
|
-
webauthnCreate = (user) => this.callWorkerFunction('webauthnCreate', user);
|
|
170
|
-
webauthnGet = (user) => this.callWorkerFunction('webauthnGet', user);
|
|
171
|
-
webauthnRetrieve = (user) => this.callWorkerFunction('webauthnRetrieve', user);
|
|
172
|
-
webauthnDelete = (user) => this.callWorkerFunction('webauthnDelete', user);
|
|
173
26
|
}
|
|
174
27
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
GLOBAL.showLogs = () => {
|
|
185
|
-
if(!GLOBAL.logStack || GLOBAL.logStack.length === 0) return console.info('There are no logs currently in the stack!');
|
|
186
|
-
|
|
187
|
-
const getTime = (ISOStamp) => new Date(ISOStamp).toISOString().split('T')[1].slice(0,-1);
|
|
188
|
-
|
|
189
|
-
(function parseLog(stack=[...GLOBAL.logStack], parentEndTime = Infinity) {
|
|
190
|
-
while (stack.length > 0 && stack[0].startTime < parentEndTime) {
|
|
191
|
-
let markS, markE, spanName, indE, duration, stamps;
|
|
192
|
-
markS = stack.shift();
|
|
193
|
-
spanName = markS.name.slice(0, -6);
|
|
194
|
-
indE = stack.findIndex(log => log.name === spanName + "-END");
|
|
195
|
-
if (indE !== -1) markE = stack.splice(indE, 1)[0];
|
|
196
|
-
duration = (markE != null) ? (markE.startTime - markS.startTime).toFixed(4) + 'ms' : 'ONGOING';
|
|
197
|
-
stamps = (markE != null) ? getTime(markS.stamp) + " - " + getTime(markE.stamp) : getTime(markS.stamp) + " - ...";
|
|
198
|
-
|
|
199
|
-
console.groupCollapsed(spanName.replace(/-/g, ' :: ') + ' :: ' + duration + " (" + stamps + ")");
|
|
200
|
-
parseLog(stack, markE.startTime);
|
|
201
|
-
console.groupEnd();
|
|
202
|
-
}
|
|
203
|
-
})()
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
GLOBAL.addPerfMarker = (tag) => {
|
|
207
|
-
const {name, startTime} = performance.mark(tag).toJSON();
|
|
208
|
-
GLOBAL.logStack.push({
|
|
209
|
-
type : "MAINTHREAD",
|
|
210
|
-
order : GLOBAL.logStack.length,
|
|
211
|
-
name,
|
|
212
|
-
absTime : startTime,
|
|
213
|
-
stamp : performance.timeOrigin + startTime
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return class extends cls {
|
|
219
|
-
constructor(...args) {
|
|
220
|
-
super(...args);
|
|
221
|
-
|
|
222
|
-
Object.getOwnPropertyNames(this).forEach(propName => {
|
|
223
|
-
if (propName === "constructor" || typeof this[propName] !== "function") return;
|
|
224
|
-
|
|
225
|
-
const originalMethod = this[propName];
|
|
226
|
-
let markerTagPrefix = `[MAINTHREAD]-${cls.name}-${propName}`;
|
|
227
|
-
this[propName] = function(...args) {
|
|
228
|
-
if(propName === "callWorkerFunction") markerTagPrefix = `[MAINTHREAD]-${cls.name}-${propName}-${args[0]}`;
|
|
229
|
-
GLOBAL.addPerfMarker(markerTagPrefix + "-START");
|
|
230
|
-
const result = originalMethod.apply(this, args);
|
|
231
|
-
if (result && typeof result.then === 'function') {
|
|
232
|
-
return result.finally(() => GLOBAL.addPerfMarker(markerTagPrefix + "-END"));
|
|
233
|
-
} else {
|
|
234
|
-
GLOBAL.addPerfMarker(markerTagPrefix + "-END");
|
|
235
|
-
return result;
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
//
|
|
244
|
-
if(typeof UMFAClient !== "undefined" && UMFAClient instanceof Function) UMFAClient = amendPerformanceLoggingToClass(UMFAClient);
|
|
245
|
-
if(typeof FIDO2Client !== "undefined" && FIDO2Client instanceof Function) FIDO2Client = amendPerformanceLoggingToClass(FIDO2Client);
|
|
246
|
-
|
|
247
|
-
let masterLogs = [];
|
|
248
|
-
if(window){
|
|
249
|
-
let tzO = new Date().getTimezoneOffset() * 60000;
|
|
250
|
-
|
|
251
|
-
GLOBAL.getAllLogs = async (showCSV) => {
|
|
252
|
-
let res = await zsmClient.callWorkerFunction("getLogs");
|
|
253
|
-
let {logs, timeOrigin} = JSON.parse(res);
|
|
254
|
-
let timeDifferential = performance.timeOrigin - timeOrigin;
|
|
255
|
-
if(!showCSV) {
|
|
256
|
-
console.groupCollapsed('RAW logs');
|
|
257
|
-
GLOBAL.logStack.forEach(mainRecord => console.info('mainRecord :', mainRecord));
|
|
258
|
-
logs.forEach(workerRecord => {
|
|
259
|
-
workerRecord.absTime = workerRecord.absTime - timeDifferential;
|
|
260
|
-
console.info('workerRecord :', workerRecord);
|
|
261
|
-
});
|
|
262
|
-
console.groupEnd();
|
|
263
|
-
}
|
|
264
|
-
let allLogs = [...GLOBAL.logStack, ...logs];
|
|
265
|
-
allLogs = allLogs.sort((a, b) => a.absTime - b.absTime);
|
|
266
|
-
allLogs = allLogs.map((log, i) => Object.assign(log, {stamp: log.absTime + performance.timeOrigin, order:i}));
|
|
267
|
-
if(!showCSV) {
|
|
268
|
-
console.groupCollapsed('ALL logs (Combined and Sorted)');
|
|
269
|
-
masterLogs = [...masterLogs, ...allLogs];
|
|
270
|
-
allLogs.forEach(log => console.info('log :', log));
|
|
271
|
-
console.groupEnd();
|
|
272
|
-
}
|
|
273
|
-
console.groupCollapsed('ALL logs (Combined and Sorted)');
|
|
274
|
-
allLogs = allLogs.map(log => {
|
|
275
|
-
if(!localStorage) return log;
|
|
276
|
-
let activeEnv = localStorage.getItem('activeEnv');
|
|
277
|
-
if(!activeEnv) return log;
|
|
278
|
-
if(! /RELPARTYSERVER|CRYPTOSERVER/.test(log.type)) return log;
|
|
279
|
-
// log.type += '-' + activeEnv.toUpperCase();
|
|
280
|
-
return log;
|
|
281
|
-
});
|
|
282
|
-
allLogs.forEach(log => console.info('log :', log));
|
|
283
|
-
console.groupEnd();
|
|
284
|
-
|
|
285
|
-
return allLogs;
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
GLOBAL.showLogs = async (showCSV=false) => {
|
|
289
|
-
const getTime = (ISOStamp, timeOnly=true) => {
|
|
290
|
-
try{
|
|
291
|
-
return timeOnly ? new Date((+ISOStamp - tzO)).toISOString().slice(11,-1) : new Date(+ISOStamp - tzO).toISOString();
|
|
292
|
-
}catch(e){
|
|
293
|
-
console.error('Error parsing ISOStamp:', ISOStamp, e);
|
|
294
|
-
return ISOStamp;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
const stripStartEnd = (name) => name.replace(/-(START|END)$/gi, '');
|
|
298
|
-
|
|
299
|
-
function recursivelyMoveChildLogsIntoStartNode(stack) {
|
|
300
|
-
let processedLogs = [];
|
|
301
|
-
while (stack.length > 0) {
|
|
302
|
-
let startingMarker = stack.shift();
|
|
303
|
-
if(/-END$/i.test(startingMarker.name)) {
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
let endingMarker = stack.findIndex(log => log.name === stripStartEnd(startingMarker.name) + '-END'),
|
|
307
|
-
dateTimeStamps = [],
|
|
308
|
-
fullDateStamps = [],
|
|
309
|
-
stackSubset = [],
|
|
310
|
-
totalDuration = 0,
|
|
311
|
-
networkLatency = 0,
|
|
312
|
-
computeDuration = 0;
|
|
313
|
-
|
|
314
|
-
if(!~endingMarker) {
|
|
315
|
-
stackSubset = stack;
|
|
316
|
-
endingMarker = stack.length;
|
|
317
|
-
totalDuration = 'ONGOING';
|
|
318
|
-
dateTimeStamps.push(getTime(startingMarker.stamp), '...?');
|
|
319
|
-
fullDateStamps.push(getTime(startingMarker.stamp, false), '...?');
|
|
320
|
-
|
|
321
|
-
}else{
|
|
322
|
-
stackSubset = stack.splice(0, endingMarker+1);
|
|
323
|
-
endingMarker = stackSubset[stackSubset.length-1];
|
|
324
|
-
totalDuration = endingMarker.absTime - startingMarker.absTime;
|
|
325
|
-
dateTimeStamps.push(getTime(startingMarker.stamp), getTime(endingMarker.stamp));
|
|
326
|
-
fullDateStamps.push(getTime(startingMarker.stamp, false), getTime(endingMarker.stamp, false));
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
processedLogs.push(Object.assign(startingMarker, {
|
|
331
|
-
name: stripStartEnd(startingMarker.name),
|
|
332
|
-
children: recursivelyMoveChildLogsIntoStartNode(stackSubset),
|
|
333
|
-
totalDuration,
|
|
334
|
-
dateTimeStamps,
|
|
335
|
-
fullDateStamps,
|
|
336
|
-
networkLatency,
|
|
337
|
-
computeDuration
|
|
338
|
-
}));
|
|
339
|
-
}
|
|
340
|
-
return processedLogs;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
function recursivelyComputeCumulativeNetworkLatency(node) {
|
|
344
|
-
let nodeLatency = 0;
|
|
345
|
-
if(node.clientToServerLatency) nodeLatency += node.clientToServerLatency;
|
|
346
|
-
if(node.serverToClientLatency) nodeLatency += node.serverToClientLatency;
|
|
347
|
-
|
|
348
|
-
if (Array.isArray(node.children) && node.children.length > 0) {
|
|
349
|
-
node.children.forEach(child => {
|
|
350
|
-
nodeLatency += recursivelyComputeCumulativeNetworkLatency(child);
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
node.networkLatency = nodeLatency;
|
|
354
|
-
return nodeLatency;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
function calculateComputeDurationForNode(node) {
|
|
358
|
-
if(!node.children) return node.computeDuration = totalDuration;
|
|
359
|
-
node.computeDuration = (node.children.reduce((acc,child)=>{
|
|
360
|
-
return acc - child.totalDuration;
|
|
361
|
-
}, node.totalDuration))
|
|
362
|
-
node.children.forEach(calculateComputeDurationForNode)
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
let exportableStack = [];
|
|
366
|
-
|
|
367
|
-
function recursivelyOutputLogsToConsole(stack, depth = 0) {
|
|
368
|
-
let outputColors={
|
|
369
|
-
'MAINTHREAD': '#509',
|
|
370
|
-
'WORKER': '#009',
|
|
371
|
-
'RELPARTYSERVER': '#076',
|
|
372
|
-
'CRYPTOSERVER': '#700',
|
|
373
|
-
'RELPARTY': '#076',
|
|
374
|
-
'CRYPTO': '#700',
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
function formatNumberColumn(num, NaNValue='0.000') {
|
|
378
|
-
let opValue = isNaN(num) ? NaNValue : Math.abs(num).toFixed(3);
|
|
379
|
-
let lPadStr = ' '.repeat(12 - opValue.length);
|
|
380
|
-
return lPadStr + opValue;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
stack.forEach(item => {
|
|
384
|
-
let spacePadding = ' '.repeat(100);
|
|
385
|
-
let exportableRecord = {}
|
|
386
|
-
let sequence = item.order;
|
|
387
|
-
let nameElements = (item.name.match(/\[(.*?)\]-(.*)$/) || new Array(3).fill('')).slice(1,3);
|
|
388
|
-
let threadName = (nameElements[0] + spacePadding).replace('SERVER', '').slice(0, 14);
|
|
389
|
-
let processName = (nameElements[1] + spacePadding).slice(0, 70-(depth*2));
|
|
390
|
-
let totalDuration = formatNumberColumn(item?.totalDuration, 'ONGOING');
|
|
391
|
-
let computeDuration = (/ONGOING/.test(totalDuration)) ? formatNumberColumn('ONGOING', 'ONGOING') : formatNumberColumn(item?.computeDuration);
|
|
392
|
-
let networkLatency = (/ONGOING/.test(totalDuration)) ? formatNumberColumn('ONGOING', 'ONGOING') : formatNumberColumn(item?.networkLatency);
|
|
393
|
-
let cumulativeCompute;
|
|
394
|
-
if(/ONGOING/.test(totalDuration)) cumulativeCompute = formatNumberColumn('ONGOING', 'ONGOING');
|
|
395
|
-
else {
|
|
396
|
-
if(totalDuration < (Math.abs(networkLatency) + Math.abs(computeDuration))) totalDuration = formatNumberColumn(Math.abs(networkLatency) + Math.abs(computeDuration));
|
|
397
|
-
cumulativeCompute = formatNumberColumn((totalDuration - networkLatency - computeDuration), 'ONGOING');
|
|
398
|
-
}
|
|
399
|
-
let indentionDepth = depth;
|
|
400
|
-
if (/^CRYPTO/.test(threadName)) {
|
|
401
|
-
indentionDepth = depth + 2;
|
|
402
|
-
processName = processName.slice(0, -4);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
let indentionPads = depth > 0 ? ' '.repeat(indentionDepth-1) + ' ' : ' ';
|
|
406
|
-
let detailPads = depth > 0 ? ' '.repeat(indentionDepth-1) + ' '.repeat(threadName.length) + ' ' : ' ' + ' '.repeat(threadName.length);
|
|
407
|
-
let timeSpan = item?.dateTimeStamps ? (' ' + item.dateTimeStamps[0]) : 'N/A';
|
|
408
|
-
|
|
409
|
-
// if(!showCSV) {
|
|
410
|
-
let outputLine = ` ${threadName}${indentionPads} ${processName} ${totalDuration} ${networkLatency} ${cumulativeCompute} ${computeDuration} ${timeSpan}`;
|
|
411
|
-
console.groupCollapsed(`%c${outputLine}`, `color: ${outputColors[item.type]}; font-weight: 500;`);
|
|
412
|
-
console.info(`%c${detailPads} Sequence: `, `color: ${outputColors[item.type]}; font-weight: 700;`, sequence);
|
|
413
|
-
console.info(`%c${detailPads} Thread Name: `, `color: ${outputColors[item.type]}; font-weight: 700;`, threadName.trim());
|
|
414
|
-
console.info(`%c${detailPads} Process Name: `, `color: ${outputColors[item.type]}; font-weight: 700;`, processName.trim());
|
|
415
|
-
console.info(`%c${detailPads} Abs. Performance Mark: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (item?.absTime??'') + 'ms from timeOrigin');
|
|
416
|
-
console.info(`%c${detailPads} TimeStamp (Start): `, `color: ${outputColors[item.type]}; font-weight: 700;`, (item?.dateTimeStamps[0]??''));
|
|
417
|
-
console.info(`%c${detailPads} TimeStamp (End): `, `color: ${outputColors[item.type]}; font-weight: 700;`, (item?.dateTimeStamps[1]??''));
|
|
418
|
-
console.info(`%c${detailPads} Cumulative Tot. Duration: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (/ONGOING/.test(totalDuration) ? 'ONGOING' : totalDuration.trim() + 'ms'));
|
|
419
|
-
console.info(`%c${detailPads} Cumulative Network Latency: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (/ONGOING/.test(networkLatency) ? 'ONGOING' : networkLatency.trim() + 'ms'));
|
|
420
|
-
console.info(`%c${detailPads} Cumulative Compute Duration: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (/ONGOING/.test(cumulativeCompute) ? 'ONGOING' : cumulativeCompute.trim() + 'ms'));
|
|
421
|
-
console.info(`%c${detailPads} Process Compute Duration: `, `color: ${outputColors[item.type]}; font-weight: 700;`, (/ONGOING/.test(computeDuration) ? 'ONGOING' : computeDuration.trim() + 'ms'));
|
|
422
|
-
console.info(`%c${detailPads} ================================================================`, `color: ${outputColors[item.type]}; font-weight: 700;`, "\n\n");
|
|
423
|
-
console.groupEnd();
|
|
424
|
-
// } else if(!showCSV || showCSV) {
|
|
425
|
-
let activeEnv = '';
|
|
426
|
-
let pageHost = window.location.host;
|
|
427
|
-
|
|
428
|
-
if(localStorage && localStorage.getItem('activeEnv')) {
|
|
429
|
-
activeEnv = (/RELPARTY|CRYPTO/.test(threadName)) ? localStorage.getItem('activeEnv') : 'N/A';
|
|
430
|
-
}
|
|
431
|
-
exportableRecord = {
|
|
432
|
-
sequence : sequence,
|
|
433
|
-
threadName : threadName.trim(),
|
|
434
|
-
processName : processName.trim(),
|
|
435
|
-
absTime : (item?.absTime) ? (item.absTime.toFixed(5)) : '',
|
|
436
|
-
totalDuration : (/ONGOING/.test(totalDuration) ? 'ONGOING' : +(totalDuration.trim())),
|
|
437
|
-
networkLatency : (/ONGOING/.test(networkLatency) ? 'ONGOING' : +(networkLatency.trim())),
|
|
438
|
-
cumulativeCompute : (/ONGOING/.test(cumulativeCompute) ? 'ONGOING' : +(cumulativeCompute.trim())),
|
|
439
|
-
computeDuration : (/ONGOING/.test(computeDuration) ? 'ONGOING' : +(computeDuration.trim())),
|
|
440
|
-
startTime : (item?.fullDateStamps[0]?.replace(/[TZ]/g, ' ').trim() ?? ''),
|
|
441
|
-
endTime : (item?.fullDateStamps[1]?.replace(/[TZ]/g, ' ').trim() ?? ''),
|
|
442
|
-
spawnsChildren : item?.children ? item.children.length : 0,
|
|
443
|
-
host : pageHost,
|
|
444
|
-
remoteAPIEnv : activeEnv,
|
|
445
|
-
};
|
|
446
|
-
|
|
447
|
-
exportableStack.push(exportableRecord);
|
|
448
|
-
// }
|
|
449
|
-
if(item.children.length > 0) recursivelyOutputLogsToConsole(item.children, depth + 1);
|
|
450
|
-
});
|
|
451
|
-
return exportableStack.length ? exportableStack : undefined;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
let allLogs = await GLOBAL.getAllLogs(showCSV);
|
|
455
|
-
let processedStack = recursivelyMoveChildLogsIntoStartNode(allLogs);
|
|
456
|
-
processedStack.forEach(root => recursivelyComputeCumulativeNetworkLatency(root));
|
|
457
|
-
processedStack.forEach(root => calculateComputeDurationForNode(root));
|
|
458
|
-
if(!showCSV) console.info(`%c${' THREAD PROCESS NAME DURATION NETWORK TOT.COMP. COMPUTE START TIME'}`, 'color: #000; font-weight: 700;');
|
|
459
|
-
let exportableData = recursivelyOutputLogsToConsole(processedStack);
|
|
460
|
-
console.log('exportableData :', exportableData);
|
|
461
|
-
if(!showCSV || !exportableData) return;
|
|
462
|
-
let csvData = exportableData.flatMap((log, i) => {
|
|
463
|
-
let retVal = [Object.values(log)];
|
|
464
|
-
retVal[0][0] = i + 1;
|
|
465
|
-
retVal = ['"' + retVal[0].join('","') + '"'];
|
|
466
|
-
if(i === 0) retVal.unshift('"' + Object.keys(log).join('","') + '"');
|
|
467
|
-
return retVal;
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
try {
|
|
471
|
-
GLOBAL.exportCount++;
|
|
472
|
-
console.groupCollapsed(`CSV Data Exported as %c${GLOBAL.sessionStamp}-${(GLOBAL.exportCount)}.csv`, 'color: #F60; font-weight: 700;');
|
|
473
|
-
let blobdtMIME = new Blob([csvData.join('\n')], { type: "text/csv" });
|
|
474
|
-
let url = URL.createObjectURL(blobdtMIME)
|
|
475
|
-
let anchor = document.createElement("a")
|
|
476
|
-
anchor.id = "download"
|
|
477
|
-
anchor.setAttribute("download", `${GLOBAL.sessionStamp}-${(GLOBAL.exportCount)}.csv`);
|
|
478
|
-
anchor.href = url;
|
|
479
|
-
anchor.click();
|
|
480
|
-
console.info(`CSV Data:\n${csvData.join('\n')}\n...EOS`);
|
|
481
|
-
URL.revokeObjectURL(url);
|
|
482
|
-
GLOBAL.logStack = [];
|
|
483
|
-
zsmClient.callWorkerFunction("clearLogs", true);
|
|
484
|
-
console.groupEnd();
|
|
485
|
-
} catch (error) {
|
|
486
|
-
console.error('Error during download:', error);
|
|
487
|
-
console.groupEnd();
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
return exportableData;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
}
|
|
28
|
+
zsmPluginManager.registerPlugin('Core', {
|
|
29
|
+
classDefs: {
|
|
30
|
+
"UMFAClient" : UMFAClientCore,
|
|
31
|
+
"FIDO2Client" : FIDO2ClientCore,
|
|
32
|
+
"RelyingParty" : RelyingParty,
|
|
33
|
+
"WebAuthnClient" : WebAuthnClient
|
|
34
|
+
},
|
|
35
|
+
mode: 'OVERRIDE'
|
|
36
|
+
});
|
|
494
37
|
|
|
495
38
|
export { UMFAClient, FIDO2Client };
|
package/package.json
CHANGED
|
@@ -1,54 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@ideem/zsm-client-sdk",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "ZSM makes 2FA easy and invisible for everyone, all the time, using advanced cryptography like MPC to establish cryptographic proof of the origin of any transaction or login attempt, while eliminating opportunities for social engineering. ZSM has no reliance on specific hardware. Our cryptographic module has completed FIPS 140-3 NIST approved lab testing, is FIDO2-ready, and is on the Modules In Progress (MIP) list. Superior Usability. no opt-in, no codes, no downloads, no authenticator apps. Better Security.",
|
|
5
|
-
"author": "@JJ (Jason Jurusz) <jj@useideem.com>/<nerdy.deeds@done.cheap>",
|
|
6
|
-
"keywords": [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"library",
|
|
13
|
-
"UMFA",
|
|
14
|
-
"FIDO2",
|
|
15
|
-
"client",
|
|
16
|
-
"authentication",
|
|
17
|
-
"javascript",
|
|
18
|
-
"multi-factor",
|
|
19
|
-
"webauthn",
|
|
20
|
-
"authentication",
|
|
21
|
-
"security"
|
|
22
|
-
],
|
|
23
|
-
"scripts": {
|
|
24
|
-
"start": "echo 'This is a library, not an application. No start script defined. To use, import the library.'",
|
|
25
|
-
"inc": "npm version patch && cd ..; sleep 1; npm pack ./pkg_files"
|
|
2
|
+
"name" : "@ideem/zsm-client-sdk",
|
|
3
|
+
"version" : "2.5.0",
|
|
4
|
+
"description" : "ZSM makes 2FA easy and invisible for everyone, all the time, using advanced cryptography like MPC to establish cryptographic proof of the origin of any transaction or login attempt, while eliminating opportunities for social engineering. ZSM has no reliance on specific hardware. Our cryptographic module has completed FIPS 140-3 NIST approved lab testing, is FIDO2-ready, and is on the Modules In Progress (MIP) list. Superior Usability. no opt-in, no codes, no downloads, no authenticator apps. Better Security.",
|
|
5
|
+
"author" : "@JJ (Jason Jurusz) <jj@useideem.com>/<nerdy.deeds@done.cheap>",
|
|
6
|
+
"keywords" : ["ideem", "zsm", "zsm-client-sdk", "UMFAClient", "FIDO2Client", "library", "UMFA", "FIDO2", "client", "authentication", "javascript", "multi-factor", "webauthn", "authentication", "security", "cryptography", "MPC", "FIPS", "NIST", "FIDO2-ready", "Modules In Progress", "MIP"],
|
|
7
|
+
"type" : "module",
|
|
8
|
+
"main" : "./ZSMClientSDK.js",
|
|
9
|
+
"scripts" : {
|
|
10
|
+
"start" : "echo 'This is the Ideem SDK library, not a freestanding application. There is no start script defined. To use, import the library into a browser application.' 1>&2",
|
|
11
|
+
"version" : "echo \"$(npm pkg get name | tr -d \\\") current version: $(npm pkg get version | tr -d \\\")\""
|
|
26
12
|
},
|
|
27
|
-
"collaborators": [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
],
|
|
33
|
-
"license": "SEE LICENSE IN LICENSE",
|
|
34
|
-
"repository": {
|
|
35
|
-
"type": "git",
|
|
36
|
-
"url": "github:useideem/vHSM"
|
|
13
|
+
"collaborators" : [ "Joel Teply <joel@useideem.com>", "Todd Decker <todd@useideem.com>", "Brian Koziel <brian@useideem.com>" ],
|
|
14
|
+
"license" : "SEE LICENSE IN LICENSE",
|
|
15
|
+
"repository" : {
|
|
16
|
+
"type" : "git",
|
|
17
|
+
"url" : "github : useideem/vHSM"
|
|
37
18
|
},
|
|
38
|
-
"homepage": "
|
|
39
|
-
"bugs": "https://github.com/useideem/vHSM/issues",
|
|
40
|
-
"files": [
|
|
41
|
-
|
|
42
|
-
"ZSMClientSDK.js",
|
|
43
|
-
"CHANGELOG.md",
|
|
44
|
-
"LICENSE",
|
|
45
|
-
"README.md"
|
|
46
|
-
],
|
|
47
|
-
"engines": {
|
|
48
|
-
"node": ">=12.0.0"
|
|
49
|
-
},
|
|
50
|
-
"sideEffects": [
|
|
51
|
-
"worker.js",
|
|
52
|
-
"ZSMClientSDK.js"
|
|
53
|
-
]
|
|
19
|
+
"homepage" : "https://useideem.com",
|
|
20
|
+
"bugs" : "https://github.com/useideem/vHSM/issues",
|
|
21
|
+
"files" : ["./EventCoordinator.js", "./FIDO2Client.js", "./FIDO2ClientBase.js", "./GlobalScoping.js", "./IdentityIndexing.js", "./PluginManager.js", "./RelyingParty.js", "./RelyingPartyBase.js", "./UMFAClient.js", "./UMFAClientBase.js", "./Utils.js", "./WASMRustInterface.js", "./WebAuthnClient.js", "./WebAuthnClientBase.js", "./ZSMClientSDK.js", "./shims/", "./LICENSE", "./README.md", "./CHANGELOG.md"],
|
|
22
|
+
"sideEffects" : false
|
|
54
23
|
}
|