@ideem/zsm-client-sdk 2.6.1 → 2.6.3
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 +7 -1
- package/EventCoordinator.js +3 -2
- package/PluginManager.js +17 -16
- package/WebAuthnClientBase.js +6 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -11,7 +11,13 @@ and Universal MFA into a browser application.
|
|
|
11
11
|
- None at this time.
|
|
12
12
|
|
|
13
13
|
----
|
|
14
|
-
## Release 2.6.
|
|
14
|
+
## Release 2.6.3 - January 6, 2026 [ NPM PACKAGE RELEASE ] **[ LATEST ]**
|
|
15
|
+
- Minor alteration to event coordinator to support legacy versions of Safari (versions 14-18.4)
|
|
16
|
+
|
|
17
|
+
## Release 2.6.2 - December 19, 2025 [ NPM PACKAGE RELEASE ]
|
|
18
|
+
- Hotfix release to address an issue with the Passkeys+ plugin integration.
|
|
19
|
+
|
|
20
|
+
## Release 2.6.1 - December 16, 2025 [ NPM PACKAGE RELEASE ]
|
|
15
21
|
- Minor bug fixes and improvements
|
|
16
22
|
- Minor alteration to initialization process to remove the need to provide a `userIdentifier` when initializing (all method calls now provide the update).
|
|
17
23
|
- Improvements to EventCoordinator:
|
package/EventCoordinator.js
CHANGED
|
@@ -182,7 +182,7 @@ class EventCoordinator {
|
|
|
182
182
|
byStatus(eventStatus) {
|
|
183
183
|
if (!eventStatus || typeof eventStatus !== 'string' || !eventStatus.length || !["UNREGISTERED", "PENDING", "READY", "ERROR"].includes(eventStatus))
|
|
184
184
|
throw new Error(`[ZSM EventCoordinator] :: byStatus :: Invalid 'eventStatus' value: "${eventStatus}". Valid statuses are: UNREGISTERED, PENDING, READY, ERROR.`);
|
|
185
|
-
return
|
|
185
|
+
return this.entries.flatMap(([k, v]) => v === eventStatus ? [k] : []);
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
/**
|
|
@@ -202,7 +202,8 @@ class EventCoordinator {
|
|
|
202
202
|
* @returns {Object} Returns the reset event stack object.
|
|
203
203
|
*/
|
|
204
204
|
reset() {
|
|
205
|
-
this.
|
|
205
|
+
this.keys.forEach(key => this._eventStack.set(key, 'PENDING'));
|
|
206
|
+
|
|
206
207
|
if(window && window?.queueMicrotask) {
|
|
207
208
|
queueMicrotask(() => this.dispatchEvent('ZSMClientEventStackReset', { stack: this.object }));
|
|
208
209
|
} else this.dispatchEvent('ZSMClientEventStackReset', { stack: this.object });
|
package/PluginManager.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
class PluginManager {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
constructor() {
|
|
3
|
+
this._sdkClassMap = new Map(); // Map of SDK class names to their implementations
|
|
4
|
+
this._classCorpus = new Map(); // Map of plugin identities to their class maps
|
|
5
|
+
this._status = 'INITIALIZED'; // Indicates the current status of the plugin manager (INITIALIZED, SEEDED, FROZEN)
|
|
6
|
+
}
|
|
6
7
|
/**
|
|
7
8
|
* Returns whether the plugin manager is frozen.
|
|
8
9
|
* @returns {boolean} True if the plugin manager is frozen, false otherwise.
|
|
9
10
|
*/
|
|
10
11
|
get isFrozen() {
|
|
11
|
-
return this
|
|
12
|
+
return this._status === 'FROZEN';
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -20,15 +21,15 @@ class PluginManager {
|
|
|
20
21
|
* @throws {Error} If no class is registered for the given name.
|
|
21
22
|
*/
|
|
22
23
|
classes (classDesc) {
|
|
23
|
-
if(this
|
|
24
|
+
if(this._status === 'INITIALIZED') throw new Error('[zsmPluginManager] :: classes :: collection accessor cannot be referenced before SOME classes are registered!');
|
|
24
25
|
if(!classDesc || typeof classDesc !== 'string') throw new Error(`[zsmPluginManager] :: classes :: collection accessor requires a valid class description (received ${typeof classDesc}: ${classDesc})!`);
|
|
25
26
|
classDesc = classDesc.toUpperCase();
|
|
26
27
|
if(!this.isFrozen){
|
|
27
28
|
console.warn('[zsmPluginManager] :: Freezing the plugin manager as the first class has been preemptively requested. No further plugins can be registered after this point.\nIf you feel you received this message unexpectedly, please ensure all plugins are imported before initializing (`new UMFAClient()` or `new FIDO2Client()`) a client.');
|
|
28
29
|
this.freezePlugins();
|
|
29
30
|
}
|
|
30
|
-
if(!this
|
|
31
|
-
return this
|
|
31
|
+
if(!this._sdkClassMap.has(classDesc)) throw new Error(`[zsmPluginManager] :: classes :: No SDK class registered for: ${classDesc}`);
|
|
32
|
+
return this._sdkClassMap.get(classDesc);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -56,9 +57,9 @@ class PluginManager {
|
|
|
56
57
|
if (this.isFrozen) throw new Error('[zsmPluginManager] :: registerPlugin :: Cannot register plugin: PlugInManager is frozen!\nThis typically occurs when a plugin is imported after a client - UMFAClient or FIDO2Client - has already been initialized.\nMake sure to import all plugins before initializing (`new UMFAClient()` or `new FIDO2Client()`) a client.');
|
|
57
58
|
if (!pluginIdentity || typeof classObj !== 'object' || classObj == null) throw new Error('[zsmPluginManager] :: registerPlugin :: pluginIdentity and class map object required');
|
|
58
59
|
|
|
59
|
-
this
|
|
60
|
+
this._status = 'SEEDED';
|
|
60
61
|
|
|
61
|
-
this
|
|
62
|
+
this._classCorpus.set(pluginIdentity.toUpperCase(), classObj);
|
|
62
63
|
console.info(`[zsmPluginManager] :: PluginManager :: Registered plugin "${pluginIdentity}".`);
|
|
63
64
|
return true;
|
|
64
65
|
}
|
|
@@ -74,19 +75,19 @@ class PluginManager {
|
|
|
74
75
|
// As new plugins are DEVELOPED, they may introduce new classes or modify existing ones, and their extension/override logic must be declared below.
|
|
75
76
|
|
|
76
77
|
// [CORE PACKAGE] Default all of the active classes to the "core" classes (set below this declaration)
|
|
77
|
-
const core = this
|
|
78
|
+
const core = this._classCorpus.get('CORE');
|
|
78
79
|
if (!core) throw new Error('[zsmPluginManager] :: freezePlugins :: Core not registered before freeze');
|
|
79
80
|
|
|
80
81
|
const constructedMap = this.seedClassMap(core); // returns Map
|
|
81
82
|
|
|
82
83
|
// [PASSKEYS+ PLUGIN PACKAGE] If the "PASSKEYS+" plugin is registered, supercede the core classes with the passkeys classes
|
|
83
|
-
if(this
|
|
84
|
-
const passkeysMap = this
|
|
84
|
+
if(this._classCorpus.has('PASSKEYS+')) {
|
|
85
|
+
const passkeysMap = this._classCorpus.get('PASSKEYS+');
|
|
85
86
|
if (passkeysMap?.classDefs) for (const [k,v] of Object.entries(passkeysMap.classDefs)) constructedMap.set(k.toUpperCase(), v);
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
// Apply class decorators (wrappers) AFTER overlays, if present in any of the registrations
|
|
89
|
-
const postConstructDecorators = [...this
|
|
90
|
+
const postConstructDecorators = [...this._classCorpus.values()].filter(entry => entry.mode === 'DECORATOR');
|
|
90
91
|
if (postConstructDecorators.length) {
|
|
91
92
|
for (const modifier of postConstructDecorators) {
|
|
92
93
|
let { classDesc, postModFn } = modifier;
|
|
@@ -101,8 +102,8 @@ class PluginManager {
|
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
this
|
|
105
|
-
this
|
|
105
|
+
this._sdkClassMap = constructedMap;
|
|
106
|
+
this._status = 'FROZEN';
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
109
|
|
package/WebAuthnClientBase.js
CHANGED
|
@@ -12,6 +12,11 @@ const tracePrimer = (obj=false) => {
|
|
|
12
12
|
return (obj) ? {"trace": traceBase} : traceBase;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
const canParseURL = (url) => {
|
|
16
|
+
try { new URL(url); return true; } catch { return false; }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
15
20
|
class WebAuthnClientBase {
|
|
16
21
|
/**
|
|
17
22
|
* Constructs a WebAuthnClientBase object.
|
|
@@ -20,7 +25,7 @@ class WebAuthnClientBase {
|
|
|
20
25
|
constructor(config) {
|
|
21
26
|
// console.log('config :', Object.assign({}, config));
|
|
22
27
|
// Helper function to standardize URL format (ensuring it's parsable and ends with a '/')
|
|
23
|
-
const cleanURL = (url) =>
|
|
28
|
+
const cleanURL = (url) => canParseURL(url) ? new URL(url).origin + '/' : false;
|
|
24
29
|
|
|
25
30
|
if(config?.region){
|
|
26
31
|
config.authenticator_host_url ||= config.authenticator_host = `https://zsm-authenticator-${config.region}.useideem.com/`;
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name" : "@ideem/zsm-client-sdk",
|
|
3
|
-
"version" : "2.6.
|
|
3
|
+
"version" : "2.6.3",
|
|
4
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
5
|
"author" : "Jason Jurusz <jj@useideem.com>",
|
|
6
6
|
"keywords" : [ "ideem", "zsm", "zsm-client-sdk", "umfaclient", "fido2client", "library", "umfa", "fido", "fido2", "client", "javascript", "multifactor", "multi-factor", "webauthn", "authentication", "security", "cryptography", "mpc", "fips", "nist", "mip", "passkeys" ],
|
|
7
7
|
"type" : "module",
|
|
8
8
|
"main" : "./ZSMClientSDK.js",
|
|
9
9
|
"exports" : {
|
|
10
|
-
".":
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
"." : "./ZSMClientSDK.js",
|
|
11
|
+
"./*" : "./*.js",
|
|
12
|
+
"./*.js" : "./*.js"
|
|
13
|
+
},
|
|
14
|
+
|
|
15
15
|
"scripts" : {
|
|
16
16
|
"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",
|
|
17
17
|
"showVersion" : "echo \"$(npm pkg get name | tr -d \\\") current version: $(npm pkg get version | tr -d \\\")\""
|