@ideem/zsm-client-sdk 2.5.1 → 2.6.1

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) => {
@@ -21,7 +22,12 @@ class WebAuthnClientBase {
21
22
  // Helper function to standardize URL format (ensuring it's parsable and ends with a '/')
22
23
  const cleanURL = (url) => URL.canParse(url) ? new URL(url).origin + '/' : false;
23
24
 
24
- const baseConfig = {
25
+ if(config?.region){
26
+ config.authenticator_host_url ||= config.authenticator_host = `https://zsm-authenticator-${config.region}.useideem.com/`;
27
+ config.zsm_host_url ||= config.zsm_host = `https://zsm-${config.region}.useideem.com/`;
28
+ }
29
+
30
+ const baseConfig = {
25
31
  "application_id" : "",
26
32
  "api_key" : "",
27
33
  "host_url" : "https://zsm-authenticator-demo.useideem.com/",
@@ -29,9 +35,15 @@ class WebAuthnClientBase {
29
35
  "log_level" : 'Debug',
30
36
  "request_timeout_ms" : 300000,
31
37
  "retry_count" : 0,
32
- "consumer_id" : ""
38
+ "consumer_id" : "",
39
+ "use_passkeys" : true
33
40
  };
34
41
 
42
+ if(config?.use_passkeys===false || config?.use_origin===false){
43
+ delete config.use_passkeys;
44
+ delete config.use_origin;
45
+ }
46
+
35
47
  this.zsmApi = undefined; // The ZSM API instance (read: WASM-driven Crypto Module)
36
48
  this.relyingParty = undefined; // The Relying Party instance (read: ZSM Authenticator API)
37
49
  this.status = undefined; // The status of the WebAuthnClientBase
@@ -89,7 +101,7 @@ class WebAuthnClientBase {
89
101
  * @param {Object} config The configuration object for ZSM initialization.
90
102
  * @returns {Promise<ZSMAPI>} Resolves with the initialized ZSM API.
91
103
  */
92
- getZsmApi = async (config) => {}
104
+ async getZsmApi (config) {}
93
105
 
94
106
  /**
95
107
  * @name primeZsmApi
@@ -98,16 +110,15 @@ class WebAuthnClientBase {
98
110
  * @ by the initializeZsm thereafter. Fixes several potential race conditions and improves performance.
99
111
  * @returns {Promise<ZSMAPI>} Resolves with the initialized ZSM API.
100
112
  */
101
- primeZsmApi = async () => (!this.zsmApi) ? (this.zsmApi = await this.getZsmApi(Object.assign({}, GLOBAL.mpcConfig, {consumer_id: await iid4uid(GLOBAL.mpcConfig.consumer_id)}))) : this.zsmApi;
113
+ 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
114
 
103
115
  /**
104
116
  * @name initializeZsm
105
117
  * @description Reconfigures the ZSM API, should the consumer_id change (as after an identity_id is obtained)
106
118
  * @returns {Promise<ZSMAPI>} Resolves when the ZSM API is reconfigured.
107
119
  */
108
- initializeZsm = async () => {
120
+ async initializeZsm () {
109
121
  if(GLOBAL.mpcConfig.consumer_id !== this.MPCConfig.consumer_id) {
110
- // console.log('GLOBAL.mpcConfig :', Object.assign({},GLOBAL.mpcConfig));
111
122
  await this.zsmApi.configure(GLOBAL.mpcConfig);
112
123
  this.MPCConfig = await Object.assign({}, GLOBAL.mpcConfig);
113
124
  await uid2iid(this.config.consumer_id, this.MPCConfig.consumer_id);
@@ -126,22 +137,72 @@ class WebAuthnClientBase {
126
137
  */
127
138
 
128
139
  async checkIdentity (userIdentifier, primeEnroll=false) {
140
+ if(userIdentifier == null
141
+ || userIdentifier === '') return new Error(`[WebAuthnClient] :: checkIdentity :: A userIdentifier String is required! Received: ${userIdentifier}.`);
142
+ if(userIdentifier && typeof userIdentifier === 'string') this.userIdentifier = userIdentifier;
143
+
129
144
  try {
130
- this.status='CHECKING_IDENTITY_STARTING';
131
145
  const resultOfCheck = await this.relyingParty.checkServerSideIdentity(primeEnroll);
146
+
132
147
  if(!resultOfCheck) throw new Error('Unable to communicate with identity server!');
133
- const identityID = resultOfCheck.identity_id;
148
+ const identityID = Array.isArray(resultOfCheck) ? resultOfCheck[0].identity_id : resultOfCheck.identity_id;
149
+
134
150
  if(!identityID) throw new Error('Unable to acquire identity_id!');
151
+
135
152
  uid2iid(userIdentifier, identityID);
136
153
  GLOBAL.mpcConfig.consumer_id = identityID;
137
- this.status = 'CHECKING_IDENTITY_FINISHED';
138
154
  return identityID;
139
155
  } catch(err) {
140
- this.status = 'CHECKING_IDENTITY_FAILED';
141
156
  return Promise.reject(err);
142
157
  }
143
158
  }
144
159
 
160
+ /**
161
+ * @name webauthnCreate
162
+ * @description Creates a new WebAuthn credential for the specified userIdentifier.
163
+ * @param {string} userIdentifier The user identifier.
164
+ * @returns {Promise<Object>} Resolves with the created credential.
165
+ * @throws {Error} Throws a COUNTED error if unable to retrieve the public key from the Relying Party Server.
166
+ * @throws {Error} [MPC] Throws an error if unable to obtain the createResponse from the Crypto Server.
167
+ * @throws {Error} [MPC] Throws an error if the createResponse is missing the credential.
168
+ * @throws {Error} [MPC] Throws an error if the credential is missing the attestation object.
169
+ * @throws {Error} Throws a COUNTED error if unable to verify the credential with the Relying Party Server.
170
+ */
171
+ async webauthnCreate (userIdentifier) {
172
+ if(userIdentifier == null
173
+ || userIdentifier === '') return new Error(`[WebAuthnClient] :: webauthnCreate :: A userIdentifier String is required! Received: ${userIdentifier}.`);
174
+ if(userIdentifier && typeof userIdentifier === 'string') this.userIdentifier = userIdentifier;
175
+
176
+ await this.initializeZsm('webauthnCreate');
177
+
178
+
179
+ const publicKey = await this.relyingParty.registrationStart();
180
+ if(publicKey instanceof Error) throw new Error(publicKey);
181
+ else if (!publicKey) throw new Error('[WebAuthnClient] :: webauthnCreate :: Unable to retrieve public key from Relying Party Server!');
182
+
183
+ publicKey.user_id = publicKey.user.id;
184
+
185
+ let createResponse = await this.zsmApi.webauthn_create(publicKey, undefined, userIdentifier, tracePrimer());
186
+ if(!createResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain response from Crypto Server!');
187
+
188
+
189
+ createResponse = toObject(createResponse);
190
+ GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: createResponse }));
191
+
192
+ if(!createResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain credential from Crypto Server!');
193
+ if(!createResponse?.result?.response) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to acquire attestation object!');
194
+
195
+ const credential = createResponse.result;
196
+
197
+
198
+ const registrationResult = await this.relyingParty.registrationFinish(credential);
199
+ if(registrationResult instanceof Error) throw new Error(registrationResult);
200
+ else if(registrationResult == false) throw new Error('[WebAuthnClient] :: webauthnCreate :: Unable to verify credential Relying Party Server!');
201
+
202
+
203
+ return registrationResult;
204
+ };
205
+
145
206
  /**
146
207
  * @name webauthnCreate
147
208
  * @description Creates a new WebAuthn credential for the specified userIdentifier.
@@ -154,30 +215,28 @@ class WebAuthnClientBase {
154
215
  * @throws {Error} Throws an error if unable to acquire the identity ID from the Relying Party Server.
155
216
  * @throws {Error} Throws an error if the user ID or token is missing from the response body.
156
217
  */
157
- async webauthnCreate (userIdentifier) {
218
+ async webauthnCreateMpcThenFinish (userIdentifier, publicKey, pairing_token) {
219
+ if(userIdentifier == null
220
+ || userIdentifier === '') return new Error(`[WebAuthnClient] :: webauthnCreateMpcThenFinish :: A userIdentifier String is required! Received: ${userIdentifier}.`);
221
+ if(userIdentifier && typeof userIdentifier === 'string') this.userIdentifier = userIdentifier;
158
222
  this.status = 'ENROLLMENT_STARTING';
159
- await this.initializeZsm('webauthnCreate');
160
-
161
- // await this.checkIdentity(userIdentifier, true);
223
+ await this.initializeZsm('webauthnCreateMpcThenFinish');
162
224
 
163
- const publicKey = await this.relyingParty.registrationStart();
164
- if(!publicKey) throw new Error('[WebAuthnClient] :: webauthnCreate :: Unable to retrieve public key from Relying Party Server!');
165
-
166
- let createResponse = await this.zsmApi.webauthn_create(publicKey, tracePrimer());
167
- if(!createResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain response from Crypto Server!');
225
+ let createResponse = await this.zsmApi.webauthn_create(publicKey, pairing_token, userIdentifier, tracePrimer());
226
+ if(!createResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreateMpcThenFinish :: Unable to obtain response from Crypto Server!');
168
227
 
169
228
  createResponse = toObject(createResponse);
170
229
  GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: createResponse }));
171
230
 
172
- if(!createResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain credential from Crypto Server!');
173
- if(!createResponse?.result?.response) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to acquire attestation object!');
231
+ if(!createResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreateMpcThenFinish :: Unable to obtain credential from Crypto Server!');
232
+ if(!createResponse?.result?.response) throw new Error('[WebAuthnClient - mpc_round] :: webauthnCreateMpcThenFinish :: Unable to acquire attestation object!');
174
233
 
175
234
  const credential = createResponse.result;
176
235
 
177
236
  const registrationResult = await this.relyingParty.registrationFinish(credential);
178
- if (!registrationResult) throw new Error('[WebAuthnClient] :: webauthnCreate :: Unable to verify credential Relying Party Server!');
237
+ if (!registrationResult) throw new Error('[WebAuthnClient] :: webauthnCreateMpcThenFinish :: Unable to verify credential Relying Party Server!');
179
238
 
180
- return registrationResult;
239
+ return registrationResult.credential;
181
240
  };
182
241
 
183
242
  /**
@@ -186,95 +245,96 @@ class WebAuthnClientBase {
186
245
  * @param {string} userIdentifier The user identifier.
187
246
  * @returns {Promise<ZSMAPI>} Resolves with the retrieved credential.
188
247
  * @throws {Error} Throws an error if no credential ID is found.
189
- * @throws {Error} Throws an error if unable to start authentication with the Relying Party Server.
248
+ * @throws {Error} Throws a COUNTED error if unable to start authentication with the Relying Party Server.
190
249
  * @throws {Error} Throws an error if unable to retrieve the public key/challenge from the Relying Party Server.
191
- * @throws {Error} Throws an error if unable to obtain the getResponse/credential from the Crypto Server.
250
+ * @throws {Error} Throws an error if unable to obtain the mpcResponse/credential from the Crypto Server.
192
251
  * @throws {Error} Throws an error if unable to verify the credential with the Relying Party Server.
193
252
  * @throws {Error} Throws an error if the user ID or token is missing from the response body.
194
253
  */
195
- webauthnGet = async (userIdentifier) => {
196
- this.status = 'AUTHENTICATION_STARTING';
254
+ async webauthnGet (userIdentifier) {
255
+ if(userIdentifier == null
256
+ || userIdentifier === '') return new Error(`[WebAuthnClient] :: webauthnGet :: A userIdentifier String is required! Received: ${userIdentifier}.`);
257
+ if(userIdentifier && typeof userIdentifier === 'string') this.userIdentifier = userIdentifier;
197
258
 
198
259
  await this.initializeZsm('webauthnGet');
199
- await this.webauthnRetrieve(userIdentifier, true)
200
-
260
+ const credentialId = await this.webauthnRetrieve(userIdentifier, true);
201
261
 
202
- if (!this.isEnrolled) throw new Error(`[WebAuthnClient] :: webauthnGet :: Credential is missing for ${userIdentifier}`);
262
+ if (!this.isEnrolled) throw new Error(`[WebAuthnClient] :: webauthnGet :: ${userIdentifier} is not enrolled, lacks a credential, or credential is corrupted!`);
203
263
 
204
- let authStartResponse = await this.relyingParty.authenticationStart(this.credentialID);
205
- if(!authStartResponse) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to start authentication with Relying Party Server!');
264
+ let authStartResponse = await this.relyingParty.authenticationStart(credentialId);
206
265
 
266
+ if (authStartResponse instanceof Error) throw new Error(authStartResponse);
267
+ else if (!authStartResponse) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to start authentication with Relying Party Server!');
268
+
207
269
  authStartResponse = toObject(authStartResponse);
208
270
 
209
- if(!authStartResponse?.rcr || !authStartResponse?.rcr?.publicKey) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to retrieve public key from Relying Party Server!');
210
-
211
- const pubKey = authStartResponse?.rcr?.publicKey;
271
+ 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));
272
+ const publicKey = authStartResponse.rcr.publicKey;
212
273
 
213
- if(!pubKey || !pubKey?.challenge) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to acquire challenge from public key!');
274
+ let mpcResponse = await this.zsmApi.webauthn_get(publicKey, undefined, userIdentifier, tracePrimer());
275
+
214
276
 
215
- let getResponse = await this.zsmApi.webauthn_get(pubKey, tracePrimer());
216
- if(!getResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain getResponse from Crypto Server!');
277
+ if(!mpcResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Crypto server did not respond!');
217
278
 
218
- getResponse = toObject(getResponse);
279
+ mpcResponse = toObject(mpcResponse);
280
+ if(!mpcResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Response from Crypto Server did not contain a credential!\nResponse Body: ' + JSON.stringify(mpcResponse));
219
281
 
220
- if(!getResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain credential from Crypto Server!');
282
+ GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: mpcResponse }));
221
283
 
222
- GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: getResponse }));
223
-
224
- const credential = getResponse.result;
284
+ const credential = mpcResponse.result;
225
285
  let authFinishResponse = await this.relyingParty.authenticationFinish(credential);
226
286
 
227
- if (!authFinishResponse) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to verify credential Relying Party Server!');
287
+ if (authFinishResponse instanceof Error) throw new Error(authFinishResponse);
288
+ else if (!authFinishResponse) throw new Error('[WebAuthnClient] :: webauthnGet :: Unable to verify credential from Relying Party Server!');
228
289
 
229
290
  authFinishResponse = toObject(authFinishResponse)
230
-
231
- if (!authFinishResponse.user_id || !authFinishResponse.token) throw new Error('[WebAuthnClient] :: webauthnGet :: User ID or token is missing from response body!');
291
+ if (!authFinishResponse.token) throw new Error('[WebAuthnClient] :: webauthnGet :: Token mismatched or missing from Relying Party Server verification attempt!\nResponse Body: ' + JSON.stringify(authFinishResponse));
232
292
 
233
293
  return {
234
294
  signature : credential.response.signature,
235
295
  signedChallenge : credential.response.clientDataJSON,
236
296
  user_id : authFinishResponse.user_id,
237
297
  token : authFinishResponse.token,
238
- challenge : pubKey.challenge,
298
+ challenge : publicKey.challenge,
239
299
  credential
240
300
  };
241
301
  };
242
302
 
303
+
304
+
243
305
  /**
244
306
  * @name webauthnRetrieve
245
307
  * @description Looks up the Identity ID for the specified userIdentifier and retrieves its credential ID (if it exists).
246
308
  * @ This is used to make a client-only check to see if a given userIdentifier already has an enrollment on the device.
247
309
  * @param {string} userIdentifier The user identifier.
248
- * @param {boolean} silent Whether to suppress status updates. [default: false]
249
- * @returns {Promise<Boolean>} Resolves with the credential ID or `false` if retrieval fails.
250
- * @returns {Promise<String>} Resolves with the retrieved rawID for the specified user.
310
+ * @param {string} targetData The specific data to retrieve. Options are:
311
+ * @ - 'id' or omitted: retrieves the ZSM credential ID (default)
312
+ * @ - 'all': retrieves an object containing all relevant credential data
313
+ * @ - any other string: retrieves the specified field from the response
314
+ * @returns {Promise<Boolean:false>} Returns `false` if retrieval fails (no enrollment found).
315
+ * @returns {Promise<String>} Returns the requested data if found (e.g., ").
316
+ * @returns {Promise<Object>} Resolves with an object containing all relevant credential data.
317
+ * @returns {Promise<Null>} Resolves with null if the requested data is not found.
318
+ * @throws {Error} Throws an error if an uncaught/unhandled error occurs while retrieving the credential.
251
319
  */
252
- webauthnRetrieve = async (userIdentifier, silent=false) => {
320
+ async webauthnRetrieve (userIdentifier) {
321
+ if(userIdentifier == null
322
+ || userIdentifier === '') return new Error(`[WebAuthnClient] :: webauthnRetrieve :: A userIdentifier String is required! Received: ${userIdentifier}.`);
323
+ if(userIdentifier && typeof userIdentifier === 'string') this.userIdentifier = userIdentifier;
253
324
  this.credentialID = null;
254
- if (!silent) {
255
- this.status = 'CREDENTIAL_RETRIEVING';
256
- }
257
-
258
- try {
259
- this.initializeZsm('webauthnRetrieve');
260
- let credentialIdentifier = await iid4uid(userIdentifier);
261
- GLOBAL.mpcConfig.consumer_id = credentialIdentifier;
262
325
 
263
- let response = await this.zsmApi.webauthn_retrieve(credentialIdentifier);
264
- response = toObject(response);
326
+ this.initializeZsm('webauthnRetrieve');
327
+ let credentialIdentifier = await iid4uid(userIdentifier),
328
+ requestedData = {};
329
+ GLOBAL.mpcConfig.consumer_id = credentialIdentifier;
265
330
 
266
- if (response.error || !response?.result?.rawId) return false;
331
+ let response = await this.zsmApi.webauthn_retrieve(userIdentifier);
332
+ response = toObject(response);
267
333
 
268
- this.credentialID = response.result.rawId;
269
- if (!silent) this.status = 'CREDENTIAL_RETRIEVED';
270
-
271
- return this.credentialID;
272
- } catch (error) {
273
- if(!silent){
274
- this.status = 'CREDENTIAL_RETRIEVAL_FAILED';
275
- throw error;
276
- }
277
- }
334
+ if (response?.error || !response?.result) return false;
335
+
336
+ this.credentialID = response?.result['zsm_credential_id']??null;
337
+ return this.credentialID || false;
278
338
  };
279
339
 
280
340
  /**
@@ -285,10 +345,13 @@ class WebAuthnClientBase {
285
345
  * @throws {Error} Throws an error if the credential is missing for the userIdentifier provided.
286
346
  * @throws {Error} Throws an error if unable to start authentication with the Relying Party Server.
287
347
  * @throws {Error} Throws an error if unable to retrieve the public key from the Relying Party Server.
288
- * @throws {Error} Throws an error if unable to obtain the getResponse/credential from the Crypto Server.
289
- * @emits {CustomEvent} Emits a "MPCResponse" event with the getResponse data.
348
+ * @throws {Error} Throws an error if unable to obtain the mpcResponse/credential from the Crypto Server.
349
+ * @emits {CustomEvent} Emits a "MPCResponse" event with the mpcResponse data.
290
350
  */
291
- webauthnPartialGet = async (userIdentifier) => {
351
+ async webauthnPartialGet (userIdentifier) {
352
+ if(userIdentifier == null
353
+ || userIdentifier === '') return new Error(`[WebAuthnClient] :: webauthnPartialGet :: A userIdentifier String is required! Received: ${userIdentifier}.`);
354
+ if(userIdentifier && typeof userIdentifier === 'string') this.userIdentifier = userIdentifier;
292
355
  this.status = 'AUTHENTICATION_STARTING';
293
356
  await this.initializeZsm('webauthnPartialGet');
294
357
 
@@ -302,16 +365,16 @@ class WebAuthnClientBase {
302
365
  if(!getChallenge?.rcr || !getChallenge.rcr.publicKey) throw new Error('[WebAuthnClient] :: webauthnPartialGet :: Unable to retrieve public key from Relying Party Server!');
303
366
  const pubKey = getChallenge.rcr.publicKey;
304
367
 
305
- let getResponse = await this.zsmApi.webauthn_get(pubKey, tracePrimer());
306
- if(!getResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain getResponse from Crypto Server!');
368
+ let mpcResponse = await this.zsmApi.webauthn_get(pubKey, null, userIdentifier, tracePrimer());
369
+ if(!mpcResponse) throw new Error('[WebAuthnClient - mpc_round] :: webauthnPartialGet :: Unable to obtain mpcResponse from Crypto Server!');
307
370
 
308
- getResponse = toObject(getResponse);
371
+ mpcResponse = toObject(mpcResponse);
309
372
 
310
- if(!getResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnGet :: Unable to obtain credential from Crypto Server!');
373
+ if(!mpcResponse?.result) throw new Error('[WebAuthnClient - mpc_round] :: webauthnPartialGet :: Unable to obtain credential from Crypto Server!');
311
374
 
312
- GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: getResponse }));
375
+ GLOBAL.dispatchEvent(new CustomEvent("MPCResponse", {bubbles: true, cancelable: false, detail: mpcResponse }));
313
376
 
314
- const getCredential = getResponse.result;
377
+ const getCredential = mpcResponse.result;
315
378
  return {
316
379
  signature: getCredential.response.signature,
317
380
  signedChallenge: getCredential.response.clientDataJSON,
@@ -330,7 +393,10 @@ class WebAuthnClientBase {
330
393
  * @throws {Error<CredentialError>} Throws an CredentialError if the credential is missing for the userIdentifier provided
331
394
  * @throws {Error<UnenrollError>} Throws an UnenrollError if a credential matching userIdentifier IS stored on the device, but was unable to be removed.
332
395
  */
333
- unbindFromDevice = async (userIdentifier) => {
396
+ async unbindFromDevice (userIdentifier) {
397
+ if(userIdentifier == null
398
+ || userIdentifier === '') return new Error(`[WebAuthnClient] :: unbindFromDevice :: A userIdentifier String is required! Received: ${userIdentifier}.`);
399
+ if(userIdentifier && typeof userIdentifier === 'string') this.userIdentifier = userIdentifier;
334
400
  this.status = 'UNENROLL_STARTING';
335
401
  if(userIdentifier !== this.userIdentifier) return false;
336
402
  await this.initializeZsm('unbindFromDevice');
@@ -346,7 +412,11 @@ class WebAuthnClientBase {
346
412
  const cursor = event.target.result;
347
413
  if (cursor) {
348
414
  const { key, value } = cursor;
349
- if (value instanceof Map && value.has("rawId") && value.get("rawId") === rawID) return (store.delete(key), true);
415
+ if(
416
+ key.includes(userIdentifier) ||
417
+ (typeof value === 'string' && value.includes(userIdentifier)) ||
418
+ typeof value === 'object' && value?.zsm_credential?.get('rawId') === rawID
419
+ ) (store.delete(key), true);
350
420
  cursor.continue();
351
421
  }
352
422
  };
package/package.json CHANGED
@@ -1,23 +1,70 @@
1
1
  {
2
- "name" : "@ideem/zsm-client-sdk",
3
- "version" : "2.5.1",
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 \\\")\""
12
- },
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"
18
- },
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
2
+ "name" : "@ideem/zsm-client-sdk",
3
+ "version" : "2.6.1",
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" : "Jason Jurusz <jj@useideem.com>",
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
+ "type" : "module",
8
+ "main" : "./ZSMClientSDK.js",
9
+ "exports" : {
10
+ ".": {
11
+ "import": "./ZSMClientSDK.js",
12
+ "default": "./ZSMClientSDK.js"
13
+ }
14
+ },
15
+ "scripts" : {
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
+ "showVersion" : "echo \"$(npm pkg get name | tr -d \\\") current version: $(npm pkg get version | tr -d \\\")\""
18
+ },
19
+ "collaborators" : [
20
+ "Joel Teply <joel@useideem.com>",
21
+ "Todd Decker <todd@useideem.com>",
22
+ "Brian Koziel <brian@useideem.com>"
23
+ ],
24
+ "license" : "LicenseRef-Ideem",
25
+ "repository" : {
26
+ "type" : "git",
27
+ "url" : "git+https://github.com/useideem/vHSM.git"
28
+ },
29
+ "homepage" : "https://useideem.com",
30
+ "bugs" : "https://github.com/useideem/vHSM/issues",
31
+ "files" : [
32
+ "./shims/",
33
+ "./ErrorHandler.js",
34
+ "./EventCoordinator.js",
35
+ "./FIDO2Client.js",
36
+ "./FIDO2ClientBase.js",
37
+ "./GlobalScoping.js",
38
+ "./IdentityIndexing.js",
39
+ "./PluginManager.js",
40
+ "./RelyingParty.js",
41
+ "./RelyingPartyBase.js",
42
+ "./UMFAClient.js",
43
+ "./UMFAClientBase.js",
44
+ "./Utils.js",
45
+ "./WASMRustInterface.js",
46
+ "./WebAuthnClient.js",
47
+ "./WebAuthnClientBase.js",
48
+ "./ZSMClientSDK.js",
49
+ "./CHANGELOG.md",
50
+ "./LICENSE",
51
+ "./README.md"
52
+ ],
53
+ "sideEffects" : [
54
+ "./EventCoordinator.js",
55
+ "./FIDO2Client.js",
56
+ "./FIDO2ClientBase.js",
57
+ "./GlobalScoping.js",
58
+ "./IdentityIndexing.js",
59
+ "./PluginManager.js",
60
+ "./RelyingParty.js",
61
+ "./RelyingPartyBase.js",
62
+ "./UMFAClient.js",
63
+ "./UMFAClientBase.js",
64
+ "./Utils.js",
65
+ "./WASMRustInterface.js",
66
+ "./WebAuthnClient.js",
67
+ "./WebAuthnClientBase.js",
68
+ "./ZSMClientSDK.js"
69
+ ]
23
70
  }