@transmitsecurity/platform-web-sdk 2.0.1 → 2.1.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.
package/dist/web-sdk.d.ts CHANGED
@@ -417,6 +417,13 @@ type EventResponse = {
417
417
  type Recommendation = {
418
418
  type: RecommendationType;
419
419
  };
420
+ type LightweightPayload = {
421
+ clientId: string;
422
+ deviceId?: string;
423
+ userId: string | null;
424
+ sdkPlatform: 'mobile_web' | 'desktop_web';
425
+ events: Array<Record<string, unknown>>;
426
+ };
420
427
 
421
428
  interface ActionResponse {
422
429
  /** The token return by the SDK when the action was reported */
@@ -446,6 +453,8 @@ interface ConstructorOptions {
446
453
  /** @internal
447
454
  * Internal flag indicating this web_sdk instance has its own clientId separate from the Platform SDK root-level clientId */
448
455
  hasOwnClientId?: boolean;
456
+ /** Tier mode for the SDK: 'standard' (default) or 'lightweight' (server-to-server) */
457
+ tier?: 'standard' | 'lightweight';
449
458
  }
450
459
  interface TransactionData {
451
460
  amount: number;
@@ -523,6 +532,7 @@ declare class TSAccountProtection {
523
532
  private identifiersMigrationEnabled;
524
533
  private firstPartyMigrationUrl;
525
534
  private hasOwnClientId;
535
+ private tier;
526
536
  private validationManager;
527
537
  private storageManager;
528
538
  private eventsManager;
@@ -553,6 +563,14 @@ declare class TSAccountProtection {
553
563
  /** @ignore */
554
564
  getActions(): Promise<string[]>;
555
565
  getSessionToken(): Promise<any>;
566
+ getPayload(): Promise<LightweightPayload>;
567
+ clearQueue(): void;
568
+ /**
569
+ * Sets the deviceId for lightweight mode (citadel).
570
+ * Should be called after receiving deviceId from backend on first request.
571
+ * @param deviceId - The JWT deviceId returned from citadel backend
572
+ */
573
+ setDeviceId(deviceId: string): void;
556
574
  /**
557
575
  * Initializes the AccountProtection SDK, which starts automatically tracking and submitting info of the user journey
558
576
  * @param options Init options
@@ -631,6 +649,14 @@ declare const getSessionToken: TSAccountProtection['getSessionToken'];
631
649
  */
632
650
  declare const getSecureSessionToken: TSAccountProtection['getSecureSessionToken'];
633
651
  /** @ignore */
652
+ declare const getPayload: TSAccountProtection['getPayload'];
653
+ /**
654
+ * Sets the deviceId for lightweight mode (citadel).
655
+ * Should be called after receiving deviceId from backend on first request.
656
+ * @param deviceId - The JWT deviceId returned from citadel backend
657
+ */
658
+ declare const setDeviceId: TSAccountProtection['setDeviceId'];
659
+ /** @ignore */
634
660
  declare const __internal: {
635
661
  getDeviceId(): string;
636
662
  getClientId(): string;
@@ -639,23 +665,29 @@ declare const __internal: {
639
665
 
640
666
  type webSdkModule_d_ActionEventOptions = ActionEventOptions;
641
667
  type webSdkModule_d_ActionResponse = ActionResponse;
668
+ type webSdkModule_d_LightweightPayload = LightweightPayload;
642
669
  declare const webSdkModule_d___internal: typeof __internal;
643
670
  declare const webSdkModule_d_clearUser: typeof clearUser;
644
671
  declare const webSdkModule_d_getActions: typeof getActions;
672
+ declare const webSdkModule_d_getPayload: typeof getPayload;
645
673
  declare const webSdkModule_d_getSecureSessionToken: typeof getSecureSessionToken;
646
674
  declare const webSdkModule_d_getSessionToken: typeof getSessionToken;
647
675
  declare const webSdkModule_d_setAuthenticatedUser: typeof setAuthenticatedUser;
676
+ declare const webSdkModule_d_setDeviceId: typeof setDeviceId;
648
677
  declare const webSdkModule_d_triggerActionEvent: typeof triggerActionEvent;
649
678
  declare namespace webSdkModule_d {
650
679
  export {
651
680
  webSdkModule_d_ActionEventOptions as ActionEventOptions,
652
681
  webSdkModule_d_ActionResponse as ActionResponse,
682
+ webSdkModule_d_LightweightPayload as LightweightPayload,
653
683
  webSdkModule_d___internal as __internal,
654
684
  webSdkModule_d_clearUser as clearUser,
655
685
  webSdkModule_d_getActions as getActions,
686
+ webSdkModule_d_getPayload as getPayload,
656
687
  webSdkModule_d_getSecureSessionToken as getSecureSessionToken,
657
688
  webSdkModule_d_getSessionToken as getSessionToken,
658
689
  webSdkModule_d_setAuthenticatedUser as setAuthenticatedUser,
690
+ webSdkModule_d_setDeviceId as setDeviceId,
659
691
  webSdkModule_d_triggerActionEvent as triggerActionEvent,
660
692
  };
661
693
  }
@@ -2262,6 +2294,15 @@ declare namespace index_d {
2262
2294
  };
2263
2295
  }
2264
2296
 
2297
+ interface SdkVersions {
2298
+ 'identity-orchestration': string;
2299
+ 'risk-detection': string;
2300
+ 'identity-verification': string;
2301
+ 'webauthn': string;
2302
+ 'unified-platform': string;
2303
+ }
2304
+ declare const SDK_VERSIONS: SdkVersions;
2305
+
2265
2306
  /**
2266
2307
  * Main SDK class for CDN usage (window.tsPlatform)
2267
2308
  * Provides access to all modules and common functionality
@@ -2275,6 +2316,6 @@ declare class TSWebSDK {
2275
2316
  }
2276
2317
  declare const _default: TSWebSDK;
2277
2318
 
2278
- declare const PACKAGE_VERSION = "2.0.1";
2319
+ declare const PACKAGE_VERSION = "2.1.1";
2279
2320
 
2280
- export { ActionEventOptions, ActionResponse, AuthenticationAutofillActivateHandlers, AutofillHandlers, CrossDeviceController, ErrorCode$1 as ErrorCode, PACKAGE_VERSION, SdkError, WebauthnApis, WebauthnAuthenticationFlows, WebauthnCrossDeviceFlows, WebauthnCrossDeviceRegistrationOptions, WebauthnRegistrationOptions, authenticate, index_d$3 as common, crossDevice, _default as default, webSdkModule_d as drs, getDefaultPaths, index_d as ido, index_d$2 as idv, initConfigParams, initialize, isAutofillSupported, isPlatformAuthenticatorSupported, register, index_d$1 as webauthn };
2321
+ export { ActionEventOptions, ActionResponse, AuthenticationAutofillActivateHandlers, AutofillHandlers, CrossDeviceController, ErrorCode$1 as ErrorCode, PACKAGE_VERSION, SDK_VERSIONS, SdkError, WebauthnApis, WebauthnAuthenticationFlows, WebauthnCrossDeviceFlows, WebauthnCrossDeviceRegistrationOptions, WebauthnRegistrationOptions, authenticate, index_d$3 as common, crossDevice, _default as default, webSdkModule_d as drs, getDefaultPaths, index_d as ido, index_d$2 as idv, initConfigParams, initialize, isAutofillSupported, isPlatformAuthenticatorSupported, register, index_d$1 as webauthn };
package/dist/webauthn.cjs CHANGED
@@ -1 +1 @@
1
- "undefined"==typeof globalThis&&("undefined"!=typeof window?(window.globalThis=window,window.global=window):"undefined"!=typeof self&&(self.globalThis=self,self.global=self));var t=require("./common.cjs"),e=require("./common.cjs");function i(t,e,i){return(e=function(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var i=t[Symbol.toPrimitive];if(void 0!==i){var a=i.call(t,e||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:e+""}(e))in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function a(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function r(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{};e%2?a(Object(r),!0).forEach((function(e){i(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}class n{static arrayBufferToBase64(t){return btoa(String.fromCharCode(...new Uint8Array(t)))}static base64ToArrayBuffer(t){return Uint8Array.from(atob(t),(t=>t.charCodeAt(0)))}static stringToBase64(t){return btoa(t)}static jsonToBase64(t){const e=JSON.stringify(t);return btoa(e)}static base64ToJson(t){const e=atob(t);return JSON.parse(e)}}const s={log:console.log,error:console.error};var o,c;!function(t){t.NotInitialized="not_initialized",t.AuthenticationFailed="authentication_failed",t.AuthenticationAbortedTimeout="authentication_aborted_timeout",t.AuthenticationCanceled="webauthn_authentication_canceled",t.RegistrationFailed="registration_failed",t.AlreadyRegistered="username_already_registered",t.RegistrationAbortedTimeout="registration_aborted_timeout",t.RegistrationCanceled="webauthn_registration_canceled",t.AutofillAuthenticationAborted="autofill_authentication_aborted",t.AuthenticationProcessAlreadyActive="authentication_process_already_active",t.InvalidApprovalData="invalid_approval_data",t.FailedToInitCrossDeviceSession="cross_device_init_failed",t.FailedToGetCrossDeviceStatus="cross_device_status_failed",t.Unknown="unknown"}(o||(o={}));class l extends Error{constructor(t,e){super(t),this.errorCode=o.NotInitialized,this.data=e}}class u extends l{constructor(t,e){super(null!=t?t:"WebAuthnSdk is not initialized",e),this.errorCode=o.NotInitialized}}class d extends l{constructor(t,e){super(null!=t?t:"Authentication failed with an error",e),this.errorCode=o.AuthenticationFailed}}class h extends l{constructor(t,e){super(null!=t?t:"Authentication was canceled by the user or got timeout",e),this.errorCode=o.AuthenticationCanceled}}class p extends l{constructor(t,e){super(null!=t?t:"Registration failed with an error",e),this.errorCode=o.RegistrationFailed}}class v extends l{constructor(t,e){super(null!=t?t:"Registration was canceled by the user or got timeout",e),this.errorCode=o.RegistrationCanceled}}class g extends l{constructor(t){super(null!=t?t:"Autofill flow was aborted"),this.errorCode=o.AutofillAuthenticationAborted}}class f extends l{constructor(t){super(null!=t?t:"Operation was aborted by timeout"),this.errorCode=o.AutofillAuthenticationAborted}}class w extends l{constructor(t){super(null!=t?t:"Passkey with this username is already registered with the relying party."),this.errorCode=o.AlreadyRegistered}}class m extends l{constructor(t,e){super(null!=t?t:"Authentication process is already active",e),this.errorCode=o.AuthenticationProcessAlreadyActive}}class y extends l{constructor(t,e){super(null!=t?t:"Invalid approval data",e),this.errorCode=o.InvalidApprovalData}}class b extends l{constructor(t,e){super(null!=t?t:"Failed to init cross device authentication",e),this.errorCode=o.FailedToInitCrossDeviceSession}}class C extends l{constructor(t,e){super(null!=t?t:"Failed to get cross device status",e),this.errorCode=o.FailedToGetCrossDeviceStatus}}function A(t){return t.errorCode&&Object.values(o).includes(t.errorCode)}!function(t){t[t.persistent=0]="persistent",t[t.session=1]="session"}(c||(c={}));class D{static get(t){return D.getStorageMedium(D.allowedKeys[t]).getItem(D.getStorageKey(t))||void 0}static set(t,e){return D.getStorageMedium(D.allowedKeys[t]).setItem(D.getStorageKey(t),e)}static remove(t){D.getStorageMedium(D.allowedKeys[t]).removeItem(D.getStorageKey(t))}static clear(t){for(const[e,i]of Object.entries(D.allowedKeys)){const a=e;t&&this.configurationKeys.includes(a)||D.getStorageMedium(i).removeItem(D.getStorageKey(a))}}static getStorageKey(t){return`WebAuthnSdk:${t}`}static getStorageMedium(t){return t===c.session?sessionStorage:localStorage}}D.allowedKeys={clientId:c.session},D.configurationKeys=["clientId"];class _{static isNewApiDomain(t){return t&&(this.newApiDomains.includes(t)||t.startsWith("api.")&&t.endsWith(".transmitsecurity.io"))}static dnsPrefetch(t){const e=document.createElement("link");e.rel="dns-prefetch",e.href=t,document.head.appendChild(e)}static preconnect(t,e){const i=document.createElement("link");i.rel="preconnect",i.href=t,e&&(i.crossOrigin="anonymous"),document.head.appendChild(i)}static warmupConnection(t){this.dnsPrefetch(t),this.preconnect(t,!1),this.preconnect(t,!0)}static init(t,e){var i,a;try{this._serverPath=new URL(e.serverPath),this.isNewApiDomain(null===(i=this._serverPath)||void 0===i?void 0:i.hostname)&&this.warmupConnection(this._serverPath.origin),this._apiPaths=null!==(a=e.webauthnApiPaths)&&void 0!==a?a:this.getDefaultPaths(),this._clientId=t,D.set("clientId",t)}catch(t){throw new u("Invalid options.serverPath",{error:t})}}static getDefaultPaths(){var t;const e=this.isNewApiDomain(null===(t=this._serverPath)||void 0===t?void 0:t.hostname)?"/cis":"";return{startAuthentication:`${e}/v1/auth/webauthn/authenticate/start`,startRegistration:`${e}/v1/auth/webauthn/register/start`,initCrossDeviceAuthentication:`${e}/v1/auth/webauthn/cross-device/authenticate/init`,startCrossDeviceAuthentication:`${e}/v1/auth/webauthn/cross-device/authenticate/start`,startCrossDeviceRegistration:`${e}/v1/auth/webauthn/cross-device/register/start`,getCrossDeviceTicketStatus:`${e}/v1/auth/webauthn/cross-device/status`,attachDeviceToCrossDeviceSession:`${e}/v1/auth/webauthn/cross-device/attach-device`}}static getApiPaths(){return this._apiPaths}static async sendRequest(t,e,i){s.log(`[WebAuthn SDK] Calling ${e.method} ${t}...`);const a=new URL(this._serverPath);return a.pathname=t,i&&(a.search=i),fetch(a.toString(),e)}static async startRegistration(t){const e=await this.sendRequest(this._apiPaths.startRegistration,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r(r({client_id:this.getValidatedClientId(),username:t.username,display_name:t.displayName},t.timeout&&{timeout:t.timeout}),t.limitSingleCredentialToDevice&&{limit_single_credential_to_device:t.limitSingleCredentialToDevice}))});if(!(null==e?void 0:e.ok))throw new d("Failed to start registration",null==e?void 0:e.body);return await e.json()}static async startAuthentication(t){const e=await this.sendRequest(this._apiPaths.startAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r(r(r(r(r({client_id:this.getValidatedClientId()},t.username&&{username:t.username}),t.identifier&&{identifier:t.identifier}),t.identifierType&&{identifier_type:t.identifierType}),t.approvalData&&{approval_data:t.approvalData}),t.timeout&&{timeout:t.timeout}))});if(!(null==e?void 0:e.ok))throw new d("Failed to start authentication",null==e?void 0:e.body);return await e.json()}static async initCrossDeviceAuthentication(t){const e=await this.sendRequest(this._apiPaths.initCrossDeviceAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r(r({client_id:this.getValidatedClientId()},t.username&&{username:t.username}),t.approvalData&&{approval_data:t.approvalData}))});if(!(null==e?void 0:e.ok))throw new b(void 0,null==e?void 0:e.body);return await e.json()}static async getCrossDeviceTicketStatus(t){const e=await this.sendRequest(this._apiPaths.getCrossDeviceTicketStatus,{method:"GET"},`cross_device_ticket_id=${t.ticketId}`);if(!(null==e?void 0:e.ok))throw new C(void 0,null==e?void 0:e.body);return await e.json()}static async startCrossDeviceAuthentication(t){const e=await this.sendRequest(this._apiPaths.startCrossDeviceAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new d("Failed to start cross device authentication",null==e?void 0:e.body);return await e.json()}static async startCrossDeviceRegistration(t){const e=await this.sendRequest(this._apiPaths.startCrossDeviceRegistration,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new p("Failed to start cross device registration",null==e?void 0:e.body);return await e.json()}static async attachDeviceToCrossDeviceSession(t){const e=await this.sendRequest(this._apiPaths.attachDeviceToCrossDeviceSession,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new p("Failed to attach device to cross device session",null==e?void 0:e.body);return await e.json()}static getValidatedClientId(){var t;const e=null!==(t=this._clientId)&&void 0!==t?t:D.get("clientId");if(!e)throw new u("Missing clientId");return e}}var S,T,k,I;_.newApiDomains=["api.idsec-dev.com","api.idsec-stg.com"],function(t){t.InputAutofill="input-autofill",t.Modal="modal"}(S||(S={})),exports.WebauthnCrossDeviceStatus=void 0,(T=exports.WebauthnCrossDeviceStatus||(exports.WebauthnCrossDeviceStatus={})).Pending="pending",T.Scanned="scanned",T.Success="success",T.Error="error",T.Timeout="timeout",T.Aborted="aborted",function(t){t.toAuthenticationError=t=>A(t)?t:"NotAllowedError"===t.name?new h:"OperationError"===t.name?new m(t.message):"SecurityError"===t.name?new d(t.message):t===o.AuthenticationAbortedTimeout?new f:"AbortError"===t.name||t===o.AutofillAuthenticationAborted?new g:new d("Something went wrong during authentication",{error:t}),t.toRegistrationError=t=>A(t)?t:"NotAllowedError"===t.name?new v:"SecurityError"===t.name?new p(t.message):"InvalidStateError"===t.name?new w:t===o.RegistrationAbortedTimeout?new f:new p("Something went wrong during registration",{error:t})}(k||(k={})),function(t){t.processCredentialRequestOptions=t=>r(r({},t),{},{challenge:n.base64ToArrayBuffer(t.challenge),allowCredentials:t.allowCredentials.map((t=>r(r({},t),{},{id:n.base64ToArrayBuffer(t.id)})))}),t.processCredentialCreationOptions=(t,e)=>{var i;const a=JSON.parse(JSON.stringify(t));return a.challenge=n.base64ToArrayBuffer(t.challenge),a.user.id=n.base64ToArrayBuffer(t.user.id),(null==e?void 0:e.limitSingleCredentialToDevice)&&(a.excludeCredentials=null===(i=t.excludeCredentials)||void 0===i?void 0:i.map((t=>r(r({},t),{},{id:n.base64ToArrayBuffer(t.id)})))),(null==e?void 0:e.registerAsDiscoverable)?(a.authenticatorSelection.residentKey="preferred",a.authenticatorSelection.requireResidentKey=!0):(a.authenticatorSelection.residentKey="discouraged",a.authenticatorSelection.requireResidentKey=!1),a.authenticatorSelection.authenticatorAttachment=(null==e?void 0:e.allowCrossPlatformAuthenticators)?void 0:"platform",a},t.encodeAuthenticationResult=t=>{const{authenticatorAttachment:e}=t,i=t.response;return{id:t.id,rawId:n.arrayBufferToBase64(t.rawId),response:{authenticatorData:n.arrayBufferToBase64(i.authenticatorData),clientDataJSON:n.arrayBufferToBase64(i.clientDataJSON),signature:n.arrayBufferToBase64(i.signature),userHandle:n.arrayBufferToBase64(i.userHandle)},authenticatorAttachment:e,type:t.type}},t.encodeRegistrationResult=t=>{const{authenticatorAttachment:e}=t,i=t.response;return{id:t.id,rawId:n.arrayBufferToBase64(t.rawId),response:{attestationObject:n.arrayBufferToBase64(i.attestationObject),clientDataJSON:n.arrayBufferToBase64(i.clientDataJSON)},authenticatorAttachment:e,type:t.type}}}(I||(I={}));class P{async modal(t){try{const e=await this.performAuthentication(r(r({},t),{},{mediationType:S.Modal}));return n.jsonToBase64(e)}catch(t){throw k.toAuthenticationError(t)}}activateAutofill(t){const{handlers:e,username:i}=t,{onSuccess:a,onError:r,onReady:s}=e;this.performAuthentication({username:i,mediationType:S.InputAutofill,onReady:s}).then((t=>{a(n.jsonToBase64(t))})).catch((t=>{const e=k.toAuthenticationError(t);if(!r)throw e;r(e)}))}abortAutofill(){this.abortController&&this.abortController.abort(o.AutofillAuthenticationAborted)}abortAuthentication(){this.abortController&&this.abortController.abort(o.AuthenticationAbortedTimeout)}async performAuthentication(t){var e,i;const a="crossDeviceTicketId"in t?await _.startCrossDeviceAuthentication({ticketId:t.crossDeviceTicketId}):await _.startAuthentication({username:t.username,identifier:t.identifier,identifierType:t.identifierType,timeout:null===(e=t.options)||void 0===e?void 0:e.timeout}),r=a.credential_request_options,n=I.processCredentialRequestOptions(r),s=this.getMediatedCredentialRequest(n,t.mediationType);t.mediationType===S.InputAutofill&&(null===(i=t.onReady)||void 0===i||i.call(t));const o=await navigator.credentials.get(s).catch((t=>{throw k.toAuthenticationError(t)}));return{webauthnSessionId:a.webauthn_session_id,publicKeyCredential:I.encodeAuthenticationResult(o),userAgent:navigator.userAgent}}getMediatedCredentialRequest(t,e){const i={publicKey:t};return this.abortController=new AbortController,i.signal=this.abortController&&this.abortController.signal,e===S.InputAutofill?i.mediation="conditional":t.timeout&&setTimeout((()=>{this.abortAuthentication()}),t.timeout),i}}class O{constructor(t,e){this.handler=t,this.intervalInMs=e}begin(){var t;this.intervalId=window.setInterval((t=this.handler,async function(){t.isRunning||(t.isRunning=!0,await t(...arguments),t.isRunning=!1)}),this.intervalInMs)}stop(){clearInterval(this.intervalId)}}const R=/^[A-Za-z0-9\-_.: ]*$/;function j(t){if(t&&(!function(t){return Object.keys(t).length<=10}(t)||!function(t){const e=t=>"string"==typeof t,i=t=>R.test(t);return Object.keys(t).every((a=>e(a)&&e(t[a])&&i(a)&&i(t[a])))}(t)))throw s.error("Failed validating approval data"),new y("Provided approval data should have 10 properties max. Also, it should contain only \n alphanumeric characters, numbers, and the special characters: '-', '_', '.'")}class x{constructor(t,e,i){this.authenticationHandler=t,this.registrationHandler=e,this.approvalHandler=i,this.init={registration:async t=>(this.ticketStatus=exports.WebauthnCrossDeviceStatus.Pending,this.pollCrossDeviceSession(t.crossDeviceTicketId,t.handlers)),authentication:async t=>{const{username:e}=t,i=(await _.initCrossDeviceAuthentication(r({},e&&{username:e}))).cross_device_ticket_id;return this.ticketStatus=exports.WebauthnCrossDeviceStatus.Pending,this.pollCrossDeviceSession(i,t.handlers)},approval:async t=>{const{username:e,approvalData:i}=t;j(i);const a=(await _.initCrossDeviceAuthentication({username:e,approvalData:i})).cross_device_ticket_id;return this.ticketStatus=exports.WebauthnCrossDeviceStatus.Pending,this.pollCrossDeviceSession(a,t.handlers)}},this.authenticate={modal:async t=>this.authenticationHandler.modal({crossDeviceTicketId:t})},this.approve={modal:async t=>this.approvalHandler.modal({crossDeviceTicketId:t})}}async register(t){return this.registrationHandler.register(t)}async attachDevice(t){const e=await _.attachDeviceToCrossDeviceSession({ticketId:t});return r({status:e.status,startedAt:e.started_at},e.approval_data&&{approvalData:e.approval_data})}async pollCrossDeviceSession(t,e){return this.poller=new O((async()=>{var i,a;const r=await _.getCrossDeviceTicketStatus({ticketId:t}),n=r.status;if(n!==this.ticketStatus)switch(this.ticketStatus=n,n){case exports.WebauthnCrossDeviceStatus.Scanned:await e.onDeviceAttach();break;case exports.WebauthnCrossDeviceStatus.Error:case exports.WebauthnCrossDeviceStatus.Timeout:case exports.WebauthnCrossDeviceStatus.Aborted:await e.onFailure(r),null===(i=this.poller)||void 0===i||i.stop();break;case exports.WebauthnCrossDeviceStatus.Success:if("onCredentialRegister"in e)await e.onCredentialRegister();else{if(!r.session_id)throw new C("Cross device session is complete without returning session_id",r);await e.onCredentialAuthenticate(r.session_id)}null===(a=this.poller)||void 0===a||a.stop()}}),1e3),this.poller.begin(),setTimeout((()=>{var t;null===(t=this.poller)||void 0===t||t.stop(),e.onFailure({status:exports.WebauthnCrossDeviceStatus.Timeout})}),3e5),{crossDeviceTicketId:t,stop:()=>{var t;null===(t=this.poller)||void 0===t||t.stop()}}}}class K{async register(t){var e,i,a;this.abortController=new AbortController;const s=r({allowCrossPlatformAuthenticators:!("crossDeviceTicketId"in t),registerAsDiscoverable:!0},t.options);try{const r="crossDeviceTicketId"in t?await _.startCrossDeviceRegistration({ticketId:t.crossDeviceTicketId}):await _.startRegistration({username:t.username,displayName:(null===(e=t.options)||void 0===e?void 0:e.displayName)||t.username,timeout:null===(i=t.options)||void 0===i?void 0:i.timeout,limitSingleCredentialToDevice:null===(a=t.options)||void 0===a?void 0:a.limitSingleCredentialToDevice}),o=I.processCredentialCreationOptions(r.credential_creation_options,s);setTimeout((()=>{this.abortRegistration()}),o.timeout);const c=await this.registerCredential(o),l={webauthnSessionId:r.webauthn_session_id,publicKeyCredential:c,userAgent:navigator.userAgent};return n.jsonToBase64(l)}catch(t){throw k.toRegistrationError(t)}}abortRegistration(){this.abortController&&this.abortController.abort(o.RegistrationAbortedTimeout)}async registerCredential(t){const e=await navigator.credentials.create({publicKey:t,signal:this.abortController&&this.abortController.signal}).catch((t=>{throw k.toRegistrationError(t)}));return I.encodeRegistrationResult(e)}}class B{async modal(t){try{const e=await this.performApproval(t);return n.jsonToBase64(e)}catch(t){throw k.toAuthenticationError(t)}}async performApproval(t){"approvalData"in t&&j(t.approvalData);const e="crossDeviceTicketId"in t?await _.startCrossDeviceAuthentication({ticketId:t.crossDeviceTicketId}):await _.startAuthentication({username:t.username,approvalData:t.approvalData}),i=e.credential_request_options,a=I.processCredentialRequestOptions(i),r=await navigator.credentials.get({publicKey:a}).catch((t=>{throw k.toAuthenticationError(t)}));return{webauthnSessionId:e.webauthn_session_id,publicKeyCredential:I.encodeAuthenticationResult(r),userAgent:navigator.userAgent}}}class E{constructor(){this._initialized=!1,this._authenticationHandler=new P,this._registrationHandler=new K,this._approvalHandler=new B,this._crossDeviceHandler=new x(this._authenticationHandler,this._registrationHandler,this._approvalHandler),this.authenticate={modal:async t=>(this.initCheck(),this._authenticationHandler.modal(t)),autofill:{activate:t=>(this.initCheck(),this._authenticationHandler.activateAutofill(t)),abort:()=>this._authenticationHandler.abortAutofill()}},this.approve={modal:async t=>(this.initCheck(),this._approvalHandler.modal(t))},this.register=async t=>(this.initCheck(),this._registrationHandler.register(t)),this.crossDevice={init:{registration:async t=>(this.initCheck(),this._crossDeviceHandler.init.registration(t)),authentication:async t=>(this.initCheck(),this._crossDeviceHandler.init.authentication(t)),approval:async t=>(this.initCheck(),this._crossDeviceHandler.init.approval(t))},authenticate:{modal:async t=>(this.initCheck(),this._crossDeviceHandler.authenticate.modal(t))},approve:{modal:async t=>(this.initCheck(),this._crossDeviceHandler.approve.modal(t))},register:async t=>(this.initCheck(),this._crossDeviceHandler.register(t)),attachDevice:async t=>(this.initCheck(),this._crossDeviceHandler.attachDevice(t))},this.isPlatformAuthenticatorSupported=async()=>{var t;try{return await(null===(t=E.StaticPublicKeyCredential)||void 0===t?void 0:t.isUserVerifyingPlatformAuthenticatorAvailable())}catch(t){return!1}},this.isAutofillSupported=async()=>{var t,e;return!(!(null===(t=E.StaticPublicKeyCredential)||void 0===t?void 0:t.isConditionalMediationAvailable)||!await(null===(e=E.StaticPublicKeyCredential)||void 0===e?void 0:e.isConditionalMediationAvailable()))}}async init(t){const{clientId:e,options:i}=t;try{if(!e)throw new u("Invalid clientId",{clientId:e});if(i.webauthnApiPaths){const t=_.getDefaultPaths();if(function(t,e){const i=new Set(t),a=new Set(e);return[...t.filter((t=>!a.has(t))),...e.filter((t=>!i.has(t)))]}(Object.keys(i.webauthnApiPaths),Object.keys(t)).length)throw new u("Invalid custom paths",{customApiPaths:i.webauthnApiPaths})}_.init(e,i),this._initialized=!0}catch(t){throw A(t)?t:new u("Failed to initialize SDK")}}getDefaultPaths(){return this.initCheck(),_.getDefaultPaths()}getApiPaths(){return this.initCheck(),_.getApiPaths()}initCheck(){if(!this._initialized)throw new u}}E.StaticPublicKeyCredential=window.PublicKeyCredential;const N=new t("webauthn"),H=new E;N.events.on(N.events.MODULE_INITIALIZED,(()=>{var t;const e=N.moduleMetadata.getInitConfig();if(!(null===(t=null==e?void 0:e.webauthn)||void 0===t?void 0:t.serverPath))return;const{clientId:i,webauthn:a}=e;H.init({clientId:i,options:r({},a)})}));const W={modal:async t=>(H.initCheck(),H.authenticate.modal(t)),autofill:{activate:t=>{H.initCheck(),H.authenticate.autofill.activate(t)},abort:()=>{H.initCheck(),H.authenticate.autofill.abort()}}},q={modal:async t=>(H.initCheck(),H.approve.modal(t))};async function F(t){return H.initCheck(),H.register(t)}const{crossDevice:M}=H,{isPlatformAuthenticatorSupported:z}=H,{isAutofillSupported:J}=H,{getDefaultPaths:$}=H;window.localWebAuthnSDK=H;var U=Object.freeze({__proto__:null,get WebauthnCrossDeviceStatus(){return exports.WebauthnCrossDeviceStatus},approve:q,authenticate:W,crossDevice:M,getDefaultPaths:$,isAutofillSupported:J,isPlatformAuthenticatorSupported:z,register:F});const V={initialize:e.initialize,...U};Object.defineProperty(exports,"initialize",{enumerable:!0,get:function(){return e.initialize}}),exports.PACKAGE_VERSION="2.0.1",exports.approve=q,exports.authenticate=W,exports.crossDevice=M,exports.getDefaultPaths=$,exports.isAutofillSupported=J,exports.isPlatformAuthenticatorSupported=z,exports.register=F,exports.webauthn=V;
1
+ "undefined"==typeof globalThis&&("undefined"!=typeof window?(window.globalThis=window,window.global=window):"undefined"!=typeof self&&(self.globalThis=self,self.global=self));var t=require("./common.cjs"),e=require("./common.cjs");function i(t,e,i){return(e=function(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var i=t[Symbol.toPrimitive];if(void 0!==i){var a=i.call(t,e||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:e+""}(e))in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function a(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function r(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{};e%2?a(Object(r),!0).forEach((function(e){i(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}class n{static arrayBufferToBase64(t){return btoa(String.fromCharCode(...new Uint8Array(t)))}static base64ToArrayBuffer(t){return Uint8Array.from(atob(t),(t=>t.charCodeAt(0)))}static stringToBase64(t){return btoa(t)}static jsonToBase64(t){const e=JSON.stringify(t);return btoa(e)}static base64ToJson(t){const e=atob(t);return JSON.parse(e)}}const s={log:console.log,error:console.error};var o,c;!function(t){t.NotInitialized="not_initialized",t.AuthenticationFailed="authentication_failed",t.AuthenticationAbortedTimeout="authentication_aborted_timeout",t.AuthenticationCanceled="webauthn_authentication_canceled",t.RegistrationFailed="registration_failed",t.AlreadyRegistered="username_already_registered",t.RegistrationAbortedTimeout="registration_aborted_timeout",t.RegistrationCanceled="webauthn_registration_canceled",t.AutofillAuthenticationAborted="autofill_authentication_aborted",t.AuthenticationProcessAlreadyActive="authentication_process_already_active",t.InvalidApprovalData="invalid_approval_data",t.FailedToInitCrossDeviceSession="cross_device_init_failed",t.FailedToGetCrossDeviceStatus="cross_device_status_failed",t.Unknown="unknown"}(o||(o={}));class l extends Error{constructor(t,e){super(t),this.errorCode=o.NotInitialized,this.data=e}}class u extends l{constructor(t,e){super(null!=t?t:"WebAuthnSdk is not initialized",e),this.errorCode=o.NotInitialized}}class d extends l{constructor(t,e){super(null!=t?t:"Authentication failed with an error",e),this.errorCode=o.AuthenticationFailed}}class h extends l{constructor(t,e){super(null!=t?t:"Authentication was canceled by the user or got timeout",e),this.errorCode=o.AuthenticationCanceled}}class p extends l{constructor(t,e){super(null!=t?t:"Registration failed with an error",e),this.errorCode=o.RegistrationFailed}}class v extends l{constructor(t,e){super(null!=t?t:"Registration was canceled by the user or got timeout",e),this.errorCode=o.RegistrationCanceled}}class g extends l{constructor(t){super(null!=t?t:"Autofill flow was aborted"),this.errorCode=o.AutofillAuthenticationAborted}}class f extends l{constructor(t){super(null!=t?t:"Operation was aborted by timeout"),this.errorCode=o.AutofillAuthenticationAborted}}class w extends l{constructor(t){super(null!=t?t:"Passkey with this username is already registered with the relying party."),this.errorCode=o.AlreadyRegistered}}class m extends l{constructor(t,e){super(null!=t?t:"Authentication process is already active",e),this.errorCode=o.AuthenticationProcessAlreadyActive}}class y extends l{constructor(t,e){super(null!=t?t:"Invalid approval data",e),this.errorCode=o.InvalidApprovalData}}class b extends l{constructor(t,e){super(null!=t?t:"Failed to init cross device authentication",e),this.errorCode=o.FailedToInitCrossDeviceSession}}class C extends l{constructor(t,e){super(null!=t?t:"Failed to get cross device status",e),this.errorCode=o.FailedToGetCrossDeviceStatus}}function A(t){return t.errorCode&&Object.values(o).includes(t.errorCode)}!function(t){t[t.persistent=0]="persistent",t[t.session=1]="session"}(c||(c={}));class D{static get(t){return D.getStorageMedium(D.allowedKeys[t]).getItem(D.getStorageKey(t))||void 0}static set(t,e){return D.getStorageMedium(D.allowedKeys[t]).setItem(D.getStorageKey(t),e)}static remove(t){D.getStorageMedium(D.allowedKeys[t]).removeItem(D.getStorageKey(t))}static clear(t){for(const[e,i]of Object.entries(D.allowedKeys)){const a=e;t&&this.configurationKeys.includes(a)||D.getStorageMedium(i).removeItem(D.getStorageKey(a))}}static getStorageKey(t){return`WebAuthnSdk:${t}`}static getStorageMedium(t){return t===c.session?sessionStorage:localStorage}}D.allowedKeys={clientId:c.session},D.configurationKeys=["clientId"];class _{static isNewApiDomain(t){return t&&(this.newApiDomains.includes(t)||t.startsWith("api.")&&t.endsWith(".transmitsecurity.io"))}static dnsPrefetch(t){const e=document.createElement("link");e.rel="dns-prefetch",e.href=t,document.head.appendChild(e)}static preconnect(t,e){const i=document.createElement("link");i.rel="preconnect",i.href=t,e&&(i.crossOrigin="anonymous"),document.head.appendChild(i)}static warmupConnection(t){this.dnsPrefetch(t),this.preconnect(t,!1),this.preconnect(t,!0)}static init(t,e){var i,a;try{this._serverPath=new URL(e.serverPath),this.isNewApiDomain(null===(i=this._serverPath)||void 0===i?void 0:i.hostname)&&this.warmupConnection(this._serverPath.origin),this._apiPaths=null!==(a=e.webauthnApiPaths)&&void 0!==a?a:this.getDefaultPaths(),this._clientId=t,D.set("clientId",t)}catch(t){throw new u("Invalid options.serverPath",{error:t})}}static getDefaultPaths(){var t;const e=this.isNewApiDomain(null===(t=this._serverPath)||void 0===t?void 0:t.hostname)?"/cis":"";return{startAuthentication:`${e}/v1/auth/webauthn/authenticate/start`,startRegistration:`${e}/v1/auth/webauthn/register/start`,initCrossDeviceAuthentication:`${e}/v1/auth/webauthn/cross-device/authenticate/init`,startCrossDeviceAuthentication:`${e}/v1/auth/webauthn/cross-device/authenticate/start`,startCrossDeviceRegistration:`${e}/v1/auth/webauthn/cross-device/register/start`,getCrossDeviceTicketStatus:`${e}/v1/auth/webauthn/cross-device/status`,attachDeviceToCrossDeviceSession:`${e}/v1/auth/webauthn/cross-device/attach-device`}}static getApiPaths(){return this._apiPaths}static async sendRequest(t,e,i){s.log(`[WebAuthn SDK] Calling ${e.method} ${t}...`);const a=new URL(this._serverPath);return a.pathname=t,i&&(a.search=i),fetch(a.toString(),e)}static async startRegistration(t){const e=await this.sendRequest(this._apiPaths.startRegistration,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r(r({client_id:this.getValidatedClientId(),username:t.username,display_name:t.displayName},t.timeout&&{timeout:t.timeout}),t.limitSingleCredentialToDevice&&{limit_single_credential_to_device:t.limitSingleCredentialToDevice}))});if(!(null==e?void 0:e.ok))throw new d("Failed to start registration",null==e?void 0:e.body);return await e.json()}static async startAuthentication(t){const e=await this.sendRequest(this._apiPaths.startAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r(r(r(r(r({client_id:this.getValidatedClientId()},t.username&&{username:t.username}),t.identifier&&{identifier:t.identifier}),t.identifierType&&{identifier_type:t.identifierType}),t.approvalData&&{approval_data:t.approvalData}),t.timeout&&{timeout:t.timeout}))});if(!(null==e?void 0:e.ok))throw new d("Failed to start authentication",null==e?void 0:e.body);return await e.json()}static async initCrossDeviceAuthentication(t){const e=await this.sendRequest(this._apiPaths.initCrossDeviceAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r(r({client_id:this.getValidatedClientId()},t.username&&{username:t.username}),t.approvalData&&{approval_data:t.approvalData}))});if(!(null==e?void 0:e.ok))throw new b(void 0,null==e?void 0:e.body);return await e.json()}static async getCrossDeviceTicketStatus(t){const e=await this.sendRequest(this._apiPaths.getCrossDeviceTicketStatus,{method:"GET"},`cross_device_ticket_id=${t.ticketId}`);if(!(null==e?void 0:e.ok))throw new C(void 0,null==e?void 0:e.body);return await e.json()}static async startCrossDeviceAuthentication(t){const e=await this.sendRequest(this._apiPaths.startCrossDeviceAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new d("Failed to start cross device authentication",null==e?void 0:e.body);return await e.json()}static async startCrossDeviceRegistration(t){const e=await this.sendRequest(this._apiPaths.startCrossDeviceRegistration,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new p("Failed to start cross device registration",null==e?void 0:e.body);return await e.json()}static async attachDeviceToCrossDeviceSession(t){const e=await this.sendRequest(this._apiPaths.attachDeviceToCrossDeviceSession,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new p("Failed to attach device to cross device session",null==e?void 0:e.body);return await e.json()}static getValidatedClientId(){var t;const e=null!==(t=this._clientId)&&void 0!==t?t:D.get("clientId");if(!e)throw new u("Missing clientId");return e}}var S,T,k,I;_.newApiDomains=["api.idsec-dev.com","api.idsec-stg.com"],function(t){t.InputAutofill="input-autofill",t.Modal="modal"}(S||(S={})),exports.WebauthnCrossDeviceStatus=void 0,(T=exports.WebauthnCrossDeviceStatus||(exports.WebauthnCrossDeviceStatus={})).Pending="pending",T.Scanned="scanned",T.Success="success",T.Error="error",T.Timeout="timeout",T.Aborted="aborted",function(t){t.toAuthenticationError=t=>A(t)?t:"NotAllowedError"===t.name?new h:"OperationError"===t.name?new m(t.message):"SecurityError"===t.name?new d(t.message):t===o.AuthenticationAbortedTimeout?new f:"AbortError"===t.name||t===o.AutofillAuthenticationAborted?new g:new d("Something went wrong during authentication",{error:t}),t.toRegistrationError=t=>A(t)?t:"NotAllowedError"===t.name?new v:"SecurityError"===t.name?new p(t.message):"InvalidStateError"===t.name?new w:t===o.RegistrationAbortedTimeout?new f:new p("Something went wrong during registration",{error:t})}(k||(k={})),function(t){t.processCredentialRequestOptions=t=>r(r({},t),{},{challenge:n.base64ToArrayBuffer(t.challenge),allowCredentials:t.allowCredentials.map((t=>r(r({},t),{},{id:n.base64ToArrayBuffer(t.id)})))}),t.processCredentialCreationOptions=(t,e)=>{var i;const a=JSON.parse(JSON.stringify(t));return a.challenge=n.base64ToArrayBuffer(t.challenge),a.user.id=n.base64ToArrayBuffer(t.user.id),(null==e?void 0:e.limitSingleCredentialToDevice)&&(a.excludeCredentials=null===(i=t.excludeCredentials)||void 0===i?void 0:i.map((t=>r(r({},t),{},{id:n.base64ToArrayBuffer(t.id)})))),(null==e?void 0:e.registerAsDiscoverable)?(a.authenticatorSelection.residentKey="preferred",a.authenticatorSelection.requireResidentKey=!0):(a.authenticatorSelection.residentKey="discouraged",a.authenticatorSelection.requireResidentKey=!1),a.authenticatorSelection.authenticatorAttachment=(null==e?void 0:e.allowCrossPlatformAuthenticators)?void 0:"platform",a},t.encodeAuthenticationResult=t=>{const{authenticatorAttachment:e}=t,i=t.response;return{id:t.id,rawId:n.arrayBufferToBase64(t.rawId),response:{authenticatorData:n.arrayBufferToBase64(i.authenticatorData),clientDataJSON:n.arrayBufferToBase64(i.clientDataJSON),signature:n.arrayBufferToBase64(i.signature),userHandle:n.arrayBufferToBase64(i.userHandle)},authenticatorAttachment:e,type:t.type}},t.encodeRegistrationResult=t=>{const{authenticatorAttachment:e}=t,i=t.response;return{id:t.id,rawId:n.arrayBufferToBase64(t.rawId),response:{attestationObject:n.arrayBufferToBase64(i.attestationObject),clientDataJSON:n.arrayBufferToBase64(i.clientDataJSON)},authenticatorAttachment:e,type:t.type}}}(I||(I={}));class P{async modal(t){try{const e=await this.performAuthentication(r(r({},t),{},{mediationType:S.Modal}));return n.jsonToBase64(e)}catch(t){throw k.toAuthenticationError(t)}}activateAutofill(t){const{handlers:e,username:i}=t,{onSuccess:a,onError:r,onReady:s}=e;this.performAuthentication({username:i,mediationType:S.InputAutofill,onReady:s}).then((t=>{a(n.jsonToBase64(t))})).catch((t=>{const e=k.toAuthenticationError(t);if(!r)throw e;r(e)}))}abortAutofill(){this.abortController&&this.abortController.abort(o.AutofillAuthenticationAborted)}abortAuthentication(){this.abortController&&this.abortController.abort(o.AuthenticationAbortedTimeout)}async performAuthentication(t){var e,i;const a="crossDeviceTicketId"in t?await _.startCrossDeviceAuthentication({ticketId:t.crossDeviceTicketId}):await _.startAuthentication({username:t.username,identifier:t.identifier,identifierType:t.identifierType,timeout:null===(e=t.options)||void 0===e?void 0:e.timeout}),r=a.credential_request_options,n=I.processCredentialRequestOptions(r),s=this.getMediatedCredentialRequest(n,t.mediationType);t.mediationType===S.InputAutofill&&(null===(i=t.onReady)||void 0===i||i.call(t));const o=await navigator.credentials.get(s).catch((t=>{throw k.toAuthenticationError(t)}));return{webauthnSessionId:a.webauthn_session_id,publicKeyCredential:I.encodeAuthenticationResult(o),userAgent:navigator.userAgent}}getMediatedCredentialRequest(t,e){const i={publicKey:t};return this.abortController=new AbortController,i.signal=this.abortController&&this.abortController.signal,e===S.InputAutofill?i.mediation="conditional":t.timeout&&setTimeout((()=>{this.abortAuthentication()}),t.timeout),i}}class O{constructor(t,e){this.handler=t,this.intervalInMs=e}begin(){var t;this.intervalId=window.setInterval((t=this.handler,async function(){t.isRunning||(t.isRunning=!0,await t(...arguments),t.isRunning=!1)}),this.intervalInMs)}stop(){clearInterval(this.intervalId)}}const R=/^[A-Za-z0-9\-_.: ]*$/;function j(t){if(t&&(!function(t){return Object.keys(t).length<=10}(t)||!function(t){const e=t=>"string"==typeof t,i=t=>R.test(t);return Object.keys(t).every((a=>e(a)&&e(t[a])&&i(a)&&i(t[a])))}(t)))throw s.error("Failed validating approval data"),new y("Provided approval data should have 10 properties max. Also, it should contain only \n alphanumeric characters, numbers, and the special characters: '-', '_', '.'")}class x{constructor(t,e,i){this.authenticationHandler=t,this.registrationHandler=e,this.approvalHandler=i,this.init={registration:async t=>(this.ticketStatus=exports.WebauthnCrossDeviceStatus.Pending,this.pollCrossDeviceSession(t.crossDeviceTicketId,t.handlers)),authentication:async t=>{const{username:e}=t,i=(await _.initCrossDeviceAuthentication(r({},e&&{username:e}))).cross_device_ticket_id;return this.ticketStatus=exports.WebauthnCrossDeviceStatus.Pending,this.pollCrossDeviceSession(i,t.handlers)},approval:async t=>{const{username:e,approvalData:i}=t;j(i);const a=(await _.initCrossDeviceAuthentication({username:e,approvalData:i})).cross_device_ticket_id;return this.ticketStatus=exports.WebauthnCrossDeviceStatus.Pending,this.pollCrossDeviceSession(a,t.handlers)}},this.authenticate={modal:async t=>this.authenticationHandler.modal({crossDeviceTicketId:t})},this.approve={modal:async t=>this.approvalHandler.modal({crossDeviceTicketId:t})}}async register(t){return this.registrationHandler.register(t)}async attachDevice(t){const e=await _.attachDeviceToCrossDeviceSession({ticketId:t});return r({status:e.status,startedAt:e.started_at},e.approval_data&&{approvalData:e.approval_data})}async pollCrossDeviceSession(t,e){return this.poller=new O((async()=>{var i,a;const r=await _.getCrossDeviceTicketStatus({ticketId:t}),n=r.status;if(n!==this.ticketStatus)switch(this.ticketStatus=n,n){case exports.WebauthnCrossDeviceStatus.Scanned:await e.onDeviceAttach();break;case exports.WebauthnCrossDeviceStatus.Error:case exports.WebauthnCrossDeviceStatus.Timeout:case exports.WebauthnCrossDeviceStatus.Aborted:await e.onFailure(r),null===(i=this.poller)||void 0===i||i.stop();break;case exports.WebauthnCrossDeviceStatus.Success:if("onCredentialRegister"in e)await e.onCredentialRegister();else{if(!r.session_id)throw new C("Cross device session is complete without returning session_id",r);await e.onCredentialAuthenticate(r.session_id)}null===(a=this.poller)||void 0===a||a.stop()}}),1e3),this.poller.begin(),setTimeout((()=>{var t;null===(t=this.poller)||void 0===t||t.stop(),e.onFailure({status:exports.WebauthnCrossDeviceStatus.Timeout})}),3e5),{crossDeviceTicketId:t,stop:()=>{var t;null===(t=this.poller)||void 0===t||t.stop()}}}}class K{async register(t){var e,i,a;this.abortController=new AbortController;const s=r({allowCrossPlatformAuthenticators:!("crossDeviceTicketId"in t),registerAsDiscoverable:!0},t.options);try{const r="crossDeviceTicketId"in t?await _.startCrossDeviceRegistration({ticketId:t.crossDeviceTicketId}):await _.startRegistration({username:t.username,displayName:(null===(e=t.options)||void 0===e?void 0:e.displayName)||t.username,timeout:null===(i=t.options)||void 0===i?void 0:i.timeout,limitSingleCredentialToDevice:null===(a=t.options)||void 0===a?void 0:a.limitSingleCredentialToDevice}),o=I.processCredentialCreationOptions(r.credential_creation_options,s);setTimeout((()=>{this.abortRegistration()}),o.timeout);const c=await this.registerCredential(o),l={webauthnSessionId:r.webauthn_session_id,publicKeyCredential:c,userAgent:navigator.userAgent};return n.jsonToBase64(l)}catch(t){throw k.toRegistrationError(t)}}abortRegistration(){this.abortController&&this.abortController.abort(o.RegistrationAbortedTimeout)}async registerCredential(t){const e=await navigator.credentials.create({publicKey:t,signal:this.abortController&&this.abortController.signal}).catch((t=>{throw k.toRegistrationError(t)}));return I.encodeRegistrationResult(e)}}class B{async modal(t){try{const e=await this.performApproval(t);return n.jsonToBase64(e)}catch(t){throw k.toAuthenticationError(t)}}async performApproval(t){"approvalData"in t&&j(t.approvalData);const e="crossDeviceTicketId"in t?await _.startCrossDeviceAuthentication({ticketId:t.crossDeviceTicketId}):await _.startAuthentication({username:t.username,approvalData:t.approvalData}),i=e.credential_request_options,a=I.processCredentialRequestOptions(i),r=await navigator.credentials.get({publicKey:a}).catch((t=>{throw k.toAuthenticationError(t)}));return{webauthnSessionId:e.webauthn_session_id,publicKeyCredential:I.encodeAuthenticationResult(r),userAgent:navigator.userAgent}}}class E{constructor(){this._initialized=!1,this._authenticationHandler=new P,this._registrationHandler=new K,this._approvalHandler=new B,this._crossDeviceHandler=new x(this._authenticationHandler,this._registrationHandler,this._approvalHandler),this.authenticate={modal:async t=>(this.initCheck(),this._authenticationHandler.modal(t)),autofill:{activate:t=>(this.initCheck(),this._authenticationHandler.activateAutofill(t)),abort:()=>this._authenticationHandler.abortAutofill()}},this.approve={modal:async t=>(this.initCheck(),this._approvalHandler.modal(t))},this.register=async t=>(this.initCheck(),this._registrationHandler.register(t)),this.crossDevice={init:{registration:async t=>(this.initCheck(),this._crossDeviceHandler.init.registration(t)),authentication:async t=>(this.initCheck(),this._crossDeviceHandler.init.authentication(t)),approval:async t=>(this.initCheck(),this._crossDeviceHandler.init.approval(t))},authenticate:{modal:async t=>(this.initCheck(),this._crossDeviceHandler.authenticate.modal(t))},approve:{modal:async t=>(this.initCheck(),this._crossDeviceHandler.approve.modal(t))},register:async t=>(this.initCheck(),this._crossDeviceHandler.register(t)),attachDevice:async t=>(this.initCheck(),this._crossDeviceHandler.attachDevice(t))},this.isPlatformAuthenticatorSupported=async()=>{var t;try{return await(null===(t=E.StaticPublicKeyCredential)||void 0===t?void 0:t.isUserVerifyingPlatformAuthenticatorAvailable())}catch(t){return!1}},this.isAutofillSupported=async()=>{var t,e;return!(!(null===(t=E.StaticPublicKeyCredential)||void 0===t?void 0:t.isConditionalMediationAvailable)||!await(null===(e=E.StaticPublicKeyCredential)||void 0===e?void 0:e.isConditionalMediationAvailable()))}}async init(t){const{clientId:e,options:i}=t;try{if(!e)throw new u("Invalid clientId",{clientId:e});if(i.webauthnApiPaths){const t=_.getDefaultPaths();if(function(t,e){const i=new Set(t),a=new Set(e);return[...t.filter((t=>!a.has(t))),...e.filter((t=>!i.has(t)))]}(Object.keys(i.webauthnApiPaths),Object.keys(t)).length)throw new u("Invalid custom paths",{customApiPaths:i.webauthnApiPaths})}_.init(e,i),this._initialized=!0}catch(t){throw A(t)?t:new u("Failed to initialize SDK")}}getDefaultPaths(){return this.initCheck(),_.getDefaultPaths()}getApiPaths(){return this.initCheck(),_.getApiPaths()}initCheck(){if(!this._initialized)throw new u}}E.StaticPublicKeyCredential=window.PublicKeyCredential;const N=new t("webauthn"),H=new E;N.events.on(N.events.MODULE_INITIALIZED,(()=>{var t;const e=N.moduleMetadata.getInitConfig();if(!(null===(t=null==e?void 0:e.webauthn)||void 0===t?void 0:t.serverPath))return;const{clientId:i,webauthn:a}=e;H.init({clientId:i,options:r({},a)})}));const W={modal:async t=>(H.initCheck(),H.authenticate.modal(t)),autofill:{activate:t=>{H.initCheck(),H.authenticate.autofill.activate(t)},abort:()=>{H.initCheck(),H.authenticate.autofill.abort()}}},q={modal:async t=>(H.initCheck(),H.approve.modal(t))};async function F(t){return H.initCheck(),H.register(t)}const{crossDevice:M}=H,{isPlatformAuthenticatorSupported:z}=H,{isAutofillSupported:J}=H,{getDefaultPaths:$}=H;window.localWebAuthnSDK=H;var U=Object.freeze({__proto__:null,get WebauthnCrossDeviceStatus(){return exports.WebauthnCrossDeviceStatus},approve:q,authenticate:W,crossDevice:M,getDefaultPaths:$,isAutofillSupported:J,isPlatformAuthenticatorSupported:z,register:F});const V={initialize:e.initialize,...U};Object.defineProperty(exports,"initialize",{enumerable:!0,get:function(){return e.initialize}}),exports.PACKAGE_VERSION="2.1.1",exports.approve=q,exports.authenticate=W,exports.crossDevice=M,exports.getDefaultPaths=$,exports.isAutofillSupported=J,exports.isPlatformAuthenticatorSupported=z,exports.register=F,exports.webauthn=V;
package/dist/webauthn.js CHANGED
@@ -1 +1 @@
1
- "undefined"==typeof globalThis&&("undefined"!=typeof window?(window.globalThis=window,window.global=window):"undefined"!=typeof self&&(self.globalThis=self,self.global=self));import t from"./common.js";import{initialize as e}from"./common.js";export{initialize}from"./common.js";function i(t,e,i){return(e=function(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var i=t[Symbol.toPrimitive];if(void 0!==i){var a=i.call(t,e||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:e+""}(e))in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function a(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function n(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?a(Object(n),!0).forEach((function(e){i(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}class r{static arrayBufferToBase64(t){return btoa(String.fromCharCode(...new Uint8Array(t)))}static base64ToArrayBuffer(t){return Uint8Array.from(atob(t),(t=>t.charCodeAt(0)))}static stringToBase64(t){return btoa(t)}static jsonToBase64(t){const e=JSON.stringify(t);return btoa(e)}static base64ToJson(t){const e=atob(t);return JSON.parse(e)}}const o={log:console.log,error:console.error};var s,c;!function(t){t.NotInitialized="not_initialized",t.AuthenticationFailed="authentication_failed",t.AuthenticationAbortedTimeout="authentication_aborted_timeout",t.AuthenticationCanceled="webauthn_authentication_canceled",t.RegistrationFailed="registration_failed",t.AlreadyRegistered="username_already_registered",t.RegistrationAbortedTimeout="registration_aborted_timeout",t.RegistrationCanceled="webauthn_registration_canceled",t.AutofillAuthenticationAborted="autofill_authentication_aborted",t.AuthenticationProcessAlreadyActive="authentication_process_already_active",t.InvalidApprovalData="invalid_approval_data",t.FailedToInitCrossDeviceSession="cross_device_init_failed",t.FailedToGetCrossDeviceStatus="cross_device_status_failed",t.Unknown="unknown"}(s||(s={}));class l extends Error{constructor(t,e){super(t),this.errorCode=s.NotInitialized,this.data=e}}class u extends l{constructor(t,e){super(null!=t?t:"WebAuthnSdk is not initialized",e),this.errorCode=s.NotInitialized}}class d extends l{constructor(t,e){super(null!=t?t:"Authentication failed with an error",e),this.errorCode=s.AuthenticationFailed}}class h extends l{constructor(t,e){super(null!=t?t:"Authentication was canceled by the user or got timeout",e),this.errorCode=s.AuthenticationCanceled}}class p extends l{constructor(t,e){super(null!=t?t:"Registration failed with an error",e),this.errorCode=s.RegistrationFailed}}class v extends l{constructor(t,e){super(null!=t?t:"Registration was canceled by the user or got timeout",e),this.errorCode=s.RegistrationCanceled}}class g extends l{constructor(t){super(null!=t?t:"Autofill flow was aborted"),this.errorCode=s.AutofillAuthenticationAborted}}class m extends l{constructor(t){super(null!=t?t:"Operation was aborted by timeout"),this.errorCode=s.AutofillAuthenticationAborted}}class f extends l{constructor(t){super(null!=t?t:"Passkey with this username is already registered with the relying party."),this.errorCode=s.AlreadyRegistered}}class w extends l{constructor(t,e){super(null!=t?t:"Authentication process is already active",e),this.errorCode=s.AuthenticationProcessAlreadyActive}}class y extends l{constructor(t,e){super(null!=t?t:"Invalid approval data",e),this.errorCode=s.InvalidApprovalData}}class b extends l{constructor(t,e){super(null!=t?t:"Failed to init cross device authentication",e),this.errorCode=s.FailedToInitCrossDeviceSession}}class A extends l{constructor(t,e){super(null!=t?t:"Failed to get cross device status",e),this.errorCode=s.FailedToGetCrossDeviceStatus}}function C(t){return t.errorCode&&Object.values(s).includes(t.errorCode)}!function(t){t[t.persistent=0]="persistent",t[t.session=1]="session"}(c||(c={}));class _{static get(t){return _.getStorageMedium(_.allowedKeys[t]).getItem(_.getStorageKey(t))||void 0}static set(t,e){return _.getStorageMedium(_.allowedKeys[t]).setItem(_.getStorageKey(t),e)}static remove(t){_.getStorageMedium(_.allowedKeys[t]).removeItem(_.getStorageKey(t))}static clear(t){for(const[e,i]of Object.entries(_.allowedKeys)){const a=e;t&&this.configurationKeys.includes(a)||_.getStorageMedium(i).removeItem(_.getStorageKey(a))}}static getStorageKey(t){return`WebAuthnSdk:${t}`}static getStorageMedium(t){return t===c.session?sessionStorage:localStorage}}_.allowedKeys={clientId:c.session},_.configurationKeys=["clientId"];class D{static isNewApiDomain(t){return t&&(this.newApiDomains.includes(t)||t.startsWith("api.")&&t.endsWith(".transmitsecurity.io"))}static dnsPrefetch(t){const e=document.createElement("link");e.rel="dns-prefetch",e.href=t,document.head.appendChild(e)}static preconnect(t,e){const i=document.createElement("link");i.rel="preconnect",i.href=t,e&&(i.crossOrigin="anonymous"),document.head.appendChild(i)}static warmupConnection(t){this.dnsPrefetch(t),this.preconnect(t,!1),this.preconnect(t,!0)}static init(t,e){var i,a;try{this._serverPath=new URL(e.serverPath),this.isNewApiDomain(null===(i=this._serverPath)||void 0===i?void 0:i.hostname)&&this.warmupConnection(this._serverPath.origin),this._apiPaths=null!==(a=e.webauthnApiPaths)&&void 0!==a?a:this.getDefaultPaths(),this._clientId=t,_.set("clientId",t)}catch(t){throw new u("Invalid options.serverPath",{error:t})}}static getDefaultPaths(){var t;const e=this.isNewApiDomain(null===(t=this._serverPath)||void 0===t?void 0:t.hostname)?"/cis":"";return{startAuthentication:`${e}/v1/auth/webauthn/authenticate/start`,startRegistration:`${e}/v1/auth/webauthn/register/start`,initCrossDeviceAuthentication:`${e}/v1/auth/webauthn/cross-device/authenticate/init`,startCrossDeviceAuthentication:`${e}/v1/auth/webauthn/cross-device/authenticate/start`,startCrossDeviceRegistration:`${e}/v1/auth/webauthn/cross-device/register/start`,getCrossDeviceTicketStatus:`${e}/v1/auth/webauthn/cross-device/status`,attachDeviceToCrossDeviceSession:`${e}/v1/auth/webauthn/cross-device/attach-device`}}static getApiPaths(){return this._apiPaths}static async sendRequest(t,e,i){o.log(`[WebAuthn SDK] Calling ${e.method} ${t}...`);const a=new URL(this._serverPath);return a.pathname=t,i&&(a.search=i),fetch(a.toString(),e)}static async startRegistration(t){const e=await this.sendRequest(this._apiPaths.startRegistration,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n(n({client_id:this.getValidatedClientId(),username:t.username,display_name:t.displayName},t.timeout&&{timeout:t.timeout}),t.limitSingleCredentialToDevice&&{limit_single_credential_to_device:t.limitSingleCredentialToDevice}))});if(!(null==e?void 0:e.ok))throw new d("Failed to start registration",null==e?void 0:e.body);return await e.json()}static async startAuthentication(t){const e=await this.sendRequest(this._apiPaths.startAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n(n(n(n(n({client_id:this.getValidatedClientId()},t.username&&{username:t.username}),t.identifier&&{identifier:t.identifier}),t.identifierType&&{identifier_type:t.identifierType}),t.approvalData&&{approval_data:t.approvalData}),t.timeout&&{timeout:t.timeout}))});if(!(null==e?void 0:e.ok))throw new d("Failed to start authentication",null==e?void 0:e.body);return await e.json()}static async initCrossDeviceAuthentication(t){const e=await this.sendRequest(this._apiPaths.initCrossDeviceAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n(n({client_id:this.getValidatedClientId()},t.username&&{username:t.username}),t.approvalData&&{approval_data:t.approvalData}))});if(!(null==e?void 0:e.ok))throw new b(void 0,null==e?void 0:e.body);return await e.json()}static async getCrossDeviceTicketStatus(t){const e=await this.sendRequest(this._apiPaths.getCrossDeviceTicketStatus,{method:"GET"},`cross_device_ticket_id=${t.ticketId}`);if(!(null==e?void 0:e.ok))throw new A(void 0,null==e?void 0:e.body);return await e.json()}static async startCrossDeviceAuthentication(t){const e=await this.sendRequest(this._apiPaths.startCrossDeviceAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new d("Failed to start cross device authentication",null==e?void 0:e.body);return await e.json()}static async startCrossDeviceRegistration(t){const e=await this.sendRequest(this._apiPaths.startCrossDeviceRegistration,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new p("Failed to start cross device registration",null==e?void 0:e.body);return await e.json()}static async attachDeviceToCrossDeviceSession(t){const e=await this.sendRequest(this._apiPaths.attachDeviceToCrossDeviceSession,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new p("Failed to attach device to cross device session",null==e?void 0:e.body);return await e.json()}static getValidatedClientId(){var t;const e=null!==(t=this._clientId)&&void 0!==t?t:_.get("clientId");if(!e)throw new u("Missing clientId");return e}}var S,T,k,I;D.newApiDomains=["api.idsec-dev.com","api.idsec-stg.com"],function(t){t.InputAutofill="input-autofill",t.Modal="modal"}(S||(S={})),function(t){t.Pending="pending",t.Scanned="scanned",t.Success="success",t.Error="error",t.Timeout="timeout",t.Aborted="aborted"}(T||(T={})),function(t){t.toAuthenticationError=t=>C(t)?t:"NotAllowedError"===t.name?new h:"OperationError"===t.name?new w(t.message):"SecurityError"===t.name?new d(t.message):t===s.AuthenticationAbortedTimeout?new m:"AbortError"===t.name||t===s.AutofillAuthenticationAborted?new g:new d("Something went wrong during authentication",{error:t}),t.toRegistrationError=t=>C(t)?t:"NotAllowedError"===t.name?new v:"SecurityError"===t.name?new p(t.message):"InvalidStateError"===t.name?new f:t===s.RegistrationAbortedTimeout?new m:new p("Something went wrong during registration",{error:t})}(k||(k={})),function(t){t.processCredentialRequestOptions=t=>n(n({},t),{},{challenge:r.base64ToArrayBuffer(t.challenge),allowCredentials:t.allowCredentials.map((t=>n(n({},t),{},{id:r.base64ToArrayBuffer(t.id)})))}),t.processCredentialCreationOptions=(t,e)=>{var i;const a=JSON.parse(JSON.stringify(t));return a.challenge=r.base64ToArrayBuffer(t.challenge),a.user.id=r.base64ToArrayBuffer(t.user.id),(null==e?void 0:e.limitSingleCredentialToDevice)&&(a.excludeCredentials=null===(i=t.excludeCredentials)||void 0===i?void 0:i.map((t=>n(n({},t),{},{id:r.base64ToArrayBuffer(t.id)})))),(null==e?void 0:e.registerAsDiscoverable)?(a.authenticatorSelection.residentKey="preferred",a.authenticatorSelection.requireResidentKey=!0):(a.authenticatorSelection.residentKey="discouraged",a.authenticatorSelection.requireResidentKey=!1),a.authenticatorSelection.authenticatorAttachment=(null==e?void 0:e.allowCrossPlatformAuthenticators)?void 0:"platform",a},t.encodeAuthenticationResult=t=>{const{authenticatorAttachment:e}=t,i=t.response;return{id:t.id,rawId:r.arrayBufferToBase64(t.rawId),response:{authenticatorData:r.arrayBufferToBase64(i.authenticatorData),clientDataJSON:r.arrayBufferToBase64(i.clientDataJSON),signature:r.arrayBufferToBase64(i.signature),userHandle:r.arrayBufferToBase64(i.userHandle)},authenticatorAttachment:e,type:t.type}},t.encodeRegistrationResult=t=>{const{authenticatorAttachment:e}=t,i=t.response;return{id:t.id,rawId:r.arrayBufferToBase64(t.rawId),response:{attestationObject:r.arrayBufferToBase64(i.attestationObject),clientDataJSON:r.arrayBufferToBase64(i.clientDataJSON)},authenticatorAttachment:e,type:t.type}}}(I||(I={}));class P{async modal(t){try{const e=await this.performAuthentication(n(n({},t),{},{mediationType:S.Modal}));return r.jsonToBase64(e)}catch(t){throw k.toAuthenticationError(t)}}activateAutofill(t){const{handlers:e,username:i}=t,{onSuccess:a,onError:n,onReady:o}=e;this.performAuthentication({username:i,mediationType:S.InputAutofill,onReady:o}).then((t=>{a(r.jsonToBase64(t))})).catch((t=>{const e=k.toAuthenticationError(t);if(!n)throw e;n(e)}))}abortAutofill(){this.abortController&&this.abortController.abort(s.AutofillAuthenticationAborted)}abortAuthentication(){this.abortController&&this.abortController.abort(s.AuthenticationAbortedTimeout)}async performAuthentication(t){var e,i;const a="crossDeviceTicketId"in t?await D.startCrossDeviceAuthentication({ticketId:t.crossDeviceTicketId}):await D.startAuthentication({username:t.username,identifier:t.identifier,identifierType:t.identifierType,timeout:null===(e=t.options)||void 0===e?void 0:e.timeout}),n=a.credential_request_options,r=I.processCredentialRequestOptions(n),o=this.getMediatedCredentialRequest(r,t.mediationType);t.mediationType===S.InputAutofill&&(null===(i=t.onReady)||void 0===i||i.call(t));const s=await navigator.credentials.get(o).catch((t=>{throw k.toAuthenticationError(t)}));return{webauthnSessionId:a.webauthn_session_id,publicKeyCredential:I.encodeAuthenticationResult(s),userAgent:navigator.userAgent}}getMediatedCredentialRequest(t,e){const i={publicKey:t};return this.abortController=new AbortController,i.signal=this.abortController&&this.abortController.signal,e===S.InputAutofill?i.mediation="conditional":t.timeout&&setTimeout((()=>{this.abortAuthentication()}),t.timeout),i}}class O{constructor(t,e){this.handler=t,this.intervalInMs=e}begin(){var t;this.intervalId=window.setInterval((t=this.handler,async function(){t.isRunning||(t.isRunning=!0,await t(...arguments),t.isRunning=!1)}),this.intervalInMs)}stop(){clearInterval(this.intervalId)}}const R=/^[A-Za-z0-9\-_.: ]*$/;function j(t){if(t&&(!function(t){return Object.keys(t).length<=10}(t)||!function(t){const e=t=>"string"==typeof t,i=t=>R.test(t);return Object.keys(t).every((a=>e(a)&&e(t[a])&&i(a)&&i(t[a])))}(t)))throw o.error("Failed validating approval data"),new y("Provided approval data should have 10 properties max. Also, it should contain only \n alphanumeric characters, numbers, and the special characters: '-', '_', '.'")}class B{constructor(t,e,i){this.authenticationHandler=t,this.registrationHandler=e,this.approvalHandler=i,this.init={registration:async t=>(this.ticketStatus=T.Pending,this.pollCrossDeviceSession(t.crossDeviceTicketId,t.handlers)),authentication:async t=>{const{username:e}=t,i=(await D.initCrossDeviceAuthentication(n({},e&&{username:e}))).cross_device_ticket_id;return this.ticketStatus=T.Pending,this.pollCrossDeviceSession(i,t.handlers)},approval:async t=>{const{username:e,approvalData:i}=t;j(i);const a=(await D.initCrossDeviceAuthentication({username:e,approvalData:i})).cross_device_ticket_id;return this.ticketStatus=T.Pending,this.pollCrossDeviceSession(a,t.handlers)}},this.authenticate={modal:async t=>this.authenticationHandler.modal({crossDeviceTicketId:t})},this.approve={modal:async t=>this.approvalHandler.modal({crossDeviceTicketId:t})}}async register(t){return this.registrationHandler.register(t)}async attachDevice(t){const e=await D.attachDeviceToCrossDeviceSession({ticketId:t});return n({status:e.status,startedAt:e.started_at},e.approval_data&&{approvalData:e.approval_data})}async pollCrossDeviceSession(t,e){return this.poller=new O((async()=>{var i,a;const n=await D.getCrossDeviceTicketStatus({ticketId:t}),r=n.status;if(r!==this.ticketStatus)switch(this.ticketStatus=r,r){case T.Scanned:await e.onDeviceAttach();break;case T.Error:case T.Timeout:case T.Aborted:await e.onFailure(n),null===(i=this.poller)||void 0===i||i.stop();break;case T.Success:if("onCredentialRegister"in e)await e.onCredentialRegister();else{if(!n.session_id)throw new A("Cross device session is complete without returning session_id",n);await e.onCredentialAuthenticate(n.session_id)}null===(a=this.poller)||void 0===a||a.stop()}}),1e3),this.poller.begin(),setTimeout((()=>{var t;null===(t=this.poller)||void 0===t||t.stop(),e.onFailure({status:T.Timeout})}),3e5),{crossDeviceTicketId:t,stop:()=>{var t;null===(t=this.poller)||void 0===t||t.stop()}}}}class K{async register(t){var e,i,a;this.abortController=new AbortController;const o=n({allowCrossPlatformAuthenticators:!("crossDeviceTicketId"in t),registerAsDiscoverable:!0},t.options);try{const n="crossDeviceTicketId"in t?await D.startCrossDeviceRegistration({ticketId:t.crossDeviceTicketId}):await D.startRegistration({username:t.username,displayName:(null===(e=t.options)||void 0===e?void 0:e.displayName)||t.username,timeout:null===(i=t.options)||void 0===i?void 0:i.timeout,limitSingleCredentialToDevice:null===(a=t.options)||void 0===a?void 0:a.limitSingleCredentialToDevice}),s=I.processCredentialCreationOptions(n.credential_creation_options,o);setTimeout((()=>{this.abortRegistration()}),s.timeout);const c=await this.registerCredential(s),l={webauthnSessionId:n.webauthn_session_id,publicKeyCredential:c,userAgent:navigator.userAgent};return r.jsonToBase64(l)}catch(t){throw k.toRegistrationError(t)}}abortRegistration(){this.abortController&&this.abortController.abort(s.RegistrationAbortedTimeout)}async registerCredential(t){const e=await navigator.credentials.create({publicKey:t,signal:this.abortController&&this.abortController.signal}).catch((t=>{throw k.toRegistrationError(t)}));return I.encodeRegistrationResult(e)}}class E{async modal(t){try{const e=await this.performApproval(t);return r.jsonToBase64(e)}catch(t){throw k.toAuthenticationError(t)}}async performApproval(t){"approvalData"in t&&j(t.approvalData);const e="crossDeviceTicketId"in t?await D.startCrossDeviceAuthentication({ticketId:t.crossDeviceTicketId}):await D.startAuthentication({username:t.username,approvalData:t.approvalData}),i=e.credential_request_options,a=I.processCredentialRequestOptions(i),n=await navigator.credentials.get({publicKey:a}).catch((t=>{throw k.toAuthenticationError(t)}));return{webauthnSessionId:e.webauthn_session_id,publicKeyCredential:I.encodeAuthenticationResult(n),userAgent:navigator.userAgent}}}class H{constructor(){this._initialized=!1,this._authenticationHandler=new P,this._registrationHandler=new K,this._approvalHandler=new E,this._crossDeviceHandler=new B(this._authenticationHandler,this._registrationHandler,this._approvalHandler),this.authenticate={modal:async t=>(this.initCheck(),this._authenticationHandler.modal(t)),autofill:{activate:t=>(this.initCheck(),this._authenticationHandler.activateAutofill(t)),abort:()=>this._authenticationHandler.abortAutofill()}},this.approve={modal:async t=>(this.initCheck(),this._approvalHandler.modal(t))},this.register=async t=>(this.initCheck(),this._registrationHandler.register(t)),this.crossDevice={init:{registration:async t=>(this.initCheck(),this._crossDeviceHandler.init.registration(t)),authentication:async t=>(this.initCheck(),this._crossDeviceHandler.init.authentication(t)),approval:async t=>(this.initCheck(),this._crossDeviceHandler.init.approval(t))},authenticate:{modal:async t=>(this.initCheck(),this._crossDeviceHandler.authenticate.modal(t))},approve:{modal:async t=>(this.initCheck(),this._crossDeviceHandler.approve.modal(t))},register:async t=>(this.initCheck(),this._crossDeviceHandler.register(t)),attachDevice:async t=>(this.initCheck(),this._crossDeviceHandler.attachDevice(t))},this.isPlatformAuthenticatorSupported=async()=>{var t;try{return await(null===(t=H.StaticPublicKeyCredential)||void 0===t?void 0:t.isUserVerifyingPlatformAuthenticatorAvailable())}catch(t){return!1}},this.isAutofillSupported=async()=>{var t,e;return!(!(null===(t=H.StaticPublicKeyCredential)||void 0===t?void 0:t.isConditionalMediationAvailable)||!await(null===(e=H.StaticPublicKeyCredential)||void 0===e?void 0:e.isConditionalMediationAvailable()))}}async init(t){const{clientId:e,options:i}=t;try{if(!e)throw new u("Invalid clientId",{clientId:e});if(i.webauthnApiPaths){const t=D.getDefaultPaths();if(function(t,e){const i=new Set(t),a=new Set(e);return[...t.filter((t=>!a.has(t))),...e.filter((t=>!i.has(t)))]}(Object.keys(i.webauthnApiPaths),Object.keys(t)).length)throw new u("Invalid custom paths",{customApiPaths:i.webauthnApiPaths})}D.init(e,i),this._initialized=!0}catch(t){throw C(t)?t:new u("Failed to initialize SDK")}}getDefaultPaths(){return this.initCheck(),D.getDefaultPaths()}getApiPaths(){return this.initCheck(),D.getApiPaths()}initCheck(){if(!this._initialized)throw new u}}H.StaticPublicKeyCredential=window.PublicKeyCredential;const N=new t("webauthn"),F=new H;N.events.on(N.events.MODULE_INITIALIZED,(()=>{var t;const e=N.moduleMetadata.getInitConfig();if(!(null===(t=null==e?void 0:e.webauthn)||void 0===t?void 0:t.serverPath))return;const{clientId:i,webauthn:a}=e;F.init({clientId:i,options:n({},a)})}));const x={modal:async t=>(F.initCheck(),F.authenticate.modal(t)),autofill:{activate:t=>{F.initCheck(),F.authenticate.autofill.activate(t)},abort:()=>{F.initCheck(),F.authenticate.autofill.abort()}}},q={modal:async t=>(F.initCheck(),F.approve.modal(t))};async function M(t){return F.initCheck(),F.register(t)}const{crossDevice:J}=F,{isPlatformAuthenticatorSupported:z}=F,{isAutofillSupported:$}=F,{getDefaultPaths:U}=F;window.localWebAuthnSDK=F;const W="2.0.1",V={initialize:e,...Object.freeze({__proto__:null,get WebauthnCrossDeviceStatus(){return T},approve:q,authenticate:x,crossDevice:J,getDefaultPaths:U,isAutofillSupported:$,isPlatformAuthenticatorSupported:z,register:M})};export{W as PACKAGE_VERSION,T as WebauthnCrossDeviceStatus,q as approve,x as authenticate,J as crossDevice,U as getDefaultPaths,$ as isAutofillSupported,z as isPlatformAuthenticatorSupported,M as register,V as webauthn};
1
+ "undefined"==typeof globalThis&&("undefined"!=typeof window?(window.globalThis=window,window.global=window):"undefined"!=typeof self&&(self.globalThis=self,self.global=self));import t from"./common.js";import{initialize as e}from"./common.js";export{initialize}from"./common.js";function i(t,e,i){return(e=function(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var i=t[Symbol.toPrimitive];if(void 0!==i){var a=i.call(t,e||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:e+""}(e))in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function a(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function n(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?a(Object(n),!0).forEach((function(e){i(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}class r{static arrayBufferToBase64(t){return btoa(String.fromCharCode(...new Uint8Array(t)))}static base64ToArrayBuffer(t){return Uint8Array.from(atob(t),(t=>t.charCodeAt(0)))}static stringToBase64(t){return btoa(t)}static jsonToBase64(t){const e=JSON.stringify(t);return btoa(e)}static base64ToJson(t){const e=atob(t);return JSON.parse(e)}}const o={log:console.log,error:console.error};var s,c;!function(t){t.NotInitialized="not_initialized",t.AuthenticationFailed="authentication_failed",t.AuthenticationAbortedTimeout="authentication_aborted_timeout",t.AuthenticationCanceled="webauthn_authentication_canceled",t.RegistrationFailed="registration_failed",t.AlreadyRegistered="username_already_registered",t.RegistrationAbortedTimeout="registration_aborted_timeout",t.RegistrationCanceled="webauthn_registration_canceled",t.AutofillAuthenticationAborted="autofill_authentication_aborted",t.AuthenticationProcessAlreadyActive="authentication_process_already_active",t.InvalidApprovalData="invalid_approval_data",t.FailedToInitCrossDeviceSession="cross_device_init_failed",t.FailedToGetCrossDeviceStatus="cross_device_status_failed",t.Unknown="unknown"}(s||(s={}));class l extends Error{constructor(t,e){super(t),this.errorCode=s.NotInitialized,this.data=e}}class u extends l{constructor(t,e){super(null!=t?t:"WebAuthnSdk is not initialized",e),this.errorCode=s.NotInitialized}}class d extends l{constructor(t,e){super(null!=t?t:"Authentication failed with an error",e),this.errorCode=s.AuthenticationFailed}}class h extends l{constructor(t,e){super(null!=t?t:"Authentication was canceled by the user or got timeout",e),this.errorCode=s.AuthenticationCanceled}}class p extends l{constructor(t,e){super(null!=t?t:"Registration failed with an error",e),this.errorCode=s.RegistrationFailed}}class v extends l{constructor(t,e){super(null!=t?t:"Registration was canceled by the user or got timeout",e),this.errorCode=s.RegistrationCanceled}}class g extends l{constructor(t){super(null!=t?t:"Autofill flow was aborted"),this.errorCode=s.AutofillAuthenticationAborted}}class m extends l{constructor(t){super(null!=t?t:"Operation was aborted by timeout"),this.errorCode=s.AutofillAuthenticationAborted}}class f extends l{constructor(t){super(null!=t?t:"Passkey with this username is already registered with the relying party."),this.errorCode=s.AlreadyRegistered}}class w extends l{constructor(t,e){super(null!=t?t:"Authentication process is already active",e),this.errorCode=s.AuthenticationProcessAlreadyActive}}class y extends l{constructor(t,e){super(null!=t?t:"Invalid approval data",e),this.errorCode=s.InvalidApprovalData}}class b extends l{constructor(t,e){super(null!=t?t:"Failed to init cross device authentication",e),this.errorCode=s.FailedToInitCrossDeviceSession}}class A extends l{constructor(t,e){super(null!=t?t:"Failed to get cross device status",e),this.errorCode=s.FailedToGetCrossDeviceStatus}}function C(t){return t.errorCode&&Object.values(s).includes(t.errorCode)}!function(t){t[t.persistent=0]="persistent",t[t.session=1]="session"}(c||(c={}));class _{static get(t){return _.getStorageMedium(_.allowedKeys[t]).getItem(_.getStorageKey(t))||void 0}static set(t,e){return _.getStorageMedium(_.allowedKeys[t]).setItem(_.getStorageKey(t),e)}static remove(t){_.getStorageMedium(_.allowedKeys[t]).removeItem(_.getStorageKey(t))}static clear(t){for(const[e,i]of Object.entries(_.allowedKeys)){const a=e;t&&this.configurationKeys.includes(a)||_.getStorageMedium(i).removeItem(_.getStorageKey(a))}}static getStorageKey(t){return`WebAuthnSdk:${t}`}static getStorageMedium(t){return t===c.session?sessionStorage:localStorage}}_.allowedKeys={clientId:c.session},_.configurationKeys=["clientId"];class D{static isNewApiDomain(t){return t&&(this.newApiDomains.includes(t)||t.startsWith("api.")&&t.endsWith(".transmitsecurity.io"))}static dnsPrefetch(t){const e=document.createElement("link");e.rel="dns-prefetch",e.href=t,document.head.appendChild(e)}static preconnect(t,e){const i=document.createElement("link");i.rel="preconnect",i.href=t,e&&(i.crossOrigin="anonymous"),document.head.appendChild(i)}static warmupConnection(t){this.dnsPrefetch(t),this.preconnect(t,!1),this.preconnect(t,!0)}static init(t,e){var i,a;try{this._serverPath=new URL(e.serverPath),this.isNewApiDomain(null===(i=this._serverPath)||void 0===i?void 0:i.hostname)&&this.warmupConnection(this._serverPath.origin),this._apiPaths=null!==(a=e.webauthnApiPaths)&&void 0!==a?a:this.getDefaultPaths(),this._clientId=t,_.set("clientId",t)}catch(t){throw new u("Invalid options.serverPath",{error:t})}}static getDefaultPaths(){var t;const e=this.isNewApiDomain(null===(t=this._serverPath)||void 0===t?void 0:t.hostname)?"/cis":"";return{startAuthentication:`${e}/v1/auth/webauthn/authenticate/start`,startRegistration:`${e}/v1/auth/webauthn/register/start`,initCrossDeviceAuthentication:`${e}/v1/auth/webauthn/cross-device/authenticate/init`,startCrossDeviceAuthentication:`${e}/v1/auth/webauthn/cross-device/authenticate/start`,startCrossDeviceRegistration:`${e}/v1/auth/webauthn/cross-device/register/start`,getCrossDeviceTicketStatus:`${e}/v1/auth/webauthn/cross-device/status`,attachDeviceToCrossDeviceSession:`${e}/v1/auth/webauthn/cross-device/attach-device`}}static getApiPaths(){return this._apiPaths}static async sendRequest(t,e,i){o.log(`[WebAuthn SDK] Calling ${e.method} ${t}...`);const a=new URL(this._serverPath);return a.pathname=t,i&&(a.search=i),fetch(a.toString(),e)}static async startRegistration(t){const e=await this.sendRequest(this._apiPaths.startRegistration,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n(n({client_id:this.getValidatedClientId(),username:t.username,display_name:t.displayName},t.timeout&&{timeout:t.timeout}),t.limitSingleCredentialToDevice&&{limit_single_credential_to_device:t.limitSingleCredentialToDevice}))});if(!(null==e?void 0:e.ok))throw new d("Failed to start registration",null==e?void 0:e.body);return await e.json()}static async startAuthentication(t){const e=await this.sendRequest(this._apiPaths.startAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n(n(n(n(n({client_id:this.getValidatedClientId()},t.username&&{username:t.username}),t.identifier&&{identifier:t.identifier}),t.identifierType&&{identifier_type:t.identifierType}),t.approvalData&&{approval_data:t.approvalData}),t.timeout&&{timeout:t.timeout}))});if(!(null==e?void 0:e.ok))throw new d("Failed to start authentication",null==e?void 0:e.body);return await e.json()}static async initCrossDeviceAuthentication(t){const e=await this.sendRequest(this._apiPaths.initCrossDeviceAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n(n({client_id:this.getValidatedClientId()},t.username&&{username:t.username}),t.approvalData&&{approval_data:t.approvalData}))});if(!(null==e?void 0:e.ok))throw new b(void 0,null==e?void 0:e.body);return await e.json()}static async getCrossDeviceTicketStatus(t){const e=await this.sendRequest(this._apiPaths.getCrossDeviceTicketStatus,{method:"GET"},`cross_device_ticket_id=${t.ticketId}`);if(!(null==e?void 0:e.ok))throw new A(void 0,null==e?void 0:e.body);return await e.json()}static async startCrossDeviceAuthentication(t){const e=await this.sendRequest(this._apiPaths.startCrossDeviceAuthentication,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new d("Failed to start cross device authentication",null==e?void 0:e.body);return await e.json()}static async startCrossDeviceRegistration(t){const e=await this.sendRequest(this._apiPaths.startCrossDeviceRegistration,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new p("Failed to start cross device registration",null==e?void 0:e.body);return await e.json()}static async attachDeviceToCrossDeviceSession(t){const e=await this.sendRequest(this._apiPaths.attachDeviceToCrossDeviceSession,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cross_device_ticket_id:t.ticketId})});if(!(null==e?void 0:e.ok))throw new p("Failed to attach device to cross device session",null==e?void 0:e.body);return await e.json()}static getValidatedClientId(){var t;const e=null!==(t=this._clientId)&&void 0!==t?t:_.get("clientId");if(!e)throw new u("Missing clientId");return e}}var S,T,k,I;D.newApiDomains=["api.idsec-dev.com","api.idsec-stg.com"],function(t){t.InputAutofill="input-autofill",t.Modal="modal"}(S||(S={})),function(t){t.Pending="pending",t.Scanned="scanned",t.Success="success",t.Error="error",t.Timeout="timeout",t.Aborted="aborted"}(T||(T={})),function(t){t.toAuthenticationError=t=>C(t)?t:"NotAllowedError"===t.name?new h:"OperationError"===t.name?new w(t.message):"SecurityError"===t.name?new d(t.message):t===s.AuthenticationAbortedTimeout?new m:"AbortError"===t.name||t===s.AutofillAuthenticationAborted?new g:new d("Something went wrong during authentication",{error:t}),t.toRegistrationError=t=>C(t)?t:"NotAllowedError"===t.name?new v:"SecurityError"===t.name?new p(t.message):"InvalidStateError"===t.name?new f:t===s.RegistrationAbortedTimeout?new m:new p("Something went wrong during registration",{error:t})}(k||(k={})),function(t){t.processCredentialRequestOptions=t=>n(n({},t),{},{challenge:r.base64ToArrayBuffer(t.challenge),allowCredentials:t.allowCredentials.map((t=>n(n({},t),{},{id:r.base64ToArrayBuffer(t.id)})))}),t.processCredentialCreationOptions=(t,e)=>{var i;const a=JSON.parse(JSON.stringify(t));return a.challenge=r.base64ToArrayBuffer(t.challenge),a.user.id=r.base64ToArrayBuffer(t.user.id),(null==e?void 0:e.limitSingleCredentialToDevice)&&(a.excludeCredentials=null===(i=t.excludeCredentials)||void 0===i?void 0:i.map((t=>n(n({},t),{},{id:r.base64ToArrayBuffer(t.id)})))),(null==e?void 0:e.registerAsDiscoverable)?(a.authenticatorSelection.residentKey="preferred",a.authenticatorSelection.requireResidentKey=!0):(a.authenticatorSelection.residentKey="discouraged",a.authenticatorSelection.requireResidentKey=!1),a.authenticatorSelection.authenticatorAttachment=(null==e?void 0:e.allowCrossPlatformAuthenticators)?void 0:"platform",a},t.encodeAuthenticationResult=t=>{const{authenticatorAttachment:e}=t,i=t.response;return{id:t.id,rawId:r.arrayBufferToBase64(t.rawId),response:{authenticatorData:r.arrayBufferToBase64(i.authenticatorData),clientDataJSON:r.arrayBufferToBase64(i.clientDataJSON),signature:r.arrayBufferToBase64(i.signature),userHandle:r.arrayBufferToBase64(i.userHandle)},authenticatorAttachment:e,type:t.type}},t.encodeRegistrationResult=t=>{const{authenticatorAttachment:e}=t,i=t.response;return{id:t.id,rawId:r.arrayBufferToBase64(t.rawId),response:{attestationObject:r.arrayBufferToBase64(i.attestationObject),clientDataJSON:r.arrayBufferToBase64(i.clientDataJSON)},authenticatorAttachment:e,type:t.type}}}(I||(I={}));class P{async modal(t){try{const e=await this.performAuthentication(n(n({},t),{},{mediationType:S.Modal}));return r.jsonToBase64(e)}catch(t){throw k.toAuthenticationError(t)}}activateAutofill(t){const{handlers:e,username:i}=t,{onSuccess:a,onError:n,onReady:o}=e;this.performAuthentication({username:i,mediationType:S.InputAutofill,onReady:o}).then((t=>{a(r.jsonToBase64(t))})).catch((t=>{const e=k.toAuthenticationError(t);if(!n)throw e;n(e)}))}abortAutofill(){this.abortController&&this.abortController.abort(s.AutofillAuthenticationAborted)}abortAuthentication(){this.abortController&&this.abortController.abort(s.AuthenticationAbortedTimeout)}async performAuthentication(t){var e,i;const a="crossDeviceTicketId"in t?await D.startCrossDeviceAuthentication({ticketId:t.crossDeviceTicketId}):await D.startAuthentication({username:t.username,identifier:t.identifier,identifierType:t.identifierType,timeout:null===(e=t.options)||void 0===e?void 0:e.timeout}),n=a.credential_request_options,r=I.processCredentialRequestOptions(n),o=this.getMediatedCredentialRequest(r,t.mediationType);t.mediationType===S.InputAutofill&&(null===(i=t.onReady)||void 0===i||i.call(t));const s=await navigator.credentials.get(o).catch((t=>{throw k.toAuthenticationError(t)}));return{webauthnSessionId:a.webauthn_session_id,publicKeyCredential:I.encodeAuthenticationResult(s),userAgent:navigator.userAgent}}getMediatedCredentialRequest(t,e){const i={publicKey:t};return this.abortController=new AbortController,i.signal=this.abortController&&this.abortController.signal,e===S.InputAutofill?i.mediation="conditional":t.timeout&&setTimeout((()=>{this.abortAuthentication()}),t.timeout),i}}class O{constructor(t,e){this.handler=t,this.intervalInMs=e}begin(){var t;this.intervalId=window.setInterval((t=this.handler,async function(){t.isRunning||(t.isRunning=!0,await t(...arguments),t.isRunning=!1)}),this.intervalInMs)}stop(){clearInterval(this.intervalId)}}const R=/^[A-Za-z0-9\-_.: ]*$/;function j(t){if(t&&(!function(t){return Object.keys(t).length<=10}(t)||!function(t){const e=t=>"string"==typeof t,i=t=>R.test(t);return Object.keys(t).every((a=>e(a)&&e(t[a])&&i(a)&&i(t[a])))}(t)))throw o.error("Failed validating approval data"),new y("Provided approval data should have 10 properties max. Also, it should contain only \n alphanumeric characters, numbers, and the special characters: '-', '_', '.'")}class B{constructor(t,e,i){this.authenticationHandler=t,this.registrationHandler=e,this.approvalHandler=i,this.init={registration:async t=>(this.ticketStatus=T.Pending,this.pollCrossDeviceSession(t.crossDeviceTicketId,t.handlers)),authentication:async t=>{const{username:e}=t,i=(await D.initCrossDeviceAuthentication(n({},e&&{username:e}))).cross_device_ticket_id;return this.ticketStatus=T.Pending,this.pollCrossDeviceSession(i,t.handlers)},approval:async t=>{const{username:e,approvalData:i}=t;j(i);const a=(await D.initCrossDeviceAuthentication({username:e,approvalData:i})).cross_device_ticket_id;return this.ticketStatus=T.Pending,this.pollCrossDeviceSession(a,t.handlers)}},this.authenticate={modal:async t=>this.authenticationHandler.modal({crossDeviceTicketId:t})},this.approve={modal:async t=>this.approvalHandler.modal({crossDeviceTicketId:t})}}async register(t){return this.registrationHandler.register(t)}async attachDevice(t){const e=await D.attachDeviceToCrossDeviceSession({ticketId:t});return n({status:e.status,startedAt:e.started_at},e.approval_data&&{approvalData:e.approval_data})}async pollCrossDeviceSession(t,e){return this.poller=new O((async()=>{var i,a;const n=await D.getCrossDeviceTicketStatus({ticketId:t}),r=n.status;if(r!==this.ticketStatus)switch(this.ticketStatus=r,r){case T.Scanned:await e.onDeviceAttach();break;case T.Error:case T.Timeout:case T.Aborted:await e.onFailure(n),null===(i=this.poller)||void 0===i||i.stop();break;case T.Success:if("onCredentialRegister"in e)await e.onCredentialRegister();else{if(!n.session_id)throw new A("Cross device session is complete without returning session_id",n);await e.onCredentialAuthenticate(n.session_id)}null===(a=this.poller)||void 0===a||a.stop()}}),1e3),this.poller.begin(),setTimeout((()=>{var t;null===(t=this.poller)||void 0===t||t.stop(),e.onFailure({status:T.Timeout})}),3e5),{crossDeviceTicketId:t,stop:()=>{var t;null===(t=this.poller)||void 0===t||t.stop()}}}}class K{async register(t){var e,i,a;this.abortController=new AbortController;const o=n({allowCrossPlatformAuthenticators:!("crossDeviceTicketId"in t),registerAsDiscoverable:!0},t.options);try{const n="crossDeviceTicketId"in t?await D.startCrossDeviceRegistration({ticketId:t.crossDeviceTicketId}):await D.startRegistration({username:t.username,displayName:(null===(e=t.options)||void 0===e?void 0:e.displayName)||t.username,timeout:null===(i=t.options)||void 0===i?void 0:i.timeout,limitSingleCredentialToDevice:null===(a=t.options)||void 0===a?void 0:a.limitSingleCredentialToDevice}),s=I.processCredentialCreationOptions(n.credential_creation_options,o);setTimeout((()=>{this.abortRegistration()}),s.timeout);const c=await this.registerCredential(s),l={webauthnSessionId:n.webauthn_session_id,publicKeyCredential:c,userAgent:navigator.userAgent};return r.jsonToBase64(l)}catch(t){throw k.toRegistrationError(t)}}abortRegistration(){this.abortController&&this.abortController.abort(s.RegistrationAbortedTimeout)}async registerCredential(t){const e=await navigator.credentials.create({publicKey:t,signal:this.abortController&&this.abortController.signal}).catch((t=>{throw k.toRegistrationError(t)}));return I.encodeRegistrationResult(e)}}class E{async modal(t){try{const e=await this.performApproval(t);return r.jsonToBase64(e)}catch(t){throw k.toAuthenticationError(t)}}async performApproval(t){"approvalData"in t&&j(t.approvalData);const e="crossDeviceTicketId"in t?await D.startCrossDeviceAuthentication({ticketId:t.crossDeviceTicketId}):await D.startAuthentication({username:t.username,approvalData:t.approvalData}),i=e.credential_request_options,a=I.processCredentialRequestOptions(i),n=await navigator.credentials.get({publicKey:a}).catch((t=>{throw k.toAuthenticationError(t)}));return{webauthnSessionId:e.webauthn_session_id,publicKeyCredential:I.encodeAuthenticationResult(n),userAgent:navigator.userAgent}}}class H{constructor(){this._initialized=!1,this._authenticationHandler=new P,this._registrationHandler=new K,this._approvalHandler=new E,this._crossDeviceHandler=new B(this._authenticationHandler,this._registrationHandler,this._approvalHandler),this.authenticate={modal:async t=>(this.initCheck(),this._authenticationHandler.modal(t)),autofill:{activate:t=>(this.initCheck(),this._authenticationHandler.activateAutofill(t)),abort:()=>this._authenticationHandler.abortAutofill()}},this.approve={modal:async t=>(this.initCheck(),this._approvalHandler.modal(t))},this.register=async t=>(this.initCheck(),this._registrationHandler.register(t)),this.crossDevice={init:{registration:async t=>(this.initCheck(),this._crossDeviceHandler.init.registration(t)),authentication:async t=>(this.initCheck(),this._crossDeviceHandler.init.authentication(t)),approval:async t=>(this.initCheck(),this._crossDeviceHandler.init.approval(t))},authenticate:{modal:async t=>(this.initCheck(),this._crossDeviceHandler.authenticate.modal(t))},approve:{modal:async t=>(this.initCheck(),this._crossDeviceHandler.approve.modal(t))},register:async t=>(this.initCheck(),this._crossDeviceHandler.register(t)),attachDevice:async t=>(this.initCheck(),this._crossDeviceHandler.attachDevice(t))},this.isPlatformAuthenticatorSupported=async()=>{var t;try{return await(null===(t=H.StaticPublicKeyCredential)||void 0===t?void 0:t.isUserVerifyingPlatformAuthenticatorAvailable())}catch(t){return!1}},this.isAutofillSupported=async()=>{var t,e;return!(!(null===(t=H.StaticPublicKeyCredential)||void 0===t?void 0:t.isConditionalMediationAvailable)||!await(null===(e=H.StaticPublicKeyCredential)||void 0===e?void 0:e.isConditionalMediationAvailable()))}}async init(t){const{clientId:e,options:i}=t;try{if(!e)throw new u("Invalid clientId",{clientId:e});if(i.webauthnApiPaths){const t=D.getDefaultPaths();if(function(t,e){const i=new Set(t),a=new Set(e);return[...t.filter((t=>!a.has(t))),...e.filter((t=>!i.has(t)))]}(Object.keys(i.webauthnApiPaths),Object.keys(t)).length)throw new u("Invalid custom paths",{customApiPaths:i.webauthnApiPaths})}D.init(e,i),this._initialized=!0}catch(t){throw C(t)?t:new u("Failed to initialize SDK")}}getDefaultPaths(){return this.initCheck(),D.getDefaultPaths()}getApiPaths(){return this.initCheck(),D.getApiPaths()}initCheck(){if(!this._initialized)throw new u}}H.StaticPublicKeyCredential=window.PublicKeyCredential;const N=new t("webauthn"),F=new H;N.events.on(N.events.MODULE_INITIALIZED,(()=>{var t;const e=N.moduleMetadata.getInitConfig();if(!(null===(t=null==e?void 0:e.webauthn)||void 0===t?void 0:t.serverPath))return;const{clientId:i,webauthn:a}=e;F.init({clientId:i,options:n({},a)})}));const x={modal:async t=>(F.initCheck(),F.authenticate.modal(t)),autofill:{activate:t=>{F.initCheck(),F.authenticate.autofill.activate(t)},abort:()=>{F.initCheck(),F.authenticate.autofill.abort()}}},q={modal:async t=>(F.initCheck(),F.approve.modal(t))};async function M(t){return F.initCheck(),F.register(t)}const{crossDevice:J}=F,{isPlatformAuthenticatorSupported:z}=F,{isAutofillSupported:$}=F,{getDefaultPaths:U}=F;window.localWebAuthnSDK=F;const W="2.1.1",V={initialize:e,...Object.freeze({__proto__:null,get WebauthnCrossDeviceStatus(){return T},approve:q,authenticate:x,crossDevice:J,getDefaultPaths:U,isAutofillSupported:$,isPlatformAuthenticatorSupported:z,register:M})};export{W as PACKAGE_VERSION,T as WebauthnCrossDeviceStatus,q as approve,x as authenticate,J as crossDevice,U as getDefaultPaths,$ as isAutofillSupported,z as isPlatformAuthenticatorSupported,M as register,V as webauthn};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transmitsecurity/platform-web-sdk",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "license": "MIT",
5
5
  "private": false,
6
6
  "type": "module",