@ideem/zsm-client-sdk 2.5.0 → 2.6.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.
@@ -4,6 +4,7 @@ import { uid2iid, iid4uid } from './IdentityIndexing.js';
4
4
  import { toObject } from './Utils.js';
5
5
  import {zsmPluginManager} from './PluginManager.js';
6
6
 
7
+
7
8
  eventCoordinator.update('WebAuthnClientBase');
8
9
 
9
10
  const tracePrimer = (obj=false) => {
@@ -98,7 +99,7 @@ class WebAuthnClientBase {
98
99
  * @ by the initializeZsm thereafter. Fixes several potential race conditions and improves performance.
99
100
  * @returns {Promise<ZSMAPI>} Resolves with the initialized ZSM API.
100
101
  */
101
- primeZsmApi = async () => (!this.zsmApi) ? (this.zsmApi = await this.getZsmApi(Object.assign({}, GLOBAL.mpcConfig, {consumer_id: await iid4uid(GLOBAL.mpcConfig.consumer_id)}))) : this.zsmApi;
102
+ async primeZsmApi () { return (!this.zsmApi) ? (this.zsmApi = await this.getZsmApi(Object.assign({}, GLOBAL.mpcConfig, {consumer_id: await iid4uid(GLOBAL.mpcConfig.consumer_id)}))) : this.zsmApi; }
102
103
 
103
104
  /**
104
105
  * @name initializeZsm
@@ -126,22 +127,66 @@ class WebAuthnClientBase {
126
127
  */
127
128
 
128
129
  async checkIdentity (userIdentifier, primeEnroll=false) {
130
+
129
131
  try {
130
- this.status='CHECKING_IDENTITY_STARTING';
131
132
  const resultOfCheck = await this.relyingParty.checkServerSideIdentity(primeEnroll);
133
+
132
134
  if(!resultOfCheck) throw new Error('Unable to communicate with identity server!');
133
- const identityID = resultOfCheck.identity_id;
135
+ const identityID = Array.isArray(resultOfCheck) ? resultOfCheck[0].identity_id : resultOfCheck.identity_id;
136
+
134
137
  if(!identityID) throw new Error('Unable to acquire identity_id!');
138
+
135
139
  uid2iid(userIdentifier, identityID);
136
140
  GLOBAL.mpcConfig.consumer_id = identityID;
137
- this.status = 'CHECKING_IDENTITY_FINISHED';
138
- return Promise.resolve(identityID);
141
+ return identityID;
139
142
  } catch(err) {
140
- this.status = 'CHECKING_IDENTITY_FAILED';
141
143
  return Promise.reject(err);
142
144
  }
143
145
  }
144
146
 
147
+ /**
148
+ * @name webauthnCreate
149
+ * @description Creates a new WebAuthn credential for the specified userIdentifier.
150
+ * @param {string} userIdentifier The user identifier.
151
+ * @returns {Promise<Object>} Resolves with the created credential.
152
+ * @throws {Error} Throws a COUNTED error if unable to retrieve the public key from the Relying Party Server.
153
+ * @throws {Error} [MPC] Throws an error if unable to obtain the createResponse from the Crypto Server.
154
+ * @throws {Error} [MPC] Throws an error if the createResponse is missing the credential.
155
+ * @throws {Error} [MPC] Throws an error if the credential is missing the attestation object.
156
+ * @throws {Error} Throws a COUNTED error if unable to verify the credential with the Relying Party Server.
157
+ */
158
+ async webauthnCreate (userIdentifier) {
159
+
160
+ await this.initializeZsm('webauthnCreate');
161
+
162
+
163
+ const publicKey = await this.relyingParty.registrationStart();
164
+ if(publicKey instanceof Error) throw new Error(publicKey);
165
+ else if (!publicKey) throw new Error('[WebAuthnClient] :: webauthnCreate :: Unable to retrieve public key from Relying Party Server!');
166
+
167
+ publicKey.user_id = publicKey.user.id;
168
+
169
+ let createResponse = await this.zsmApi.webauthn_create(publicKey, undefined, userIdentifier, tracePrimer());
170
+ if(!createResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain response from Crypto Server!');
171
+
172
+
173
+ createResponse = toObject(createResponse);
174
+ GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: createResponse }));
175
+
176
+ if(!createResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain credential from Crypto Server!');
177
+ if(!createResponse?.result?.response) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to acquire attestation object!');
178
+
179
+ const credential = createResponse.result;
180
+
181
+
182
+ const registrationResult = await this.relyingParty.registrationFinish(credential);
183
+ if(registrationResult instanceof Error) throw new Error(registrationResult);
184
+ else if(registrationResult == false) throw new Error('[WebAuthnClient] :: webauthnCreate :: Unable to verify credential Relying Party Server!');
185
+
186
+
187
+ return registrationResult;
188
+ };
189
+
145
190
  /**
146
191
  * @name webauthnCreate
147
192
  * @description Creates a new WebAuthn credential for the specified userIdentifier.
@@ -154,14 +199,11 @@ class WebAuthnClientBase {
154
199
  * @throws {Error} Throws an error if unable to acquire the identity ID from the Relying Party Server.
155
200
  * @throws {Error} Throws an error if the user ID or token is missing from the response body.
156
201
  */
157
- async webauthnCreate (userIdentifier) {
202
+ async webauthnCreateMpcThenFinish (userIdentifier, publicKey, pairing_token) {
158
203
  this.status = 'ENROLLMENT_STARTING';
159
204
  await this.initializeZsm('webauthnCreate');
160
205
 
161
- const publicKey = await this.relyingParty.registrationStart();
162
- if(!publicKey) throw new Error('[WebAuthnClient] :: webauthnCreate :: Unable to retrieve public key from Relying Party Server!');
163
-
164
- let createResponse = await this.zsmApi.webauthn_create(publicKey, tracePrimer());
206
+ let createResponse = await this.zsmApi.webauthn_create(publicKey, pairing_token, userIdentifier, tracePrimer());
165
207
  if(!createResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain response from Crypto Server!');
166
208
 
167
209
  createResponse = toObject(createResponse);
@@ -175,7 +217,7 @@ class WebAuthnClientBase {
175
217
  const registrationResult = await this.relyingParty.registrationFinish(credential);
176
218
  if (!registrationResult) throw new Error('[WebAuthnClient] :: webauthnCreate :: Unable to verify credential Relying Party Server!');
177
219
 
178
- return registrationResult;
220
+ return registrationResult.credential;
179
221
  };
180
222
 
181
223
  /**
@@ -184,157 +226,124 @@ class WebAuthnClientBase {
184
226
  * @param {string} userIdentifier The user identifier.
185
227
  * @returns {Promise<ZSMAPI>} Resolves with the retrieved credential.
186
228
  * @throws {Error} Throws an error if no credential ID is found.
187
- * @throws {Error} Throws an error if unable to start authentication with the Relying Party Server.
229
+ * @throws {Error} Throws a COUNTED error if unable to start authentication with the Relying Party Server.
188
230
  * @throws {Error} Throws an error if unable to retrieve the public key/challenge from the Relying Party Server.
189
- * @throws {Error} Throws an error if unable to obtain the getResponse/credential from the Crypto Server.
231
+ * @throws {Error} Throws an error if unable to obtain the mpcResponse/credential from the Crypto Server.
190
232
  * @throws {Error} Throws an error if unable to verify the credential with the Relying Party Server.
191
233
  * @throws {Error} Throws an error if the user ID or token is missing from the response body.
192
234
  */
193
235
  async webauthnGet (userIdentifier) {
194
- this.status = 'AUTHENTICATION_STARTING';
195
236
 
196
237
  await this.initializeZsm('webauthnGet');
197
- await this.webauthnRetrieve(userIdentifier, true)
238
+ const credentialId = await this.webauthnRetrieve(userIdentifier, true);
198
239
 
240
+ if (!this.isEnrolled) throw new Error(`[WebAuthnClient] :: webauthnGet :: ${userIdentifier} is not enrolled, lacks a credential, or credential is corrupted!`);
199
241
 
200
- if (!this.isEnrolled) throw new Error(`[WebAuthnClient] :: webauthnGet :: Credential is missing for ${userIdentifier}`);
201
-
202
- let authStartResponse = await this.relyingParty.authenticationStart(this.credentialID);
203
- if(!authStartResponse) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to start authentication with Relying Party Server!');
242
+ let authStartResponse = await this.relyingParty.authenticationStart(credentialId);
204
243
 
244
+ if (authStartResponse instanceof Error) throw new Error(authStartResponse);
245
+ else if (!authStartResponse) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to start authentication with Relying Party Server!');
246
+
205
247
  authStartResponse = toObject(authStartResponse);
206
248
 
207
- if(!authStartResponse?.rcr || !authStartResponse?.rcr?.publicKey) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to retrieve public key from Relying Party Server!');
208
-
209
- const pubKey = authStartResponse?.rcr?.publicKey;
249
+ if(!authStartResponse?.rcr?.publicKey?.challenge) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to locate public key/challenge inside Relying Party Server response!\nResponse Body: ' + JSON.stringify(authStartResponse));
250
+ const publicKey = authStartResponse.rcr.publicKey;
210
251
 
211
- if(!pubKey || !pubKey?.challenge) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to acquire challenge from public key!');
252
+ let mpcResponse = await this.zsmApi.webauthn_get(publicKey, undefined, userIdentifier, tracePrimer());
253
+
212
254
 
213
- let getResponse = await this.zsmApi.webauthn_get(pubKey, tracePrimer());
214
- if(!getResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain getResponse from Crypto Server!');
255
+ if(!mpcResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Crypto server did not respond!');
215
256
 
216
- getResponse = toObject(getResponse);
257
+ mpcResponse = toObject(mpcResponse);
258
+ if(!mpcResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Response from Crypto Server did not contain a credential!\nResponse Body: ' + JSON.stringify(mpcResponse));
217
259
 
218
- if(!getResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain credential from Crypto Server!');
260
+ GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: mpcResponse }));
219
261
 
220
- GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: getResponse }));
221
-
222
- const credential = getResponse.result;
262
+ const credential = mpcResponse.result;
223
263
  let authFinishResponse = await this.relyingParty.authenticationFinish(credential);
224
264
 
225
- if (!authFinishResponse) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to verify credential Relying Party Server!');
265
+ if (authFinishResponse instanceof Error) throw new Error(authFinishResponse);
266
+ else if (!authFinishResponse) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to verify credential from Relying Party Server!');
226
267
 
227
268
  authFinishResponse = toObject(authFinishResponse)
228
-
229
- if (!authFinishResponse.user_id || !authFinishResponse.token) throw new Error('[WebAuthnClient] :: webauthnGet :: User ID or token is missing from response body!');
269
+ if (!authFinishResponse.token) throw new Error('[WebAuthnClient] :: webauthnGet :: Token mismatched or missing from Relying Party Server verification attempt!\nResponse Body: ' + JSON.stringify(authFinishResponse));
230
270
 
231
271
  return {
232
272
  signature : credential.response.signature,
233
273
  signedChallenge : credential.response.clientDataJSON,
234
274
  user_id : authFinishResponse.user_id,
235
275
  token : authFinishResponse.token,
236
- challenge : pubKey.challenge,
276
+ challenge : publicKey.challenge,
237
277
  credential
238
278
  };
239
279
  };
240
280
 
281
+
282
+
241
283
  /**
242
284
  * @name webauthnRetrieve
243
285
  * @description Looks up the Identity ID for the specified userIdentifier and retrieves its credential ID (if it exists).
244
286
  * @ This is used to make a client-only check to see if a given userIdentifier already has an enrollment on the device.
245
287
  * @param {string} userIdentifier The user identifier.
246
- * @param {boolean} silent Whether to suppress status updates. [default: false]
247
- * @returns {Promise<Boolean>} Resolves with the credential ID or `false` if retrieval fails.
248
- * @returns {Promise<String>} Resolves with the retrieved rawID for the specified user.
288
+ * @param {string} targetData The specific data to retrieve. Options are:
289
+ * @ - 'id' or omitted: retrieves the ZSM credential ID (default)
290
+ * @ - 'all': retrieves an object containing all relevant credential data
291
+ * @ - any other string: retrieves the specified field from the response
292
+ * @returns {Promise<Boolean:false>} Returns `false` if retrieval fails (no enrollment found).
293
+ * @returns {Promise<String>} Returns the requested data if found (e.g., ").
294
+ * @returns {Promise<Object>} Resolves with an object containing all relevant credential data.
295
+ * @returns {Promise<Null>} Resolves with null if the requested data is not found.
296
+ * @throws {Error} Throws an error if an uncaught/unhandled error occurs while retrieving the credential.
249
297
  */
250
- async webauthnRetrieve (userIdentifier, silent=false) {
298
+ async webauthnRetrieve (userIdentifier) {
251
299
  this.credentialID = null;
252
- if (!silent) {
253
- this.status = 'CREDENTIAL_RETRIEVING';
254
- }
255
-
256
- try {
257
- await this.initializeZsm('webauthnRetrieve');
258
- let credentialIdentifier = await iid4uid(userIdentifier);
259
- GLOBAL.mpcConfig.consumer_id = credentialIdentifier;
260
-
261
- let response = await this.zsmApi.webauthn_retrieve(credentialIdentifier);
262
- response = toObject(response);
263
-
264
- if (response.error || !response?.result?.rawId) return false;
265
-
266
- this.credentialID = response.result.rawId;
267
- if (!silent) this.status = 'CREDENTIAL_RETRIEVED';
268
-
269
- return this.credentialID;
270
- } catch (error) {
271
- if(!silent){
272
- this.status = 'CREDENTIAL_RETRIEVAL_FAILED';
273
- throw error;
274
- }
275
- }
276
- };
277
-
278
- /**
279
- * @name webauthnCreateThenPartialGet
280
- * @description UMFA-OPTIMIZED FLOW: Creates a new WebAuthn credential and then performs a partial get operation.
281
- * @description This is used to create a new credential and then immediately retrieve it for authentication.
282
- * @param {string} userIdentifier The user identifier.
283
- * @returns {Promise<Object>} Resolves with the created credential.
284
- * @throws {Error} Throws an error if unable to retieve public key/regFinishAuthStart from the Relying Party Server.
285
- * @throws {Error} Throws an error if unable to obtain the createResponse/credential from the Crypto Server.
286
- */
287
- async webauthnCreateThenPartialGet (userIdentifier) {
288
- this.status = 'ENROLLMENT_STARTING';
289
-
290
- const returnObj = await this.relyingParty.createIdentityThenRegistrationStart();
291
- if (!returnObj) throw new Error('[WebAuthnClient] :: webauthnCreateThenPartialGet :: Unable to retrieve public key from Relying Party Server!');
292
300
 
293
- const {publicKey, identity_id} = returnObj;
294
- await this.initializeZsm('webauthnCreateThenPartialGet');
295
-
296
- let createResponse = await this.zsmApi.webauthn_create(publicKey, tracePrimer());
297
- if (!createResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreateThenPartialGet :: Unable to obtain response from Crypto Server!');
298
-
299
- createResponse = toObject(createResponse);
300
-
301
- GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: createResponse }));
302
-
303
- if(!createResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreateThenPartialGet :: Unable to obtain credential from Crypto Server!');
304
-
305
- const createCredential = createResponse.result;
306
-
307
- let regFinishAuthStartResponse = await this.relyingParty.registrationFinishAuthenticationStart(createCredential);
308
- if (!regFinishAuthStartResponse) throw new Error('[WebAuthnClient] :: webauthnCreateThenPartialGet :: Unable to retrieve response from Relying Party Server!');
309
-
310
- regFinishAuthStartResponse = toObject(regFinishAuthStartResponse);
311
-
312
- if(!regFinishAuthStartResponse?.rcr || !regFinishAuthStartResponse?.rcr?.publicKey) throw new Error('[WebAuthnClient] :: webauthnCreateThenPartialGet :: Unable to retrieve public key from Relying Party Server!');
313
-
314
- const getChallenge = regFinishAuthStartResponse.rcr.publicKey;
315
-
316
- let getResponse = await this.zsmApi.webauthn_get(getChallenge, tracePrimer());
317
- if(!getResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain response from Crypto Server!');
318
-
319
- getResponse = toObject(getResponse);
320
-
321
- if(!getResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain credential from Crypto Server!');
322
-
323
- GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: getResponse }));
324
-
325
-
326
- const getCredential = getResponse.result;
327
- let op = {
328
- user_id : userIdentifier,
329
- credential : getCredential,
330
- signature : getCredential.response.signature,
331
- signedChallenge : getCredential.response.clientDataJSON,
332
- challenge : getChallenge.challenge,
333
- };
301
+ this.initializeZsm('webauthnRetrieve');
302
+ let credentialIdentifier = await iid4uid(userIdentifier),
303
+ requestedData = {};
304
+ GLOBAL.mpcConfig.consumer_id = credentialIdentifier;
334
305
 
335
- return op;
306
+ let response = await this.zsmApi.webauthn_retrieve(userIdentifier);
307
+ response = toObject(response);
336
308
 
309
+ if (response?.error || !response?.result) return false;
310
+
311
+ this.credentialID = response?.result['zsm_credential_id']??null;
312
+ return this.credentialID || false;
337
313
  };
314
+ // async webauthnRetrieve (userIdentifier, targetData='id') {
315
+ // this.credentialID = null;
316
+ //
317
+ // this.initializeZsm('webauthnRetrieve');
318
+ // let credentialIdentifier = await iid4uid(userIdentifier),
319
+ // requestedData = {};
320
+ // GLOBAL.mpcConfig.consumer_id = credentialIdentifier;
321
+ //
322
+ // let response = await this.zsmApi.webauthn_retrieve(userIdentifier);
323
+ // response = toObject(response);
324
+ //
325
+ // if (response?.error || !response?.result) return false;
326
+ //
327
+ // this.credentialID = response?.result['zsm_credential_id']??null;
328
+ //
329
+ // if([undefined,true,false,null,'','id'].includes(targetData)) {
330
+ // return this.credentialID;
331
+ // }
332
+ // let pkpCred = await iid4uid(`pk:${userIdentifier}`);
333
+ // if(pkpCred === `pk:${userIdentifier}`) pkpCred = undefined;
334
+ // requestedData = {
335
+ // userIdentifier,
336
+ // zsmCredID : this.credentialID,
337
+ // hasZSMCred : (this.credentialID != null),
338
+ // pkpCredID : pkpCred,
339
+ // hasLocalPasskey : (typeof pkpCred === 'string' && pkpCred !== ''),
340
+ // hasRemotePasskey : (typeof pkpCred === 'object')
341
+ // };
342
+ // if (targetData === "all") {
343
+ // return requestedData;
344
+ // }
345
+ // return response?.[targetData] ?? response?.result?.[targetData] ?? requestedData?.[targetData] ?? null;
346
+ // };
338
347
 
339
348
  /**
340
349
  * @name webauthnPartialGet
@@ -344,8 +353,8 @@ class WebAuthnClientBase {
344
353
  * @throws {Error} Throws an error if the credential is missing for the userIdentifier provided.
345
354
  * @throws {Error} Throws an error if unable to start authentication with the Relying Party Server.
346
355
  * @throws {Error} Throws an error if unable to retrieve the public key from the Relying Party Server.
347
- * @throws {Error} Throws an error if unable to obtain the getResponse/credential from the Crypto Server.
348
- * @emits {CustomEvent} Emits a "MPCResponse" event with the getResponse data.
356
+ * @throws {Error} Throws an error if unable to obtain the mpcResponse/credential from the Crypto Server.
357
+ * @emits {CustomEvent} Emits a "MPCResponse" event with the mpcResponse data.
349
358
  */
350
359
  async webauthnPartialGet (userIdentifier) {
351
360
  this.status = 'AUTHENTICATION_STARTING';
@@ -361,16 +370,16 @@ class WebAuthnClientBase {
361
370
  if(!getChallenge?.rcr || !getChallenge.rcr.publicKey) throw new Error('[WebAuthnClient] :: webauthnPartialGet :: Unable to retrieve public key from Relying Party Server!');
362
371
  const pubKey = getChallenge.rcr.publicKey;
363
372
 
364
- let getResponse = await this.zsmApi.webauthn_get(pubKey, tracePrimer());
365
- if(!getResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain getResponse from Crypto Server!');
373
+ let mpcResponse = await this.zsmApi.webauthn_get(pubKey, null, userIdentifier, tracePrimer());
374
+ if(!mpcResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnPartialGet :: Unable to obtain mpcResponse from Crypto Server!');
366
375
 
367
- getResponse = toObject(getResponse);
376
+ mpcResponse = toObject(mpcResponse);
368
377
 
369
- if(!getResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain credential from Crypto Server!');
378
+ if(!mpcResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnPartialGet :: Unable to obtain credential from Crypto Server!');
370
379
 
371
- GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: getResponse }));
380
+ GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: mpcResponse }));
372
381
 
373
- const getCredential = getResponse.result;
382
+ const getCredential = mpcResponse.result;
374
383
  return {
375
384
  signature: getCredential.response.signature,
376
385
  signedChallenge: getCredential.response.clientDataJSON,
@@ -405,7 +414,11 @@ class WebAuthnClientBase {
405
414
  const cursor = event.target.result;
406
415
  if (cursor) {
407
416
  const { key, value } = cursor;
408
- if (value instanceof Map && value.has("rawId") && value.get("rawId") === rawID) return (store.delete(key), true);
417
+ if(
418
+ key.includes(userIdentifier) ||
419
+ (typeof value === 'string' && value.includes(userIdentifier)) ||
420
+ typeof value === 'object' && value?.zsm_credential?.get('rawId') === rawID
421
+ ) (store.delete(key), true);
409
422
  cursor.continue();
410
423
  }
411
424
  };
package/package.json CHANGED
@@ -1,23 +1,72 @@
1
1
  {
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 \\\")\""
2
+ "name": "@ideem/zsm-client-sdk",
3
+ "version": "2.6.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": [
7
+ "ideem",
8
+ "zsm",
9
+ "zsm-client-sdk",
10
+ "UMFAClient",
11
+ "FIDO2Client",
12
+ "library",
13
+ "UMFA",
14
+ "FIDO2",
15
+ "client",
16
+ "authentication",
17
+ "javascript",
18
+ "multi-factor",
19
+ "webauthn",
20
+ "authentication",
21
+ "security",
22
+ "cryptography",
23
+ "MPC",
24
+ "FIPS",
25
+ "NIST",
26
+ "FIDO2-ready",
27
+ "Modules In Progress",
28
+ "MIP"
29
+ ],
30
+ "type": "module",
31
+ "main": "./ZSMClientSDK.js",
32
+ "scripts": {
33
+ "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",
34
+ "version": "echo \"$(npm pkg get name | tr -d \\\") current version: $(npm pkg get version | tr -d \\\")\""
12
35
  },
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"
36
+ "collaborators": [
37
+ "Joel Teply <joel@useideem.com>",
38
+ "Todd Decker <todd@useideem.com>",
39
+ "Brian Koziel <brian@useideem.com>"
40
+ ],
41
+ "license": "SEE LICENSE IN LICENSE",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "github : useideem/vHSM"
18
45
  },
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
46
+ "homepage": "https://useideem.com",
47
+ "bugs": "https://github.com/useideem/vHSM/issues",
48
+ "files": [
49
+ "./ErrorHandler.js",
50
+ "./EventCoordinator.js",
51
+ "./FIDO2Client.js",
52
+ "./FIDO2ClientBase.js",
53
+ "./GlobalScoping.js",
54
+ "./IdentityIndexing.js",
55
+ "./package.json",
56
+ "./PluginManager.js",
57
+ "./RelyingParty.js",
58
+ "./RelyingPartyBase.js",
59
+ "./shims/",
60
+ "./UMFAClient.js",
61
+ "./UMFAClientBase.js",
62
+ "./Utils.js",
63
+ "./WASMRustInterface.js",
64
+ "./WebAuthnClient.js",
65
+ "./WebAuthnClientBase.js",
66
+ "./ZSMClientSDK.js",
67
+ "./CHANGELOG.md",
68
+ "./LICENSE",
69
+ "./README.md"
70
+ ],
71
+ "sideEffects": false
23
72
  }
@@ -1,96 +0,0 @@
1
- // @ideem/zsm-client-sdk/shims/VanillaJSLoader.js (ESM; single-tag, passive loader)
2
-
3
- /* ---------- tiny helpers ---------- */
4
- const $tag = () =>
5
- document.querySelector('script[type="module"][src$="shims/VanillaJSLoader.js"]') ||
6
- document.currentScript ||
7
- null;
8
-
9
- const join = (base, rel) => new URL(String(rel).replace(/^\.\//, ""), base).href;
10
-
11
- function computeNodeModulesBase({ allowGuessAtRoot = true } = {}) {
12
- const el = $tag();
13
-
14
- // 1) Explicit overrides (absolute or relative to page)
15
- const override = el?.dataset?.nodeModules || window.IDEEM_NODE_MODULES;
16
- if (override) return new URL(override, document.baseURI).href.replace(/\/+$/, "/");
17
-
18
- // 2) Infer from the actual URL this loader was fetched from (or its tag src)
19
- const candidates = [
20
- (typeof import.meta !== "undefined" && import.meta && import.meta.url) ? import.meta.url : null,
21
- el?.src || null,
22
- ];
23
-
24
- for (const c of candidates) {
25
- if (!c) continue;
26
- try {
27
- const href = new URL(c, document.baseURI).href;
28
- const m = href.match(/^(.*\/node_modules\/)/i);
29
- if (m) return m[1];
30
- } catch { /* ignore */ }
31
- }
32
-
33
- // 3) Optional last-ditch guess at site root
34
- if (allowGuessAtRoot) return new URL("/node_modules/", document.baseURI).href;
35
-
36
- throw new TypeError(
37
- '[VanillaJSLoader] :: Could not determine the `/node_modules/` base path.\n' +
38
- 'Pass the path to your `node_modules/` folder via either a `data-node-modules="<URL>"` attribute on the loader <script> ' +
39
- 'or set window.IDEEM_NODE_MODULES="<URL>" before including the shim <script>.'
40
- );
41
- }
42
-
43
- function injectImportMap(imports) {
44
- const el = document.createElement("script");
45
- el.type = "importmap";
46
- el.textContent = JSON.stringify({ imports }, null, 2);
47
- document.head.appendChild(el);
48
- }
49
-
50
- async function ensureImportMapSupport() {
51
- const hasNative =
52
- typeof HTMLScriptElement !== "undefined" &&
53
- "supports" in HTMLScriptElement &&
54
- HTMLScriptElement.supports?.("importmap");
55
-
56
- if (hasNative) return; // synchronous path on modern browsers
57
-
58
- // Load shim from the same shims/ folder as this file, then proceed
59
- const s = document.createElement("script");
60
- s.defer = true;
61
- s.src = new URL("./es-module-shims.js", import.meta.url).href;
62
- document.head.appendChild(s);
63
- await new Promise((res, rej) => {
64
- s.addEventListener("load", res, { once: true });
65
- s.addEventListener("error", () => rej(new Error("Failed to load es-module-shims")));
66
- });
67
- }
68
-
69
- /* ---------- first-party plugin registry ---------- */
70
- const PLUGINS = [
71
- { pkg: "@ideem/plugins.passkeys-plus", entry: "PasskeysPlus.js" },
72
- { pkg: "@ideem/plugins.perf-logger", entry: "index.js" },
73
- { pkg: "@ideem/plugins.worker-thread", entry: "WorkerThread.js" },
74
- ];
75
-
76
- /* ---------- main ---------- */
77
- (async function main() {
78
- // Only async if we need to load the shim; users never touch promises.
79
- await ensureImportMapSupport();
80
-
81
- const base = computeNodeModulesBase(); // or { allowGuessAtRoot: true } if you prefer
82
-
83
- // Core SDK (adjust entry filename if different)
84
- const imports = {
85
- "@ideem/zsm-client-sdk": join(base, "@ideem/zsm-client-sdk/ZSMClientSDK.js"),
86
- "@ideem/zsm-client-sdk/": join(base, "@ideem/zsm-client-sdk/"),
87
- };
88
-
89
- // Map all official plugins (harmless unless actually imported)
90
- for (const { pkg, entry } of PLUGINS) {
91
- imports[pkg] = join(base, `${pkg}/${entry}`);
92
- imports[`${pkg}/`] = join(base, `${pkg}/`);
93
- }
94
-
95
- injectImportMap(imports);
96
- })();