@ideem/zsm-client-sdk 2.9.3 → 2.9.4

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.
@@ -1 +1 @@
1
- import e from"./EventCoordinator.js";import t from"./GlobalScoping.js";import{uid2iid as r,iid4uid as i}from"./IdentityIndexing.js";import{toObject as n}from"./Utils.js";import{zsmPluginManager as s}from"./PluginManager.js";import a from"./PasskeysPlusClient.js";e.update("WebAuthnClientBase");const o=(e=!1)=>{const t=[[(new Date).toISOString(),"TRACEPRIMER"]];return e?{trace:t}:t};export default class{constructor(r){const n=e=>!!(e=>{try{return new URL(e),!0}catch{return!1}})(e)&&new URL(e).origin+"/";this.passkeysPlus=new a,r?.region&&(r.authenticator_host_url||=r.authenticator_host=`https://zsm-authenticator-${r.region}.useideem.com/`,r.zsm_host_url||=r.zsm_host=`https://zsm-${r.region}.useideem.com/`);const o={application_id:"",api_key:"",host_url:"https://zsm-authenticator-demo.useideem.com/",installation_description:"undefined"!=typeof navigator?navigator?.userAgent:"No Agent Found",log_level:"Debug",request_timeout_ms:3e5,retry_count:0,consumer_id:"",use_passkeys:!0};!1!==r?.use_passkeys&&!1!==r?.use_origin||(delete r.use_passkeys,delete r.use_origin),this.zsmApi=void 0,this.relyingParty=void 0,this.status=void 0,this.config=void 0,r.host_url=n(r.host_url)||null,null==r.host_url&&null!=r.host&&(r.host_url=n(r.host)||`https://zsm-authenticator-${r.host}.useideem.com/`),n(r.host_url)||delete r.host_url,r=Object.assign(o,r),r?.authenticator_host_url||(r.authenticator_host=r.authenticator_host_url=r.host_url),r?.zsm_host_url||(r.zsm_host_url=r.zsm_host=r.host_url.replace("zsm-authenticator","zsm")),r.host_url=r.zsm_host_url,r.api_key||=r?.application_id||"NO APPLICATION_ID PROVIDED! CHECK YOUR zsm_app_config.json!",this.config=t.zsmAppConfig=r,i(this.config.consumer_id).then(e=>{t.mpcConfig=Object.assign({},r,{consumer_id:e}),t.mpcConfig?.use_passkeys&&(t.mpcConfig.use_origin=!0,delete t.mpcConfig.use_passkeys),this.MPCConfig=Object.assign({},t.mpcConfig),this.zsmApi=this.primeZsmApi();const i=s.classes("RELYINGPARTY");this.relyingParty=new i(this.config.authenticator_host_url,this.config.api_key,this.config.application_id,this.config.application_environment,this.config?.use_passkeys??void 0,this.config.metadata),this.userIdentifier=r.consumer_id}).then(()=>t.dispatchEvent(new CustomEvent("WebAuthnClientReady",{bubbles:!0,cancelable:!1,detail:!0}))).catch(e=>console.error("Error during initialization:",e)).finally(()=>e.update("WebAuthnClientBase","READY"))}get userIdentifier(){return this.relyingParty.customerDefinedIdentifier}set userIdentifier(e){return this.relyingParty.customerDefinedIdentifier=e}get customerDefinedIdentifier(){return this.relyingParty.customerDefinedIdentifier}set customerDefinedIdentifier(e){return this.relyingParty.customerDefinedIdentifier=e}get token(){return this.relyingParty.token}get credentialID(){return this.relyingParty.credentialID}set credentialID(e){return this.relyingParty.credentialID=e}get isEnrolled(){return!!this.credentialID}get metadata(){return this.relyingParty.metadata}set metadata(e){return this.relyingParty.metadata=e}async getZsmApi(e){}async primeZsmApi(){return this.zsmApi?this.zsmApi:this.zsmApi=await this.getZsmApi(Object.assign({},t.mpcConfig,{consumer_id:await i(t.mpcConfig.consumer_id)}))}async initializeZsm(){return t.mpcConfig.consumer_id!==this.MPCConfig.consumer_id&&(await this.zsmApi.configure(t.mpcConfig),this.MPCConfig=await Object.assign({},t.mpcConfig),await r(this.config.consumer_id,this.MPCConfig.consumer_id)),await this.zsmApi}async checkIdentity(e,i=!1){if(null==e||""===e)throw new Error(`[WebAuthnClient] :: checkIdentity :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e);try{const n=await this.relyingParty.checkServerSideIdentity(i);if(!n)throw new Error("Unable to communicate with identity server!");const s=Array.isArray(n)?n[0].identity_id:n.identity_id;if(!s)throw new Error("Unable to acquire identity_id!");return r(e,s),t.mpcConfig.consumer_id=s,s}catch(e){return Promise.reject(e)}}async webauthnRetrieve(e,r=!1,s=!1){if(null==e||"string"!=typeof e||""===e)throw new Error(`[WebAuthnClient] :: webauthnRetrieve :: A userIdentifier String is required! Received: ${e} (of type ${typeof e}).`);e&&"string"==typeof e&&(this.userIdentifier=e),this.credentialID=null,this.initializeZsm("webauthnRetrieve");let a=await i(e);t.mpcConfig.consumer_id=a;const o=await this.zsmApi.webauthn_retrieve(e);let l=n(o);if(!r)return!(l?.error||!l?.result)&&(this.credentialID=l.result.zsm_credential_id??null);l=l?.error||!l?.result?{}:l.result;let u=!1;try{u=!!navigator?.credentials}catch{}this.credentialID=l.zsm_credential_id??null;let h=l;if(s||u&&!l?.has_remote_passkey&&!l?.passkey_credential_id||!l?.zsm_active||!l?.zsm_active){let t=await this.checkRemoteEnrollmentDetails(e,h);!t||t instanceof Error||(h=Object.assign({},l,t))}const c={userIdentifier:e,enrollmentActive:h?.zsm_active??!1,passkeySupported:u,passkeyEligible:u&&!(!h?.passkey_credential_id&&!h?.has_remote_passkey),hasLocalPasskey:u&&!!h?.passkey_credential_id,hasRemotePasskey:!!h?.rcr??null,pkpCredentialID:h?.passkey_credential_id??null,pkpCredID:h?.passkey_credential_id??null,hasZSMCred:!!h?.zsm_credential||!1,zsmCredential:h?.zsm_credential??null,zsmCredentialID:h?.zsm_credential_id??null,zsmCredID:h?.zsm_credential_id??null,isUsingPasswordManager:CredentialsContainer.prototype.get.toString()===navigator.credentials.get.toString()};return!0===c.hasLocalPasskey&&(c.hasRemotePasskey=!0),h?.rcr&&(c.pkpCredential=h.rcr,c.hasLocalPasskey=!0,c.pkpCredentialID||(c.pkpCredentialID=h.rcr?.publicKey?.allowCredentials?.flatMap(e=>e.id)??null,c.pkpCredentialID.length&&(c.pkpCredentialID=c.pkpCredentialID[0]))),c}async webauthnRetrieveAll(e,t=!1){return await this.webauthnRetrieve(e,!0,t)}async checkRemoteEnrollmentDetails(e,t){try{const r=await this.relyingParty.getRemoteEnrollmentDetails(e,t);return!(r instanceof Error||!r||null==r.identity_id)&&r}catch(e){return console.error("Error checking remote enrollment details:",e),!1}}async webauthnCreate(e){if(!e)throw new Error(`[WebAuthnClient] :: webauthnCreate :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e),await this.initializeZsm("webauthnCreate");const r=await this.relyingParty.registrationStart();if(r instanceof Error)throw new Error(r);if(!r)throw new Error("[WebAuthnClient] :: webauthnCreate :: Unable to retrieve public key from Relying Party Server!");r.user_id=r.user.id;let i=await this.zsmApi.webauthn_create(r,void 0,e,o());if(!i)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain response from Crypto Server!");if(i=n(i),t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:i})),!i?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain credential from Crypto Server!");if(!i?.result?.response)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to acquire attestation object!");const s=i.result,a=await this.relyingParty.registrationFinish(s);if(a instanceof Error)throw new Error(a);if(0==a)throw new Error("[WebAuthnClient] :: webauthnCreate :: Unable to verify credential Relying Party Server!");return a}async webauthnGet(e){if(null==e||""===e)throw new Error(`[WebAuthnClient] :: webauthnGet :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e),await this.initializeZsm("webauthnGet");const r=await this.webauthnRetrieve(e,!0);if(!this.isEnrolled)throw new Error(`[WebAuthnClient] :: webauthnGet :: ${e} is not enrolled, lacks a credential, or credential is corrupted!`);let i=await this.relyingParty.authenticationStart(r);if(i instanceof Error)throw new Error(i);if(!i)throw new Error("[WebAuthnClient] :: webauthnGet :: Unable to start authentication with Relying Party Server!");if(i=n(i),!i?.rcr?.publicKey?.challenge)throw new Error("[WebAuthnClient] :: webauthnGet :: Unable to locate public key/challenge inside Relying Party Server response!\nResponse Body: "+JSON.stringify(i));const s=i.rcr.publicKey;let a=await this.zsmApi.webauthn_get(s,void 0,e,o());if(!a)throw new Error("[WebAuthnClient - mpc_round] :: webauthnGet :: Crypto server did not respond!");if(a=n(a),!a?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnGet :: Response from Crypto Server did not contain a credential!\nResponse Body: "+JSON.stringify(a));return t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:a})),a.result}async webauthnPartialGet(e){if(null==e||""===e)throw new Error(`[WebAuthnClient] :: webauthnPartialGet :: A userIdentifier String is required! Received: ${e}.`);if(e&&"string"==typeof e&&(this.userIdentifier=e),this.status="AUTHENTICATION_STARTING",await this.initializeZsm("webauthnPartialGet"),!this.isEnrolled)throw new Error(`[WebAuthnClient] :: webauthnPartialGet :: Credential is missing for ${e}`);let r=await this.relyingParty.authenticationStart(this.credentialID);if(!r)throw new Error("[WebAuthnClient] :: webauthnPartialGet :: Unable to start authentication with Relying Party Server!");if(r=n(r),!r?.rcr||!r.rcr.publicKey)throw new Error("[WebAuthnClient] :: webauthnPartialGet :: Unable to retrieve public key from Relying Party Server!");const i=r.rcr.publicKey;let s=await this.zsmApi.webauthn_get(i,null,e,o());if(!s)throw new Error("[WebAuthnClient - mpc_round] :: webauthnPartialGet :: Unable to obtain mpcResponse from Crypto Server!");if(s=n(s),!s?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnPartialGet :: Unable to obtain credential from Crypto Server!");return t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:s})),s.result}async unbindFromDevice(e){if(null==e||""===e)throw new Error(`[WebAuthnClient] :: unbindFromDevice :: A userIdentifier String is required! Received: ${e}.`);if(e&&"string"==typeof e&&(this.userIdentifier=e),this.status="UNENROLL_STARTING",e!==this.userIdentifier)return!1;await this.initializeZsm("unbindFromDevice");const t=await this.webauthnRetrieve(e);if(!t)return!1;const r=await i(e);return await new Promise((i,n)=>{const s=indexedDB.open("ideem",1);s.onerror=()=>n(new Error(`[WebAuthnClient] :: unbindFromDevice :: Unable to open indexedDB for ${e}`)),s.onsuccess=s=>{const a=s.target.result.transaction("zsm","readwrite"),o=a.objectStore("zsm");a.oncomplete=()=>i(),a.onerror=()=>n(new Error(`[WebAuthnClient] :: unbindFromDevice :: transaction failed for ${e}`)),a.onabort=()=>n(new Error(`[WebAuthnClient] :: unbindFromDevice :: transaction aborted for ${e}`));const l=o.openCursor();l.onerror=()=>n(new Error(`[WebAuthnClient] :: unbindFromDevice :: cursor failed for ${e}`)),l.onsuccess=i=>{const n=i.target.result;if(n){const{key:i,value:s}=n,a="string"==typeof s&&(s.includes(e)||s===r),l="object"==typeof s&&null!==s&&s.zsm_credential instanceof Map&&s.zsm_credential.get("rawId")===t;(i.includes(e)||a||l)&&o.delete(i),n.continue()}}}}),this.status="UNENROLL_COMPLETE",!0}async webauthnCreateFromPKP(e,r,i){if(null==e||""===e)throw new TypeError(`[PK+ WebAuthnClient] :: webauthnCreateFromPKP :: A userIdentifier String is required! Received: ${e}.`);if(e&&"string"==typeof e&&(this.userIdentifier=e),!r)throw new TypeError("[WebAuthnClient] :: webauthnCreateFromPKP :: Missing publicKey parameter!");if(!i)throw new TypeError("[WebAuthnClient] :: webauthnCreateFromPKP :: Missing pairing_token parameter!");await this.initializeZsm("webauthnCreate");let s=await this.zsmApi.webauthn_create(r,i,e);if(!s)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreateFromPKP :: Unable to obtain response from Crypto Server!");if(s=n(s),t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:s})),!s?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreateFromPKP :: Unable to obtain credential from Crypto Server!");if(!s?.result?.response)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreateFromPKP :: Unable to acquire attestation object!");return s.result}async webauthnGetFromPKP(e,r,i){if(null==e||""===e)throw new Error(`[PK+ WebAuthnClient] :: webauthnGetFromPKP :: A userIdentifier String is required! Received: ${e}.`);if(e&&"string"==typeof e&&(this.userIdentifier=e),!r)throw new TypeError("[WebAuthnClient] :: webauthnGetFromPKP :: Missing publicKey parameter!");if(!i)throw new TypeError("[WebAuthnClient] :: webauthnGetFromPKP :: Missing pairing_token parameter!");let s=await this.zsmApi.webauthn_get(r,i,e);if(!s)throw new Error("[WebAuthnClient - mpc_round] :: webauthnGetFromPKP :: Crypto server did not respond!");if(s=n(s),!s?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnGetFromPKP :: Response from Crypto Server did not contain a credential!\nResponse Body: "+JSON.stringify(s));t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:s}));return s.result}async pkpCreate(e,t="preferred",i=!1,n=!1){let s=null;if(i&&"object"==typeof e){const r=Object.assign({},e);if(s=e.zsmCredentialID,this.userIdentifier=e=e.userIdentifier,null==e||"string"!=typeof e||""===e)throw new TypeError(`[PK+ WebAuthnClient] :: pkpCreate :: A userIdentifier String is required! Received: ${e}.`);this.userIdentifier=e;const i=await this.relyingParty.pkpAuthenticationStart(r);if(!i)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: No response from ZSM API's attempt to interface with Relying Party Server!");const n=await this.passkeysPlus.pkpGetPasskeyCredential(i,t);if(!n)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: Unable to call Platform Authenticator to create Passkey!");const a=await this.relyingParty.pkpAuthenticationFinish(n);if(!a)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: Platform Authenticator response was invalid!");const o=a?.response?.ccr?.publicKey??a?.response?.rcr?.publicKey;let l=await this.webauthnGetFromPKP(e,o,a.response.token);return this.zsmCredentialId=l.rawId,Promise.resolve(l)}{if(null==e||"string"!=typeof e||""===e)throw new TypeError(`[PK+ WebAuthnClient] :: pkpCreate :: A userIdentifier String is required! Received: ${e}.`);this.userIdentifier=e;const i=await this.relyingParty.pkpRegistrationStart(e,t,s,n);if(!i)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: No response from ZSM API's attempt to interface with Relying Party Server!");const a=i?.publicKey;if(!a)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: No publicKey found in Relying Party Challenge!");const o=await this.passkeysPlus.pkpCreatePasskeyCredential(a,t);if(!o)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: Unable to call Platform Authenticator to create Passkey!");const l=await this.relyingParty.pkpRegistrationFinish(o);if(!l)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: Platform Authenticator response was invalid!");r("pk:"+e,o.id);const u=l?.response?.ccr?.publicKey??l?.response?.rcr?.publicKey;let h=await this.webauthnCreateFromPKP(e,u,l.response.token);return this.zsmCredentialId=h.rawId,Promise.resolve(h)}}async pkpAuthenticate(e,t="preferred",r=!1){let i=null;if(e&&"object"==typeof e&&(i={...e},this.userIdentifier=e=e.userIdentifier),null==e||""===e)throw new Error(`[PK+ WebAuthnClient] :: pkpAuthenticate :: A userIdentifier String is required! Received: ${e}.`);let n=null;if(this.userIdentifier=e,n=await this.relyingParty.pkpAuthenticationStart(i),!n)throw new Error("[PK+ WebAuthnClient] :: pkpAuthenticate :: Unable to retrieve Platform Authority Challenge from Relying Party Server!");const s=await this.passkeysPlus.pkpGetPasskeyCredential(n,t);if(!s)throw new Error("[PK+ WebAuthnClient] :: pkpAuthenticate :: Unable to call Platform Authenticator to create Passkey!");const a=await this.relyingParty.pkpAuthenticationFinish(s);if(!a)throw new Error("[PK+ WebAuthnClient] :: pkpAuthenticate :: Platform Authenticator response was invalid!");const o=a?.response?.ccr?.publicKey??a?.response?.rcr?.publicKey;return r?await this.webauthnCreateFromPKP(e,o,a.response.token):await this.webauthnGetFromPKP(e,o,a.response.token)}async pkpAddZSMCredential(e){if(null==e||""===e)throw new Error(`[PK+ WebAuthnClient] :: pkpAddZSMCredential :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e);const t=await this.webauthnRetrieveAll(e);if(!1===t)throw new Error("[PK+ WebAuthnClient] :: pkpAddZSMCredential :: Cannot add ZSM; no passkey credentials registered for this user!");return t.userIdentifier=e,this.pkpAuthenticate(t,"required",!0)}async pkpAddPasskeyCredential(e,t="preferred"){let r=null;if(e&&"object"==typeof e?(r={...e},this.userIdentifier=e=e.userIdentifier):(this.userIdentifier=e,r=await this.webauthnRetrieveAll(e,!0)),r instanceof Error)throw new Error(`[WebAuthnClient] :: pkpAddPasskeyCredential :: Unable to retrieve existing credentials for userIdentifier: ${e}. Details: ${r.message||r}`);if(!r?.zsmCredentialID)throw new Error(`[WebAuthnClient] :: pkpAddPasskeyCredential :: userIdentifier: ${e} does not have an existing ZSM credential!`);return this.pkpCreate(r.hasLocalPasskey?Object.assign({},r,{userIdentifier:e}):e,t,r.hasLocalPasskey)}async checkForPasskeysOnOtherDevice(e){if(null==e||""===e)throw new Error(`[PK+ WebAuthnClient] :: checkForPasskeysOnOtherDevice :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e);try{this.userIdentifier=e;const t=await this.relyingParty.makePostRequest("api/passkey/bootstrap/start").catch(e=>!1);return!(!t||t instanceof Error)&&(0!==(t?.rcr?.publicKey?.allowCredentials?.length??0)&&((t?.rcr?.publicKey?.allowCredentials?.length??0)>=1?(r("pk:"+e,t.rcr.publicKey.allowCredentials[0].id),t.rcr.publicKey.allowCredentials[0].id):(t?.rcr?.publicKey?.challenge&&(t.rcr.publicKey.challenge=this.passkeysPlus.toArrayBuffer(t.rcr.publicKey.challenge)),t?.rcr?.publicKey?.allowCredentials&&(t.rcr.publicKey.allowCredentials=t.rcr.publicKey.allowCredentials.map(e=>({...e,id:this.passkeysPlus.toArrayBuffer(e.id)}))),t)))}catch(e){return!1}}webauthnReset=()=>this.relyingParty.resetAll();resetDevice=this.webauthnReset}
1
+ import e from"./EventCoordinator.js";import t from"./GlobalScoping.js";import{uid2iid as r,iid4uid as i}from"./IdentityIndexing.js";import{toObject as n}from"./Utils.js";import{zsmPluginManager as s}from"./PluginManager.js";import a from"./PasskeysPlusClient.js";e.update("WebAuthnClientBase");const o=(e=!1)=>{const t=[[(new Date).toISOString(),"TRACEPRIMER"]];return e?{trace:t}:t};export default class{constructor(r){const n=e=>!!(e=>{try{return new URL(e),!0}catch{return!1}})(e)&&new URL(e).origin+"/";this.passkeysPlus=new a,r?.region&&(r.authenticator_host_url||=r.authenticator_host=`https://zsm-authenticator-${r.region}.useideem.com/`,r.zsm_host_url||=r.zsm_host=`https://zsm-${r.region}.useideem.com/`);const o={application_id:"",api_key:"",host_url:"https://zsm-authenticator-demo.useideem.com/",installation_description:"undefined"!=typeof navigator?navigator?.userAgent:"No Agent Found",log_level:"Debug",request_timeout_ms:3e5,retry_count:0,consumer_id:"",use_passkeys:!0};!1!==r?.use_passkeys&&!1!==r?.use_origin||(delete r.use_passkeys,delete r.use_origin),this.zsmApi=void 0,this.relyingParty=void 0,this.status=void 0,this.config=void 0,r.host_url=n(r.host_url)||null,null==r.host_url&&null!=r.host&&(r.host_url=n(r.host)||`https://zsm-authenticator-${r.host}.useideem.com/`),n(r.host_url)||delete r.host_url,r=Object.assign(o,r),r?.authenticator_host_url||(r.authenticator_host=r.authenticator_host_url=r.host_url),r?.zsm_host_url||(r.zsm_host_url=r.zsm_host=r.host_url.replace("zsm-authenticator","zsm")),r.host_url=r.zsm_host_url,r.api_key||=r?.application_id||"NO APPLICATION_ID PROVIDED! CHECK YOUR zsm_app_config.json!",this.config=t.zsmAppConfig=r,i(this.config.consumer_id).then(e=>{t.mpcConfig=Object.assign({},r,{consumer_id:e}),t.mpcConfig?.use_passkeys&&(t.mpcConfig.use_origin=!0,delete t.mpcConfig.use_passkeys),this.MPCConfig=Object.assign({},t.mpcConfig),this.zsmApi=this.primeZsmApi();const i=s.classes("RELYINGPARTY");this.relyingParty=new i(this.config.authenticator_host_url,this.config.api_key,this.config.application_id,this.config.application_environment,this.config?.use_passkeys??void 0,this.config.metadata),this.userIdentifier=r.consumer_id}).then(()=>t.dispatchEvent(new CustomEvent("WebAuthnClientReady",{bubbles:!0,cancelable:!1,detail:!0}))).catch(e=>console.error("Error during initialization:",e)).finally(()=>e.update("WebAuthnClientBase","READY"))}get userIdentifier(){return this.relyingParty.customerDefinedIdentifier}set userIdentifier(e){return this.relyingParty.customerDefinedIdentifier=e}get customerDefinedIdentifier(){return this.relyingParty.customerDefinedIdentifier}set customerDefinedIdentifier(e){return this.relyingParty.customerDefinedIdentifier=e}get token(){return this.relyingParty.token}get credentialID(){return this.relyingParty.credentialID}set credentialID(e){return this.relyingParty.credentialID=e}get isEnrolled(){return!!this.credentialID}get metadata(){return this.relyingParty.metadata}set metadata(e){return this.relyingParty.metadata=e}async getZsmApi(e){}async primeZsmApi(){return this.zsmApi?this.zsmApi:this.zsmApi=await this.getZsmApi(Object.assign({},t.mpcConfig,{consumer_id:await i(t.mpcConfig.consumer_id)}))}async initializeZsm(){return t.mpcConfig.consumer_id!==this.MPCConfig.consumer_id&&(await this.zsmApi.configure(t.mpcConfig),this.MPCConfig=await Object.assign({},t.mpcConfig),await r(this.config.consumer_id,this.MPCConfig.consumer_id)),await this.zsmApi}async checkIdentity(e,i=!1){if(null==e||""===e)throw new Error(`[WebAuthnClient] :: checkIdentity :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e);try{const n=await this.relyingParty.checkServerSideIdentity(i);if(!n)throw new Error("Unable to communicate with identity server!");const s=Array.isArray(n)?n[0].identity_id:n.identity_id;if(!s)throw new Error("Unable to acquire identity_id!");return r(e,s),t.mpcConfig.consumer_id=s,s}catch(e){return Promise.reject(e)}}async webauthnRetrieve(e,r=!1,s=!1){if(null==e||"string"!=typeof e||""===e)throw new Error(`[WebAuthnClient] :: webauthnRetrieve :: A userIdentifier String is required! Received: ${e} (of type ${typeof e}).`);this.userIdentifier=e,this.credentialID=null,this.initializeZsm("webauthnRetrieve");let a=await i(e);t.mpcConfig.consumer_id=a;const o=await this.zsmApi.webauthn_retrieve(e);let l=n(o);if(!r)return!(l?.error||!l?.result)&&(this.credentialID=l?.result.zsm_credential_id??null);l=l?.error||!l?.result?{}:l.result,this.zsm_credential_id=l.zsm_credential_id??null;const u=this.passkeysPlus.passkeysSupported;let h=l,c="skipped";if(s||u&&!l?.has_remote_passkey&&!l?.passkey_credential_id||l?.passkey_credential_id&&!l?.passkey_active||!l?.zsm_active){const t=await this.fetchRemoteEnrollmentDetails(e,h),r="confirmed"===t.status&&t.data;if(c=t.status,r&&!(r instanceof Error)){h=Object.assign({},l,r);try{const e=r?.zsm_active&&!l?.zsm_active?"zsm":null;e&&await this.zsmApi.update_enrollment_status(a,e)}catch(e){console.error("[CORE] :: [WebAuthnClientBase] :: webauthnRetrieve :: update_enrollment_status failed:",e)}}}const d={userIdentifier:e,enrollmentActive:h?.zsm_active??!1,passkeySupported:u,passkeyEligible:u&&!(!h?.passkey_credential_id&&!h?.has_remote_passkey),hasLocalPasskey:u&&!!h?.passkey_credential_id,hasRemotePasskey:!!h?.rcr??null,pkpCredentialID:h?.passkey_credential_id??null,pkpCredID:h?.passkey_credential_id??null,hasZSMCred:!!h?.zsm_credential||!1,zsmCredential:h?.zsm_credential??null,zsmCredentialID:h?.zsm_credential_id??null,zsmCredID:h?.zsm_credential_id??null,isUsingPasswordManager:!(CredentialsContainer.prototype.get.toString()===navigator.credentials.get.toString()),remoteCheckStatus:c};!0===d.hasLocalPasskey&&(d.hasRemotePasskey=!0),h?.rcr&&(d.pkpCredential=h.rcr,d.hasLocalPasskey=!0,d.pkpCredentialID||(d.pkpCredentialID=h.rcr?.publicKey?.allowCredentials?.flatMap(e=>e.id)??null,d.pkpCredentialID.length&&(d.pkpCredentialID=d.pkpCredentialID[0]))),d.state=h?.zsm_active&&d.hasLocalPasskey?"BOTH":h?.zsm_active&&!d.hasLocalPasskey?"MPC_ONLY":"NONE";return Object.assign({},{userIdentifier:e,state:d.state,hasRemotePasskey:d.hasRemotePasskey,passkeySupported:d.passkeySupported},d)}async webauthnRetrieveAll(e,t=!1){try{return await this.webauthnRetrieve(e,!0,t)}catch(r){const i=new Error(`[WebAuthnClient] :: webauthnRetrieveAll :: Unable to retrieve enrollment details for userIdentifier: ${e}. Details: ${r?.message??r}`,{cause:r});return i.code="ENROLLMENT_DETAILS_UNAVAILABLE",i.userIdentifier=e,i.forceRemoteCheck=t,i}}async checkRemoteEnrollmentDetails(e,t){const r=await this.fetchRemoteEnrollmentDetails(e,t);return"confirmed"===r.status&&r.data}async fetchRemoteEnrollmentDetails(e,t){let r=null;try{r=await this.relyingParty.getRemoteEnrollmentDetails(e,t)}catch(e){return{status:"unavailable",error:e instanceof Error?e:new Error(String(e))}}return r instanceof Error?{status:"unavailable",error:r}:r?null==r.identity_id?{status:"not-found"}:{status:"confirmed",data:r}:{status:"unavailable",error:new Error(`[WebAuthnClient] :: fetchRemoteEnrollmentDetails :: The Relying Party returned no response for userIdentifier: ${e}.`)}}async webauthnCreate(e){if(!e)throw new Error(`[WebAuthnClient] :: webauthnCreate :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e),await this.initializeZsm("webauthnCreate");const r=await this.relyingParty.registrationStart();if(r instanceof Error)throw new Error(r);if(!r)throw new Error("[WebAuthnClient] :: webauthnCreate :: Unable to retrieve public key from Relying Party Server!");r.user_id=r.user.id;let i=await this.zsmApi.webauthn_create(r,void 0,e,o());if(!i)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain response from Crypto Server!");if(i=n(i),t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:i})),!i?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to obtain credential from Crypto Server!");if(!i?.result?.response)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreate :: Unable to acquire attestation object!");const s=i.result,a=await this.relyingParty.registrationFinish(s);if(a instanceof Error)throw new Error(a);if(0==a)throw new Error("[WebAuthnClient] :: webauthnCreate :: Unable to verify credential Relying Party Server!");return a}async webauthnGet(e){if(null==e||""===e)throw new Error(`[WebAuthnClient] :: webauthnGet :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e),await this.initializeZsm("webauthnGet");const r=await this.webauthnRetrieve(e,!0);if(!this.isEnrolled)throw new Error(`[WebAuthnClient] :: webauthnGet :: ${e} is not enrolled, lacks a credential, or credential is corrupted!`);let i=await this.relyingParty.authenticationStart(r);if(i instanceof Error)throw new Error(i);if(!i)throw new Error("[WebAuthnClient] :: webauthnGet :: Unable to start authentication with Relying Party Server!");if(i=n(i),!i?.rcr?.publicKey?.challenge)throw new Error("[WebAuthnClient] :: webauthnGet :: Unable to locate public key/challenge inside Relying Party Server response!\nResponse Body: "+JSON.stringify(i));const s=i.rcr.publicKey;let a=await this.zsmApi.webauthn_get(s,void 0,e,o());if(!a)throw new Error("[WebAuthnClient - mpc_round] :: webauthnGet :: Crypto server did not respond!");if(a=n(a),!a?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnGet :: Response from Crypto Server did not contain a credential!\nResponse Body: "+JSON.stringify(a));return t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:a})),a.result}async webauthnPartialGet(e){if(null==e||""===e)throw new Error(`[WebAuthnClient] :: webauthnPartialGet :: A userIdentifier String is required! Received: ${e}.`);if(e&&"string"==typeof e&&(this.userIdentifier=e),this.status="AUTHENTICATION_STARTING",await this.initializeZsm("webauthnPartialGet"),!this.isEnrolled)throw new Error(`[WebAuthnClient] :: webauthnPartialGet :: Credential is missing for ${e}`);let r=await this.relyingParty.authenticationStart(this.credentialID);if(!r)throw new Error("[WebAuthnClient] :: webauthnPartialGet :: Unable to start authentication with Relying Party Server!");if(r=n(r),!r?.rcr||!r.rcr.publicKey)throw new Error("[WebAuthnClient] :: webauthnPartialGet :: Unable to retrieve public key from Relying Party Server!");const i=r.rcr.publicKey;let s=await this.zsmApi.webauthn_get(i,null,e,o());if(!s)throw new Error("[WebAuthnClient - mpc_round] :: webauthnPartialGet :: Unable to obtain mpcResponse from Crypto Server!");if(s=n(s),!s?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnPartialGet :: Unable to obtain credential from Crypto Server!");return t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:s})),s.result}async unbindFromDevice(e){if(null==e||""===e)throw new Error(`[WebAuthnClient] :: unbindFromDevice :: A userIdentifier String is required! Received: ${e}.`);if(e&&"string"==typeof e&&(this.userIdentifier=e),this.status="UNENROLL_STARTING",e!==this.userIdentifier)return!1;await this.initializeZsm("unbindFromDevice");const t=await this.webauthnRetrieve(e);if(!t)return!1;const r=await i(e);return await new Promise((i,n)=>{const s=indexedDB.open("ideem",1);s.onerror=()=>n(new Error(`[WebAuthnClient] :: unbindFromDevice :: Unable to open indexedDB for ${e}`)),s.onsuccess=s=>{const a=s.target.result.transaction("zsm","readwrite"),o=a.objectStore("zsm");a.oncomplete=()=>i(),a.onerror=()=>n(new Error(`[WebAuthnClient] :: unbindFromDevice :: transaction failed for ${e}`)),a.onabort=()=>n(new Error(`[WebAuthnClient] :: unbindFromDevice :: transaction aborted for ${e}`));const l=o.openCursor();l.onerror=()=>n(new Error(`[WebAuthnClient] :: unbindFromDevice :: cursor failed for ${e}`)),l.onsuccess=i=>{const n=i.target.result;if(n){const{key:i,value:s}=n,a="string"==typeof s&&(s.includes(e)||s===r),l="object"==typeof s&&null!==s&&s.zsm_credential instanceof Map&&s.zsm_credential.get("rawId")===t;(i.includes(e)||a||l)&&o.delete(i),n.continue()}}}}),this.status="UNENROLL_COMPLETE",!0}async webauthnCreateFromPKP(e,r,i){if(null==e||""===e)throw new TypeError(`[PK+ WebAuthnClient] :: webauthnCreateFromPKP :: A userIdentifier String is required! Received: ${e}.`);if(e&&"string"==typeof e&&(this.userIdentifier=e),!r)throw new TypeError("[WebAuthnClient] :: webauthnCreateFromPKP :: Missing publicKey parameter!");if(!i)throw new TypeError("[WebAuthnClient] :: webauthnCreateFromPKP :: Missing pairing_token parameter!");await this.initializeZsm("webauthnCreate");let s=await this.zsmApi.webauthn_create(r,i,e);if(!s)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreateFromPKP :: Unable to obtain response from Crypto Server!");if(s=n(s),t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:s})),!s?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreateFromPKP :: Unable to obtain credential from Crypto Server!");if(!s?.result?.response)throw new Error("[WebAuthnClient - mpc_round] :: webauthnCreateFromPKP :: Unable to acquire attestation object!");return s.result}async webauthnGetFromPKP(e,r,i){if(null==e||""===e)throw new Error(`[PK+ WebAuthnClient] :: webauthnGetFromPKP :: A userIdentifier String is required! Received: ${e}.`);if(e&&"string"==typeof e&&(this.userIdentifier=e),!r)throw new TypeError("[WebAuthnClient] :: webauthnGetFromPKP :: Missing publicKey parameter!");if(!i)throw new TypeError("[WebAuthnClient] :: webauthnGetFromPKP :: Missing pairing_token parameter!");let s=await this.zsmApi.webauthn_get(r,i,e);if(!s)throw new Error("[WebAuthnClient - mpc_round] :: webauthnGetFromPKP :: Crypto server did not respond!");if(s=n(s),!s?.result)throw new Error("[WebAuthnClient - mpc_round] :: webauthnGetFromPKP :: Response from Crypto Server did not contain a credential!\nResponse Body: "+JSON.stringify(s));t.dispatchEvent(new CustomEvent("MPCResponse",{bubbles:!0,cancelable:!1,detail:s}));return s.result}async pkpCreate(e,t="preferred",i=!1,n=!1,s=null){if(i&&"object"==typeof e){const r=Object.assign({},e);if(s=e.zsmCredentialID,this.userIdentifier=e=e.userIdentifier,null==e||"string"!=typeof e||""===e)throw new TypeError(`[PK+ WebAuthnClient] :: pkpCreate :: A userIdentifier String is required! Received: ${e}.`);this.userIdentifier=e;const i=await this.relyingParty.pkpAuthenticationStart(r);if(!i)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: No response from ZSM API's attempt to interface with Relying Party Server!");const n=await this.passkeysPlus.pkpGetPasskeyCredential(i,t);if(!n)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: Unable to call Platform Authenticator to create Passkey!");const a=await this.relyingParty.pkpAuthenticationFinish(n);if(!a)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: Platform Authenticator response was invalid!");const o=a?.response?.ccr?.publicKey??a?.response?.rcr?.publicKey;let l=await this.webauthnGetFromPKP(e,o,a.response.token);return this.zsmCredentialId=l.rawId,Promise.resolve(l)}{if(null==e||"string"!=typeof e||""===e)throw new TypeError(`[PK+ WebAuthnClient] :: pkpCreate :: A userIdentifier String is required! Received: ${e}.`);this.userIdentifier=e;const i=await this.relyingParty.pkpRegistrationStart(e,t,s,n);if(!i)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: No response from ZSM API's attempt to interface with Relying Party Server!");const a=i?.publicKey;if(!a)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: No publicKey found in Relying Party Challenge!");const o=await this.passkeysPlus.pkpCreatePasskeyCredential(a,t);if(!o)throw console.error("[PK+ WebAuthnClient] :: pkpCreate :: Unable to call Platform Authenticator to create Passkey!"),new Error("[PK+ WebAuthnClient] :: pkpCreate :: Unable to call Platform Authenticator to create Passkey!");const l=await this.relyingParty.pkpRegistrationFinish(o,!!s);if(!l)throw new Error("[PK+ WebAuthnClient] :: pkpCreate :: Platform Authenticator response was invalid!");r("pk:"+e,o.id);const u=l?.response?.ccr?.publicKey,h=l?.response?.rcr?.publicKey,c=u??h;let d=u?await this.webauthnCreateFromPKP(e,c,l.response.token):await this.webauthnGetFromPKP(e,c,l.response.token);return this.zsmCredentialId=d.rawId,Promise.resolve(d)}}async pkpAuthenticate(e,t="preferred",r=!1){let i=null;if(e&&"object"==typeof e&&(i={...e},this.userIdentifier=e=e.userIdentifier),null==e||""===e)throw new Error(`[PK+ WebAuthnClient] :: pkpAuthenticate :: A userIdentifier String is required! Received: ${e}.`);let n=null;if(this.userIdentifier=e,n=await this.relyingParty.pkpAuthenticationStart(i),!n)throw new Error("[PK+ WebAuthnClient] :: pkpAuthenticate :: Unable to retrieve Platform Authority Challenge from Relying Party Server!");const s=await this.passkeysPlus.pkpGetPasskeyCredential(n,t);if(!s)throw new Error("[PK+ WebAuthnClient] :: pkpAuthenticate :: Unable to call Platform Authenticator to create Passkey!");const a=await this.relyingParty.pkpAuthenticationFinish(s);if(!a)throw new Error("[PK+ WebAuthnClient] :: pkpAuthenticate :: Platform Authenticator response was invalid!");const o=a?.response?.ccr?.publicKey??a?.response?.rcr?.publicKey;return r?await this.webauthnCreateFromPKP(e,o,a.response.token):await this.webauthnGetFromPKP(e,o,a.response.token)}async pkpAddZSMCredential(e){if(null==e||""===e)throw new Error(`[PK+ WebAuthnClient] :: pkpAddZSMCredential :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e);const t=await this.webauthnRetrieveAll(e);if(t instanceof Error)throw new Error(`[PK+ WebAuthnClient] :: pkpAddZSMCredential :: Cannot add ZSM; unable to retrieve existing credentials for this user! Details: ${t.message}`,{cause:t});if(!t?.hasLocalPasskey)throw new Error("[PK+ WebAuthnClient] :: pkpAddZSMCredential :: Cannot add ZSM; no passkey credentials registered for this user!");return t.userIdentifier=e,this.pkpAuthenticate(t,"required",!0)}async pkpAddPasskeyCredential(e,t="preferred"){let r=null;if(e&&"object"==typeof e?(r={...e},this.userIdentifier=e=e.userIdentifier):(this.userIdentifier=e,r=await this.webauthnRetrieveAll(e,!0)),r instanceof Error)throw new Error(`[WebAuthnClient] :: pkpAddPasskeyCredential :: Unable to retrieve existing credentials for userIdentifier: ${e}. Details: ${r.message||r}`);if(!r?.zsmCredentialID)throw new Error(`[WebAuthnClient] :: pkpAddPasskeyCredential :: userIdentifier: ${e} does not have an existing ZSM credential!`);return this.pkpCreate(r.hasLocalPasskey?Object.assign({},r,{userIdentifier:e}):e,t,r.hasLocalPasskey,!1,r.zsmCredentialID)}async checkForPasskeysOnOtherDevice(e){if(null==e||""===e)throw new Error(`[PK+ WebAuthnClient] :: checkForPasskeysOnOtherDevice :: A userIdentifier String is required! Received: ${e}.`);e&&"string"==typeof e&&(this.userIdentifier=e);try{this.userIdentifier=e;const t=await this.relyingParty.makePostRequest("api/passkey/bootstrap/start").catch(e=>!1);return!(!t||t instanceof Error)&&(0!==(t?.rcr?.publicKey?.allowCredentials?.length??0)&&((t?.rcr?.publicKey?.allowCredentials?.length??0)>=1?(r("pk:"+e,t.rcr.publicKey.allowCredentials[0].id),t.rcr.publicKey.allowCredentials[0].id):(t?.rcr?.publicKey?.challenge&&(t.rcr.publicKey.challenge=this.passkeysPlus.toArrayBuffer(t.rcr.publicKey.challenge)),t?.rcr?.publicKey?.allowCredentials&&(t.rcr.publicKey.allowCredentials=t.rcr.publicKey.allowCredentials.map(e=>({...e,id:this.passkeysPlus.toArrayBuffer(e.id)}))),t)))}catch(e){return!1}}webauthnReset=()=>this.relyingParty.resetAll();resetDevice=this.webauthnReset}
package/ZSMClientSDK.js CHANGED
@@ -1 +1 @@
1
- import e from"./EventCoordinator.js";import{UMFAClient as s}from"./UMFAClient.js";import{FIDO2Client as r}from"./FIDO2Client.js";import t from"./RelyingParty.js";import n from"./WebAuthnClient.js";import{zsmPluginManager as o}from"./PluginManager.js";import i from"./GlobalScoping.js";class l{constructor(s){o.freezePlugins();const r=new(o.classes("UMFAClient"))(s);return e.setCoreSDKClass("UMFAClient",r),r}}class C{constructor(s){o.freezePlugins();const r=new(o.classes("FIDO2Client"))(s);return e.setCoreSDKClass("FIDO2Client",r),r}}o.registerPlugin("Core",{classDefs:{UMFAClient:s,FIDO2Client:r,RelyingParty:t,WebAuthnClient:n},mode:"OVERRIDE"});const a="2.9.3",m=i.ZSMVersions=i.ZSMVersions?{...i.ZSMVersions,CORE:a}:{CORE:a};export{l as UMFAClient,C as FIDO2Client,m as ZSMVersions};
1
+ import e from"./EventCoordinator.js";import{UMFAClient as s}from"./UMFAClient.js";import{FIDO2Client as r}from"./FIDO2Client.js";import t from"./RelyingParty.js";import n from"./WebAuthnClient.js";import{zsmPluginManager as o}from"./PluginManager.js";import i from"./GlobalScoping.js";class l{constructor(s){o.freezePlugins();const r=new(o.classes("UMFAClient"))(s);return e.setCoreSDKClass("UMFAClient",r),r}}class C{constructor(s){o.freezePlugins();const r=new(o.classes("FIDO2Client"))(s);return e.setCoreSDKClass("FIDO2Client",r),r}}o.registerPlugin("Core",{classDefs:{UMFAClient:s,FIDO2Client:r,RelyingParty:t,WebAuthnClient:n},mode:"OVERRIDE"});const a="2.9.4",m=i.ZSMVersions=i.ZSMVersions?{...i.ZSMVersions,CORE:a}:{CORE:a};export{l as UMFAClient,C as FIDO2Client,m as ZSMVersions};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name" : "@ideem/zsm-client-sdk",
3
- "version" : "2.9.3",
3
+ "version" : "2.9.4",
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
  "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" ],
6
6
  "author" : "Jason Jurusz <jj@useideem.com>",