@authsignal/browser 0.3.6 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,17 @@
1
- import { KyInstance } from "ky/distribution/types/ky";
2
- import { AddAuthenticatorRequest, AddAuthenticatorResponse, AuthenticationOptsRequest, AuthenticationOptsResponse, RegistrationOptsRequest, RegistrationOptsResponse, VerifyRequest, VerifyResponse } from "./types";
1
+ import { AddAuthenticatorRequest, AddAuthenticatorResponse, AuthenticationOptsRequest, AuthenticationOptsResponse, PasskeyAuthenticatorResponse, RegistrationOptsRequest, RegistrationOptsResponse, VerifyRequest, VerifyResponse } from "./types";
3
2
  declare type PasskeyApiClientOptions = {
4
3
  baseUrl: string;
5
4
  tenantId: string;
6
5
  };
7
6
  export declare class PasskeyApiClient {
8
7
  tenantId: string;
9
- api: KyInstance;
8
+ baseUrl: string;
10
9
  constructor({ baseUrl, tenantId }: PasskeyApiClientOptions);
11
- registrationOptions({ token, userName }: RegistrationOptsRequest): Promise<RegistrationOptsResponse>;
10
+ registrationOptions({ token, userName, authenticatorAttachment, }: RegistrationOptsRequest): Promise<RegistrationOptsResponse>;
12
11
  authenticationOptions({ token }: AuthenticationOptsRequest): Promise<AuthenticationOptsResponse>;
13
12
  addAuthenticator({ token, ...rest }: AddAuthenticatorRequest): Promise<AddAuthenticatorResponse>;
14
13
  verify({ token, ...rest }: VerifyRequest): Promise<VerifyResponse>;
14
+ getPasskeyAuthenticator(credentialId: string): Promise<PasskeyAuthenticatorResponse>;
15
15
  private buildHeaders;
16
16
  }
17
17
  export {};
@@ -1,7 +1,8 @@
1
- import { AuthenticationResponseJSON, PublicKeyCredentialCreationOptionsJSON, RegistrationResponseJSON } from "@simplewebauthn/typescript-types";
1
+ import { AuthenticationResponseJSON, AuthenticatorAttachment, PublicKeyCredentialCreationOptionsJSON, RegistrationResponseJSON } from "@simplewebauthn/types";
2
2
  export declare type RegistrationOptsRequest = {
3
3
  userName?: string;
4
4
  token: string;
5
+ authenticatorAttachment?: AuthenticatorAttachment | null;
5
6
  };
6
7
  export declare type RegistrationOptsResponse = {
7
8
  challengeId: string;
@@ -33,3 +34,7 @@ export declare type VerifyResponse = {
33
34
  isVerified: boolean;
34
35
  accessToken?: string;
35
36
  };
37
+ export declare type PasskeyAuthenticatorResponse = {
38
+ credentialId: string;
39
+ verifiedAt: string;
40
+ };
@@ -17,7 +17,7 @@ export declare class Authsignal {
17
17
  launch(url: string, options?: {
18
18
  mode: "window";
19
19
  } & LaunchOptions): Promise<TokenPayload>;
20
- initAdvancedProfiling(baseUrl?: string): undefined;
20
+ initAdvancedProfiling(baseUrl?: string): void;
21
21
  private launchWithRedirect;
22
22
  private launchWithPopup;
23
23
  private launchWithWindow;
package/dist/index.js CHANGED
@@ -155,7 +155,7 @@ function __generator(thisArg, body) {
155
155
  }
156
156
  }
157
157
 
158
- /* [@simplewebauthn/browser@8.2.1] */
158
+ /* [@simplewebauthn/browser@9.0.1] */
159
159
  function utf8StringToBuffer(value) {
160
160
  return new TextEncoder().encode(value);
161
161
  }
@@ -305,7 +305,7 @@ function identifyRegistrationError({ error, options, }) {
305
305
  return error;
306
306
  }
307
307
 
308
- class WebAuthnAbortService {
308
+ class BaseWebAuthnAbortService {
309
309
  createNewAbortSignal() {
310
310
  if (this.controller) {
311
311
  const abortError = new Error('Cancelling existing WebAuthn API call for new one');
@@ -316,8 +316,16 @@ class WebAuthnAbortService {
316
316
  this.controller = newController;
317
317
  return newController.signal;
318
318
  }
319
+ cancelCeremony() {
320
+ if (this.controller) {
321
+ const abortError = new Error('Manually cancelling existing WebAuthn API call');
322
+ abortError.name = 'AbortError';
323
+ this.controller.abort(abortError);
324
+ this.controller = undefined;
325
+ }
326
+ }
319
327
  }
320
- const webauthnAbortService = new WebAuthnAbortService();
328
+ const WebAuthnAbortService = new BaseWebAuthnAbortService();
321
329
 
322
330
  const attachments = ['cross-platform', 'platform'];
323
331
  function toAuthenticatorAttachment(attachment) {
@@ -344,7 +352,7 @@ async function startRegistration(creationOptionsJSON) {
344
352
  excludeCredentials: creationOptionsJSON.excludeCredentials?.map(toPublicKeyCredentialDescriptor),
345
353
  };
346
354
  const options = { publicKey };
347
- options.signal = webauthnAbortService.createNewAbortSignal();
355
+ options.signal = WebAuthnAbortService.createNewAbortSignal();
348
356
  let credential;
349
357
  try {
350
358
  credential = (await navigator.credentials.create(options));
@@ -489,15 +497,15 @@ async function startAuthentication(requestOptionsJSON, useBrowserAutofill = fals
489
497
  if (!(await browserSupportsWebAuthnAutofill())) {
490
498
  throw Error('Browser does not support WebAuthn autofill');
491
499
  }
492
- const eligibleInputs = document.querySelectorAll('input[autocomplete*=\'webauthn\']');
500
+ const eligibleInputs = document.querySelectorAll('input[autocomplete$=\'webauthn\']');
493
501
  if (eligibleInputs.length < 1) {
494
- throw Error('No <input> with `"webauthn"` in its `autocomplete` attribute was detected');
502
+ throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');
495
503
  }
496
504
  options.mediation = 'conditional';
497
505
  publicKey.allowCredentials = [];
498
506
  }
499
507
  options.publicKey = publicKey;
500
- options.signal = webauthnAbortService.createNewAbortSignal();
508
+ options.signal = WebAuthnAbortService.createNewAbortSignal();
501
509
  let credential;
502
510
  try {
503
511
  credential = (await navigator.credentials.get(options));
@@ -528,556 +536,29 @@ async function startAuthentication(requestOptionsJSON, useBrowserAutofill = fals
528
536
  };
529
537
  }
530
538
 
531
- // eslint-lint-disable-next-line @typescript-eslint/naming-convention
532
- class HTTPError extends Error {
533
- constructor(response, request, options) {
534
- const code = (response.status || response.status === 0) ? response.status : '';
535
- const title = response.statusText || '';
536
- const status = `${code} ${title}`.trim();
537
- const reason = status ? `status code ${status}` : 'an unknown error';
538
- super(`Request failed with ${reason}`);
539
- Object.defineProperty(this, "response", {
540
- enumerable: true,
541
- configurable: true,
542
- writable: true,
543
- value: void 0
544
- });
545
- Object.defineProperty(this, "request", {
546
- enumerable: true,
547
- configurable: true,
548
- writable: true,
549
- value: void 0
550
- });
551
- Object.defineProperty(this, "options", {
552
- enumerable: true,
553
- configurable: true,
554
- writable: true,
555
- value: void 0
556
- });
557
- this.name = 'HTTPError';
558
- this.response = response;
559
- this.request = request;
560
- this.options = options;
561
- }
562
- }
563
-
564
- class TimeoutError extends Error {
565
- constructor(request) {
566
- super('Request timed out');
567
- Object.defineProperty(this, "request", {
568
- enumerable: true,
569
- configurable: true,
570
- writable: true,
571
- value: void 0
572
- });
573
- this.name = 'TimeoutError';
574
- this.request = request;
575
- }
576
- }
577
-
578
- // eslint-disable-next-line @typescript-eslint/ban-types
579
- const isObject = (value) => value !== null && typeof value === 'object';
580
-
581
- const validateAndMerge = (...sources) => {
582
- for (const source of sources) {
583
- if ((!isObject(source) || Array.isArray(source)) && typeof source !== 'undefined') {
584
- throw new TypeError('The `options` argument must be an object');
585
- }
586
- }
587
- return deepMerge({}, ...sources);
588
- };
589
- const mergeHeaders = (source1 = {}, source2 = {}) => {
590
- const result = new globalThis.Headers(source1);
591
- const isHeadersInstance = source2 instanceof globalThis.Headers;
592
- const source = new globalThis.Headers(source2);
593
- for (const [key, value] of source.entries()) {
594
- if ((isHeadersInstance && value === 'undefined') || value === undefined) {
595
- result.delete(key);
596
- }
597
- else {
598
- result.set(key, value);
599
- }
600
- }
601
- return result;
602
- };
603
- // TODO: Make this strongly-typed (no `any`).
604
- const deepMerge = (...sources) => {
605
- let returnValue = {};
606
- let headers = {};
607
- for (const source of sources) {
608
- if (Array.isArray(source)) {
609
- if (!Array.isArray(returnValue)) {
610
- returnValue = [];
611
- }
612
- returnValue = [...returnValue, ...source];
613
- }
614
- else if (isObject(source)) {
615
- for (let [key, value] of Object.entries(source)) {
616
- if (isObject(value) && key in returnValue) {
617
- value = deepMerge(returnValue[key], value);
618
- }
619
- returnValue = { ...returnValue, [key]: value };
620
- }
621
- if (isObject(source.headers)) {
622
- headers = mergeHeaders(headers, source.headers);
623
- returnValue.headers = headers;
624
- }
625
- }
626
- }
627
- return returnValue;
628
- };
629
-
630
- const supportsRequestStreams = (() => {
631
- let duplexAccessed = false;
632
- let hasContentType = false;
633
- const supportsReadableStream = typeof globalThis.ReadableStream === 'function';
634
- const supportsRequest = typeof globalThis.Request === 'function';
635
- if (supportsReadableStream && supportsRequest) {
636
- hasContentType = new globalThis.Request('https://a.com', {
637
- body: new globalThis.ReadableStream(),
638
- method: 'POST',
639
- // @ts-expect-error - Types are outdated.
640
- get duplex() {
641
- duplexAccessed = true;
642
- return 'half';
643
- },
644
- }).headers.has('Content-Type');
645
- }
646
- return duplexAccessed && !hasContentType;
647
- })();
648
- const supportsAbortController = typeof globalThis.AbortController === 'function';
649
- const supportsResponseStreams = typeof globalThis.ReadableStream === 'function';
650
- const supportsFormData = typeof globalThis.FormData === 'function';
651
- const requestMethods = ['get', 'post', 'put', 'patch', 'head', 'delete'];
652
- const responseTypes = {
653
- json: 'application/json',
654
- text: 'text/*',
655
- formData: 'multipart/form-data',
656
- arrayBuffer: '*/*',
657
- blob: '*/*',
658
- };
659
- // The maximum value of a 32bit int (see issue #117)
660
- const maxSafeTimeout = 2147483647;
661
- const stop = Symbol('stop');
662
-
663
- const normalizeRequestMethod = (input) => requestMethods.includes(input) ? input.toUpperCase() : input;
664
- const retryMethods = ['get', 'put', 'head', 'delete', 'options', 'trace'];
665
- const retryStatusCodes = [408, 413, 429, 500, 502, 503, 504];
666
- const retryAfterStatusCodes = [413, 429, 503];
667
- const defaultRetryOptions = {
668
- limit: 2,
669
- methods: retryMethods,
670
- statusCodes: retryStatusCodes,
671
- afterStatusCodes: retryAfterStatusCodes,
672
- maxRetryAfter: Number.POSITIVE_INFINITY,
673
- backoffLimit: Number.POSITIVE_INFINITY,
674
- };
675
- const normalizeRetryOptions = (retry = {}) => {
676
- if (typeof retry === 'number') {
677
- return {
678
- ...defaultRetryOptions,
679
- limit: retry,
680
- };
681
- }
682
- if (retry.methods && !Array.isArray(retry.methods)) {
683
- throw new Error('retry.methods must be an array');
684
- }
685
- if (retry.statusCodes && !Array.isArray(retry.statusCodes)) {
686
- throw new Error('retry.statusCodes must be an array');
687
- }
688
- return {
689
- ...defaultRetryOptions,
690
- ...retry,
691
- afterStatusCodes: retryAfterStatusCodes,
692
- };
693
- };
694
-
695
- // `Promise.race()` workaround (#91)
696
- async function timeout(request, abortController, options) {
697
- return new Promise((resolve, reject) => {
698
- const timeoutId = setTimeout(() => {
699
- if (abortController) {
700
- abortController.abort();
701
- }
702
- reject(new TimeoutError(request));
703
- }, options.timeout);
704
- void options
705
- .fetch(request)
706
- .then(resolve)
707
- .catch(reject)
708
- .then(() => {
709
- clearTimeout(timeoutId);
710
- });
711
- });
712
- }
713
-
714
- // DOMException is supported on most modern browsers and Node.js 18+.
715
- // @see https://developer.mozilla.org/en-US/docs/Web/API/DOMException#browser_compatibility
716
- const isDomExceptionSupported = Boolean(globalThis.DOMException);
717
- // TODO: When targeting Node.js 18, use `signal.throwIfAborted()` (https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/throwIfAborted)
718
- function composeAbortError(signal) {
719
- /*
720
- NOTE: Use DomException with AbortError name as specified in MDN docs (https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort)
721
- > When abort() is called, the fetch() promise rejects with an Error of type DOMException, with name AbortError.
722
- */
723
- if (isDomExceptionSupported) {
724
- return new DOMException(signal?.reason ?? 'The operation was aborted.', 'AbortError');
725
- }
726
- // DOMException not supported. Fall back to use of error and override name.
727
- const error = new Error(signal?.reason ?? 'The operation was aborted.');
728
- error.name = 'AbortError';
729
- return error;
730
- }
731
-
732
- // https://github.com/sindresorhus/delay/tree/ab98ae8dfcb38e1593286c94d934e70d14a4e111
733
- async function delay(ms, { signal }) {
734
- return new Promise((resolve, reject) => {
735
- if (signal) {
736
- if (signal.aborted) {
737
- reject(composeAbortError(signal));
738
- return;
739
- }
740
- signal.addEventListener('abort', handleAbort, { once: true });
741
- }
742
- function handleAbort() {
743
- reject(composeAbortError(signal));
744
- clearTimeout(timeoutId);
745
- }
746
- const timeoutId = setTimeout(() => {
747
- signal?.removeEventListener('abort', handleAbort);
748
- resolve();
749
- }, ms);
750
- });
751
- }
752
-
753
- class Ky {
754
- // eslint-disable-next-line @typescript-eslint/promise-function-async
755
- static create(input, options) {
756
- const ky = new Ky(input, options);
757
- const fn = async () => {
758
- if (ky._options.timeout > maxSafeTimeout) {
759
- throw new RangeError(`The \`timeout\` option cannot be greater than ${maxSafeTimeout}`);
760
- }
761
- // Delay the fetch so that body method shortcuts can set the Accept header
762
- await Promise.resolve();
763
- let response = await ky._fetch();
764
- for (const hook of ky._options.hooks.afterResponse) {
765
- // eslint-disable-next-line no-await-in-loop
766
- const modifiedResponse = await hook(ky.request, ky._options, ky._decorateResponse(response.clone()));
767
- if (modifiedResponse instanceof globalThis.Response) {
768
- response = modifiedResponse;
769
- }
770
- }
771
- ky._decorateResponse(response);
772
- if (!response.ok && ky._options.throwHttpErrors) {
773
- let error = new HTTPError(response, ky.request, ky._options);
774
- for (const hook of ky._options.hooks.beforeError) {
775
- // eslint-disable-next-line no-await-in-loop
776
- error = await hook(error);
777
- }
778
- throw error;
779
- }
780
- // If `onDownloadProgress` is passed, it uses the stream API internally
781
- /* istanbul ignore next */
782
- if (ky._options.onDownloadProgress) {
783
- if (typeof ky._options.onDownloadProgress !== 'function') {
784
- throw new TypeError('The `onDownloadProgress` option must be a function');
785
- }
786
- if (!supportsResponseStreams) {
787
- throw new Error('Streams are not supported in your environment. `ReadableStream` is missing.');
788
- }
789
- return ky._stream(response.clone(), ky._options.onDownloadProgress);
790
- }
791
- return response;
792
- };
793
- const isRetriableMethod = ky._options.retry.methods.includes(ky.request.method.toLowerCase());
794
- const result = (isRetriableMethod ? ky._retry(fn) : fn());
795
- for (const [type, mimeType] of Object.entries(responseTypes)) {
796
- result[type] = async () => {
797
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
798
- ky.request.headers.set('accept', ky.request.headers.get('accept') || mimeType);
799
- const awaitedResult = await result;
800
- const response = awaitedResult.clone();
801
- if (type === 'json') {
802
- if (response.status === 204) {
803
- return '';
804
- }
805
- const arrayBuffer = await response.clone().arrayBuffer();
806
- const responseSize = arrayBuffer.byteLength;
807
- if (responseSize === 0) {
808
- return '';
809
- }
810
- if (options.parseJson) {
811
- return options.parseJson(await response.text());
812
- }
813
- }
814
- return response[type]();
815
- };
816
- }
817
- return result;
818
- }
819
- // eslint-disable-next-line complexity
820
- constructor(input, options = {}) {
821
- Object.defineProperty(this, "request", {
822
- enumerable: true,
823
- configurable: true,
824
- writable: true,
825
- value: void 0
826
- });
827
- Object.defineProperty(this, "abortController", {
828
- enumerable: true,
829
- configurable: true,
830
- writable: true,
831
- value: void 0
832
- });
833
- Object.defineProperty(this, "_retryCount", {
834
- enumerable: true,
835
- configurable: true,
836
- writable: true,
837
- value: 0
838
- });
839
- Object.defineProperty(this, "_input", {
840
- enumerable: true,
841
- configurable: true,
842
- writable: true,
843
- value: void 0
844
- });
845
- Object.defineProperty(this, "_options", {
846
- enumerable: true,
847
- configurable: true,
848
- writable: true,
849
- value: void 0
850
- });
851
- this._input = input;
852
- this._options = {
853
- // TODO: credentials can be removed when the spec change is implemented in all browsers. Context: https://www.chromestatus.com/feature/4539473312350208
854
- credentials: this._input.credentials || 'same-origin',
855
- ...options,
856
- headers: mergeHeaders(this._input.headers, options.headers),
857
- hooks: deepMerge({
858
- beforeRequest: [],
859
- beforeRetry: [],
860
- beforeError: [],
861
- afterResponse: [],
862
- }, options.hooks),
863
- method: normalizeRequestMethod(options.method ?? this._input.method),
864
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
865
- prefixUrl: String(options.prefixUrl || ''),
866
- retry: normalizeRetryOptions(options.retry),
867
- throwHttpErrors: options.throwHttpErrors !== false,
868
- timeout: typeof options.timeout === 'undefined' ? 10000 : options.timeout,
869
- fetch: options.fetch ?? globalThis.fetch.bind(globalThis),
870
- };
871
- if (typeof this._input !== 'string' && !(this._input instanceof URL || this._input instanceof globalThis.Request)) {
872
- throw new TypeError('`input` must be a string, URL, or Request');
873
- }
874
- if (this._options.prefixUrl && typeof this._input === 'string') {
875
- if (this._input.startsWith('/')) {
876
- throw new Error('`input` must not begin with a slash when using `prefixUrl`');
877
- }
878
- if (!this._options.prefixUrl.endsWith('/')) {
879
- this._options.prefixUrl += '/';
880
- }
881
- this._input = this._options.prefixUrl + this._input;
882
- }
883
- if (supportsAbortController) {
884
- this.abortController = new globalThis.AbortController();
885
- if (this._options.signal) {
886
- const originalSignal = this._options.signal;
887
- this._options.signal.addEventListener('abort', () => {
888
- this.abortController.abort(originalSignal.reason);
889
- });
890
- }
891
- this._options.signal = this.abortController.signal;
892
- }
893
- if (supportsRequestStreams) {
894
- // @ts-expect-error - Types are outdated.
895
- this._options.duplex = 'half';
896
- }
897
- this.request = new globalThis.Request(this._input, this._options);
898
- if (this._options.searchParams) {
899
- // eslint-disable-next-line unicorn/prevent-abbreviations
900
- const textSearchParams = typeof this._options.searchParams === 'string'
901
- ? this._options.searchParams.replace(/^\?/, '')
902
- : new URLSearchParams(this._options.searchParams).toString();
903
- // eslint-disable-next-line unicorn/prevent-abbreviations
904
- const searchParams = '?' + textSearchParams;
905
- const url = this.request.url.replace(/(?:\?.*?)?(?=#|$)/, searchParams);
906
- // To provide correct form boundary, Content-Type header should be deleted each time when new Request instantiated from another one
907
- if (((supportsFormData && this._options.body instanceof globalThis.FormData)
908
- || this._options.body instanceof URLSearchParams) && !(this._options.headers && this._options.headers['content-type'])) {
909
- this.request.headers.delete('content-type');
910
- }
911
- // The spread of `this.request` is required as otherwise it misses the `duplex` option for some reason and throws.
912
- this.request = new globalThis.Request(new globalThis.Request(url, { ...this.request }), this._options);
913
- }
914
- if (this._options.json !== undefined) {
915
- this._options.body = JSON.stringify(this._options.json);
916
- this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
917
- this.request = new globalThis.Request(this.request, { body: this._options.body });
918
- }
919
- }
920
- _calculateRetryDelay(error) {
921
- this._retryCount++;
922
- if (this._retryCount < this._options.retry.limit && !(error instanceof TimeoutError)) {
923
- if (error instanceof HTTPError) {
924
- if (!this._options.retry.statusCodes.includes(error.response.status)) {
925
- return 0;
926
- }
927
- const retryAfter = error.response.headers.get('Retry-After');
928
- if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
929
- let after = Number(retryAfter);
930
- if (Number.isNaN(after)) {
931
- after = Date.parse(retryAfter) - Date.now();
932
- }
933
- else {
934
- after *= 1000;
935
- }
936
- if (typeof this._options.retry.maxRetryAfter !== 'undefined' && after > this._options.retry.maxRetryAfter) {
937
- return 0;
938
- }
939
- return after;
940
- }
941
- if (error.response.status === 413) {
942
- return 0;
943
- }
944
- }
945
- const BACKOFF_FACTOR = 0.3;
946
- return Math.min(this._options.retry.backoffLimit, BACKOFF_FACTOR * (2 ** (this._retryCount - 1)) * 1000);
947
- }
948
- return 0;
949
- }
950
- _decorateResponse(response) {
951
- if (this._options.parseJson) {
952
- response.json = async () => this._options.parseJson(await response.text());
953
- }
954
- return response;
955
- }
956
- async _retry(fn) {
957
- try {
958
- return await fn();
959
- // eslint-disable-next-line @typescript-eslint/no-implicit-any-catch
960
- }
961
- catch (error) {
962
- const ms = Math.min(this._calculateRetryDelay(error), maxSafeTimeout);
963
- if (ms !== 0 && this._retryCount > 0) {
964
- await delay(ms, { signal: this._options.signal });
965
- for (const hook of this._options.hooks.beforeRetry) {
966
- // eslint-disable-next-line no-await-in-loop
967
- const hookResult = await hook({
968
- request: this.request,
969
- options: this._options,
970
- error: error,
971
- retryCount: this._retryCount,
972
- });
973
- // If `stop` is returned from the hook, the retry process is stopped
974
- if (hookResult === stop) {
975
- return;
976
- }
977
- }
978
- return this._retry(fn);
979
- }
980
- throw error;
981
- }
982
- }
983
- async _fetch() {
984
- for (const hook of this._options.hooks.beforeRequest) {
985
- // eslint-disable-next-line no-await-in-loop
986
- const result = await hook(this.request, this._options);
987
- if (result instanceof Request) {
988
- this.request = result;
989
- break;
990
- }
991
- if (result instanceof Response) {
992
- return result;
993
- }
994
- }
995
- if (this._options.timeout === false) {
996
- return this._options.fetch(this.request.clone());
997
- }
998
- return timeout(this.request.clone(), this.abortController, this._options);
999
- }
1000
- /* istanbul ignore next */
1001
- _stream(response, onDownloadProgress) {
1002
- const totalBytes = Number(response.headers.get('content-length')) || 0;
1003
- let transferredBytes = 0;
1004
- if (response.status === 204) {
1005
- if (onDownloadProgress) {
1006
- onDownloadProgress({ percent: 1, totalBytes, transferredBytes }, new Uint8Array());
1007
- }
1008
- return new globalThis.Response(null, {
1009
- status: response.status,
1010
- statusText: response.statusText,
1011
- headers: response.headers,
1012
- });
1013
- }
1014
- return new globalThis.Response(new globalThis.ReadableStream({
1015
- async start(controller) {
1016
- const reader = response.body.getReader();
1017
- if (onDownloadProgress) {
1018
- onDownloadProgress({ percent: 0, transferredBytes: 0, totalBytes }, new Uint8Array());
1019
- }
1020
- async function read() {
1021
- const { done, value } = await reader.read();
1022
- if (done) {
1023
- controller.close();
1024
- return;
1025
- }
1026
- if (onDownloadProgress) {
1027
- transferredBytes += value.byteLength;
1028
- const percent = totalBytes === 0 ? 0 : transferredBytes / totalBytes;
1029
- onDownloadProgress({ percent, transferredBytes, totalBytes }, value);
1030
- }
1031
- controller.enqueue(value);
1032
- await read();
1033
- }
1034
- await read();
1035
- },
1036
- }), {
1037
- status: response.status,
1038
- statusText: response.statusText,
1039
- headers: response.headers,
1040
- });
1041
- }
1042
- }
1043
-
1044
- /*! MIT License © Sindre Sorhus */
1045
- const createInstance = (defaults) => {
1046
- // eslint-disable-next-line @typescript-eslint/promise-function-async
1047
- const ky = (input, options) => Ky.create(input, validateAndMerge(defaults, options));
1048
- for (const method of requestMethods) {
1049
- // eslint-disable-next-line @typescript-eslint/promise-function-async
1050
- ky[method] = (input, options) => Ky.create(input, validateAndMerge(defaults, options, { method }));
1051
- }
1052
- ky.create = (newDefaults) => createInstance(validateAndMerge(newDefaults));
1053
- ky.extend = (newDefaults) => createInstance(validateAndMerge(defaults, newDefaults));
1054
- ky.stop = stop;
1055
- return ky;
1056
- };
1057
- const ky = createInstance();
1058
- var ky$1 = ky;
1059
-
1060
539
  var PasskeyApiClient = /** @class */ (function () {
1061
540
  function PasskeyApiClient(_a) {
1062
541
  var baseUrl = _a.baseUrl, tenantId = _a.tenantId;
1063
542
  this.tenantId = tenantId;
1064
- this.api = ky$1.create({
1065
- prefixUrl: baseUrl
1066
- });
543
+ this.baseUrl = baseUrl;
1067
544
  }
1068
545
  PasskeyApiClient.prototype.registrationOptions = function (_a) {
1069
- var token = _a.token, userName = _a.userName;
546
+ var token = _a.token, userName = _a.userName, authenticatorAttachment = _a.authenticatorAttachment;
1070
547
  return __awaiter(this, void 0, void 0, function () {
1071
- var response;
548
+ var body, response;
1072
549
  return __generator(this, function (_b) {
1073
550
  switch (_b.label) {
1074
- case 0: return [4 /*yield*/, this.api.post("client/user-authenticators/passkey/registration-options", {
1075
- json: { username: userName },
1076
- headers: this.buildHeaders(token)
1077
- })];
1078
- case 1:
1079
- response = _b.sent();
1080
- return [2 /*return*/, response.json()];
551
+ case 0:
552
+ body = Boolean(authenticatorAttachment)
553
+ ? { username: userName, authenticatorAttachment: authenticatorAttachment }
554
+ : { username: userName };
555
+ response = fetch("".concat(this.baseUrl, "/client/user-authenticators/passkey/registration-options"), {
556
+ method: "POST",
557
+ headers: this.buildHeaders(token),
558
+ body: JSON.stringify(body)
559
+ });
560
+ return [4 /*yield*/, response];
561
+ case 1: return [2 /*return*/, (_b.sent()).json()];
1081
562
  }
1082
563
  });
1083
564
  });
@@ -1088,13 +569,14 @@ var PasskeyApiClient = /** @class */ (function () {
1088
569
  var response;
1089
570
  return __generator(this, function (_b) {
1090
571
  switch (_b.label) {
1091
- case 0: return [4 /*yield*/, this.api.post("client/user-authenticators/passkey/authentication-options", {
1092
- json: {},
1093
- headers: this.buildHeaders(token)
1094
- })];
1095
- case 1:
1096
- response = _b.sent();
1097
- return [2 /*return*/, response.json()];
572
+ case 0:
573
+ response = fetch("".concat(this.baseUrl, "/client/user-authenticators/passkey/authentication-options"), {
574
+ method: "POST",
575
+ headers: this.buildHeaders(token),
576
+ body: JSON.stringify({})
577
+ });
578
+ return [4 /*yield*/, response];
579
+ case 1: return [2 /*return*/, (_b.sent()).json()];
1098
580
  }
1099
581
  });
1100
582
  });
@@ -1105,13 +587,14 @@ var PasskeyApiClient = /** @class */ (function () {
1105
587
  var response;
1106
588
  return __generator(this, function (_b) {
1107
589
  switch (_b.label) {
1108
- case 0: return [4 /*yield*/, this.api.post("client/user-authenticators/passkey", {
1109
- json: rest,
1110
- headers: this.buildHeaders(token)
1111
- })];
1112
- case 1:
1113
- response = _b.sent();
1114
- return [2 /*return*/, response.json()];
590
+ case 0:
591
+ response = fetch("".concat(this.baseUrl, "/client/user-authenticators/passkey"), {
592
+ method: "POST",
593
+ headers: this.buildHeaders(token),
594
+ body: JSON.stringify(rest)
595
+ });
596
+ return [4 /*yield*/, response];
597
+ case 1: return [2 /*return*/, (_b.sent()).json()];
1115
598
  }
1116
599
  });
1117
600
  });
@@ -1122,12 +605,32 @@ var PasskeyApiClient = /** @class */ (function () {
1122
605
  var response;
1123
606
  return __generator(this, function (_b) {
1124
607
  switch (_b.label) {
1125
- case 0: return [4 /*yield*/, this.api.post("client/verify/passkey", {
1126
- json: rest,
1127
- headers: this.buildHeaders(token)
608
+ case 0:
609
+ response = fetch("".concat(this.baseUrl, "/client/verify/passkey"), {
610
+ method: "POST",
611
+ headers: this.buildHeaders(token),
612
+ body: JSON.stringify(rest)
613
+ });
614
+ return [4 /*yield*/, response];
615
+ case 1: return [2 /*return*/, (_b.sent()).json()];
616
+ }
617
+ });
618
+ });
619
+ };
620
+ PasskeyApiClient.prototype.getPasskeyAuthenticator = function (credentialId) {
621
+ return __awaiter(this, void 0, void 0, function () {
622
+ var response;
623
+ return __generator(this, function (_a) {
624
+ switch (_a.label) {
625
+ case 0: return [4 /*yield*/, fetch("".concat(this.baseUrl, "/client/user-authenticators/passkey?credentialId=").concat(credentialId), {
626
+ method: "GET",
627
+ headers: this.buildHeaders()
1128
628
  })];
1129
629
  case 1:
1130
- response = _b.sent();
630
+ response = _a.sent();
631
+ if (!response.ok) {
632
+ throw new Error(response.statusText);
633
+ }
1131
634
  return [2 /*return*/, response.json()];
1132
635
  }
1133
636
  });
@@ -1136,6 +639,7 @@ var PasskeyApiClient = /** @class */ (function () {
1136
639
  PasskeyApiClient.prototype.buildHeaders = function (token) {
1137
640
  var authorizationHeader = token ? "Bearer ".concat(token) : "Basic ".concat(window.btoa(encodeURIComponent(this.tenantId)));
1138
641
  return {
642
+ "Content-Type": "application/json",
1139
643
  Authorization: authorizationHeader
1140
644
  };
1141
645
  };
@@ -1145,27 +649,31 @@ var PasskeyApiClient = /** @class */ (function () {
1145
649
  var Passkey = /** @class */ (function () {
1146
650
  function Passkey(_a) {
1147
651
  var baseUrl = _a.baseUrl, tenantId = _a.tenantId;
652
+ this.passkeyLocalStorageKey = "as_passkey_credential_id";
1148
653
  this.api = new PasskeyApiClient({ baseUrl: baseUrl, tenantId: tenantId });
1149
654
  }
1150
655
  Passkey.prototype.signUp = function (_a) {
1151
- var userName = _a.userName, token = _a.token;
656
+ var userName = _a.userName, token = _a.token, _b = _a.authenticatorAttachment, authenticatorAttachment = _b === void 0 ? "platform" : _b;
1152
657
  return __awaiter(this, void 0, void 0, function () {
1153
658
  var optionsResponse, registrationResponse, addAuthenticatorResponse;
1154
- return __generator(this, function (_b) {
1155
- switch (_b.label) {
1156
- case 0: return [4 /*yield*/, this.api.registrationOptions({ userName: userName, token: token })];
659
+ return __generator(this, function (_c) {
660
+ switch (_c.label) {
661
+ case 0: return [4 /*yield*/, this.api.registrationOptions({ userName: userName, token: token, authenticatorAttachment: authenticatorAttachment })];
1157
662
  case 1:
1158
- optionsResponse = _b.sent();
663
+ optionsResponse = _c.sent();
1159
664
  return [4 /*yield*/, startRegistration(optionsResponse.options)];
1160
665
  case 2:
1161
- registrationResponse = _b.sent();
666
+ registrationResponse = _c.sent();
1162
667
  return [4 /*yield*/, this.api.addAuthenticator({
1163
668
  challengeId: optionsResponse.challengeId,
1164
669
  registrationCredential: registrationResponse,
1165
670
  token: token
1166
671
  })];
1167
672
  case 3:
1168
- addAuthenticatorResponse = _b.sent();
673
+ addAuthenticatorResponse = _c.sent();
674
+ if (addAuthenticatorResponse === null || addAuthenticatorResponse === void 0 ? void 0 : addAuthenticatorResponse.isVerified) {
675
+ this.storeCredentialAgainstDevice(registrationResponse);
676
+ }
1169
677
  return [2 /*return*/, addAuthenticatorResponse === null || addAuthenticatorResponse === void 0 ? void 0 : addAuthenticatorResponse.accessToken];
1170
678
  }
1171
679
  });
@@ -1193,11 +701,46 @@ var Passkey = /** @class */ (function () {
1193
701
  })];
1194
702
  case 3:
1195
703
  verifyResponse = _a.sent();
704
+ if (verifyResponse === null || verifyResponse === void 0 ? void 0 : verifyResponse.isVerified) {
705
+ this.storeCredentialAgainstDevice(authenticationResponse);
706
+ }
1196
707
  return [2 /*return*/, verifyResponse === null || verifyResponse === void 0 ? void 0 : verifyResponse.accessToken];
1197
708
  }
1198
709
  });
1199
710
  });
1200
711
  };
712
+ Passkey.prototype.isAvailableOnDevice = function () {
713
+ return __awaiter(this, void 0, void 0, function () {
714
+ var credentialId;
715
+ return __generator(this, function (_b) {
716
+ switch (_b.label) {
717
+ case 0:
718
+ credentialId = localStorage.getItem(this.passkeyLocalStorageKey);
719
+ if (!credentialId) {
720
+ return [2 /*return*/, false];
721
+ }
722
+ _b.label = 1;
723
+ case 1:
724
+ _b.trys.push([1, 3, , 4]);
725
+ return [4 /*yield*/, this.api.getPasskeyAuthenticator(credentialId)];
726
+ case 2:
727
+ _b.sent();
728
+ return [2 /*return*/, true];
729
+ case 3:
730
+ _b.sent();
731
+ return [2 /*return*/, false];
732
+ case 4: return [2 /*return*/];
733
+ }
734
+ });
735
+ });
736
+ };
737
+ Passkey.prototype.storeCredentialAgainstDevice = function (_a) {
738
+ var id = _a.id, authenticatorAttachment = _a.authenticatorAttachment;
739
+ if (authenticatorAttachment === "cross-platform") {
740
+ return;
741
+ }
742
+ localStorage.setItem(this.passkeyLocalStorageKey, id);
743
+ };
1201
744
  return Passkey;
1202
745
  }());
1203
746
 
package/dist/index.min.js CHANGED
@@ -1,2 +1 @@
1
- var authsignal=function(t){"use strict";let e;const n=new Uint8Array(16);function o(){if(!e&&(e="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!e))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return e(n)}const i=[];for(let t=0;t<256;++t)i.push((t+256).toString(16).slice(1));var r={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function s(t,e,n){if(r.randomUUID&&!e&&!t)return r.randomUUID();const s=(t=t||{}).random||(t.rng||o)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,e){n=n||0;for(let t=0;t<16;++t)e[n+t]=s[t];return e}return function(t,e=0){return(i[t[e+0]]+i[t[e+1]]+i[t[e+2]]+i[t[e+3]]+"-"+i[t[e+4]]+i[t[e+5]]+"-"+i[t[e+6]]+i[t[e+7]]+"-"+i[t[e+8]]+i[t[e+9]]+"-"+i[t[e+10]]+i[t[e+11]]+i[t[e+12]]+i[t[e+13]]+i[t[e+14]]+i[t[e+15]]).toLowerCase()}(s)}var a=function(t){var e=t.name,n=t.value,o=t.expire,i=t.domain,r=t.secure,s=o===1/0?" expires=Fri, 31 Dec 9999 23:59:59 GMT":"; max-age="+o;document.cookie=encodeURIComponent(e)+"="+n+"; path=/;"+s+(i?"; domain="+i:"")+(r?"; secure":"")};function u(t,e){var n={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&e.indexOf(o)<0&&(n[o]=t[o]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(o=Object.getOwnPropertySymbols(t);i<o.length;i++)e.indexOf(o[i])<0&&Object.prototype.propertyIsEnumerable.call(t,o[i])&&(n[o[i]]=t[o[i]])}return n}function c(t,e,n,o){return new(n||(n=Promise))((function(i,r){function s(t){try{u(o.next(t))}catch(t){r(t)}}function a(t){try{u(o.throw(t))}catch(t){r(t)}}function u(t){var e;t.done?i(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(s,a)}u((o=o.apply(t,e||[])).next())}))}function l(t,e){var n,o,i,r,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return r={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(r[Symbol.iterator]=function(){return this}),r;function a(r){return function(a){return function(r){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,o&&(i=2&r[0]?o.return:r[0]?o.throw||((i=o.return)&&i.call(o),0):o.next)&&!(i=i.call(o,r[1])).done)return i;switch(o=0,i&&(r=[2&r[0],i.value]),r[0]){case 0:case 1:i=r;break;case 4:return s.label++,{value:r[1],done:!1};case 5:s.label++,o=r[1],r=[0];continue;case 7:r=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==r[0]&&2!==r[0])){s=0;continue}if(3===r[0]&&(!i||r[1]>i[0]&&r[1]<i[3])){s.label=r[1];break}if(6===r[0]&&s.label<i[1]){s.label=i[1],i=r;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(r);break}i[2]&&s.ops.pop(),s.trys.pop();continue}r=e.call(t,s)}catch(t){r=[6,t],o=0}finally{n=i=0}if(5&r[0])throw r[1];return{value:r[0]?r[1]:void 0,done:!0}}([r,a])}}}function h(t){const e=new Uint8Array(t);let n="";for(const t of e)n+=String.fromCharCode(t);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function d(t){const e=t.replace(/-/g,"+").replace(/_/g,"/"),n=(4-e.length%4)%4,o=e.padEnd(e.length+n,"="),i=atob(o),r=new ArrayBuffer(i.length),s=new Uint8Array(r);for(let t=0;t<i.length;t++)s[t]=i.charCodeAt(t);return r}function p(){return void 0!==window?.PublicKeyCredential&&"function"==typeof window.PublicKeyCredential}function f(t){const{id:e}=t;return{...t,id:d(e),transports:t.transports}}function w(t){return"localhost"===t||/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(t)}t.AuthsignalWindowMessage=void 0,(t.AuthsignalWindowMessage||(t.AuthsignalWindowMessage={})).AUTHSIGNAL_CLOSE_POPUP="AUTHSIGNAL_CLOSE_POPUP";class b extends Error{constructor({message:t,code:e,cause:n,name:o}){super(t,{cause:n}),this.name=o??n.name,this.code=e}}const m=new class{createNewAbortSignal(){if(this.controller){const t=new Error("Cancelling existing WebAuthn API call for new one");t.name="AbortError",this.controller.abort(t)}const t=new AbortController;return this.controller=t,t.signal}},y=["cross-platform","platform"];function g(t){if(t&&!(y.indexOf(t)<0))return t}async function _(t){if(!p())throw new Error("WebAuthn is not supported in this browser");var e;const n={publicKey:{...t,challenge:d(t.challenge),user:{...t.user,id:(e=t.user.id,(new TextEncoder).encode(e))},excludeCredentials:t.excludeCredentials?.map(f)}};let o;n.signal=m.createNewAbortSignal();try{o=await navigator.credentials.create(n)}catch(t){throw function({error:t,options:e}){const{publicKey:n}=e;if(!n)throw Error("options was missing required publicKey property");if("AbortError"===t.name){if(e.signal instanceof AbortSignal)return new b({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:t})}else if("ConstraintError"===t.name){if(!0===n.authenticatorSelection?.requireResidentKey)return new b({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:t});if("required"===n.authenticatorSelection?.userVerification)return new b({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:t})}else{if("InvalidStateError"===t.name)return new b({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:t});if("NotAllowedError"===t.name)return new b({message:t.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:t});if("NotSupportedError"===t.name)return 0===n.pubKeyCredParams.filter((t=>"public-key"===t.type)).length?new b({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:t}):new b({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:t});if("SecurityError"===t.name){const e=window.location.hostname;if(!w(e))return new b({message:`${window.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:t});if(n.rp.id!==e)return new b({message:`The RP ID "${n.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:t})}else if("TypeError"===t.name){if(n.user.id.byteLength<1||n.user.id.byteLength>64)return new b({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:t})}else if("UnknownError"===t.name)return new b({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:t})}return t}({error:t,options:n})}if(!o)throw new Error("Registration was not completed");const{id:i,rawId:r,response:s,type:a}=o;let u,c,l,y;if("function"==typeof s.getTransports&&(u=s.getTransports()),"function"==typeof s.getPublicKeyAlgorithm)try{c=s.getPublicKeyAlgorithm()}catch(t){v("getPublicKeyAlgorithm()",t)}if("function"==typeof s.getPublicKey)try{const t=s.getPublicKey();null!==t&&(l=h(t))}catch(t){v("getPublicKey()",t)}if("function"==typeof s.getAuthenticatorData)try{y=h(s.getAuthenticatorData())}catch(t){v("getAuthenticatorData()",t)}return{id:i,rawId:h(r),response:{attestationObject:h(s.attestationObject),clientDataJSON:h(s.clientDataJSON),transports:u,publicKeyAlgorithm:c,publicKey:l,authenticatorData:y},type:a,clientExtensionResults:o.getClientExtensionResults(),authenticatorAttachment:g(o.authenticatorAttachment)}}function v(t,e){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${t}. You should report this error to them.\n`,e)}async function E(t,e=!1){if(!p())throw new Error("WebAuthn is not supported in this browser");let n;0!==t.allowCredentials?.length&&(n=t.allowCredentials?.map(f));const o={...t,challenge:d(t.challenge),allowCredentials:n},i={};if(e){if(!await function(){const t=window.PublicKeyCredential;return void 0===t.isConditionalMediationAvailable?new Promise((t=>t(!1))):t.isConditionalMediationAvailable()}())throw Error("Browser does not support WebAuthn autofill");if(document.querySelectorAll("input[autocomplete*='webauthn']").length<1)throw Error('No <input> with `"webauthn"` in its `autocomplete` attribute was detected');i.mediation="conditional",o.allowCredentials=[]}let r;i.publicKey=o,i.signal=m.createNewAbortSignal();try{r=await navigator.credentials.get(i)}catch(t){throw function({error:t,options:e}){const{publicKey:n}=e;if(!n)throw Error("options was missing required publicKey property");if("AbortError"===t.name){if(e.signal instanceof AbortSignal)return new b({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:t})}else{if("NotAllowedError"===t.name)return new b({message:t.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:t});if("SecurityError"===t.name){const e=window.location.hostname;if(!w(e))return new b({message:`${window.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:t});if(n.rpId!==e)return new b({message:`The RP ID "${n.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:t})}else if("UnknownError"===t.name)return new b({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:t})}return t}({error:t,options:i})}if(!r)throw new Error("Authentication was not completed");const{id:s,rawId:a,response:u,type:c}=r;let l;var y;return u.userHandle&&(y=u.userHandle,l=new TextDecoder("utf-8").decode(y)),{id:s,rawId:h(a),response:{authenticatorData:h(u.authenticatorData),clientDataJSON:h(u.clientDataJSON),signature:h(u.signature),userHandle:l},type:c,clientExtensionResults:r.getClientExtensionResults(),authenticatorAttachment:g(r.authenticatorAttachment)}}class R extends Error{constructor(t,e,n){const o=`${t.status||0===t.status?t.status:""} ${t.statusText||""}`.trim();super(`Request failed with ${o?`status code ${o}`:"an unknown error"}`),Object.defineProperty(this,"response",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"request",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"options",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.name="HTTPError",this.response=t,this.request=e,this.options=n}}class A extends Error{constructor(t){super("Request timed out"),Object.defineProperty(this,"request",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.name="TimeoutError",this.request=t}}const T=t=>null!==t&&"object"==typeof t,O=(...t)=>{for(const e of t)if((!T(e)||Array.isArray(e))&&void 0!==e)throw new TypeError("The `options` argument must be an object");return C({},...t)},I=(t={},e={})=>{const n=new globalThis.Headers(t),o=e instanceof globalThis.Headers,i=new globalThis.Headers(e);for(const[t,e]of i.entries())o&&"undefined"===e||void 0===e?n.delete(t):n.set(t,e);return n},C=(...t)=>{let e={},n={};for(const o of t)if(Array.isArray(o))Array.isArray(e)||(e=[]),e=[...e,...o];else if(T(o)){for(let[t,n]of Object.entries(o))T(n)&&t in e&&(n=C(e[t],n)),e={...e,[t]:n};T(o.headers)&&(n=I(n,o.headers),e.headers=n)}return e},x=(()=>{let t=!1,e=!1;const n="function"==typeof globalThis.ReadableStream,o="function"==typeof globalThis.Request;return n&&o&&(e=new globalThis.Request("https://a.com",{body:new globalThis.ReadableStream,method:"POST",get duplex(){return t=!0,"half"}}).headers.has("Content-Type")),t&&!e})(),P="function"==typeof globalThis.AbortController,S="function"==typeof globalThis.ReadableStream,k="function"==typeof globalThis.FormData,U=["get","post","put","patch","head","delete"],D={json:"application/json",text:"text/*",formData:"multipart/form-data",arrayBuffer:"*/*",blob:"*/*"},N=2147483647,q=Symbol("stop"),L=t=>U.includes(t)?t.toUpperCase():t,j=[413,429,503],$={limit:2,methods:["get","put","head","delete","options","trace"],statusCodes:[408,413,429,500,502,503,504],afterStatusCodes:j,maxRetryAfter:Number.POSITIVE_INFINITY,backoffLimit:Number.POSITIVE_INFINITY},H=(t={})=>{if("number"==typeof t)return{...$,limit:t};if(t.methods&&!Array.isArray(t.methods))throw new Error("retry.methods must be an array");if(t.statusCodes&&!Array.isArray(t.statusCodes))throw new Error("retry.statusCodes must be an array");return{...$,...t,afterStatusCodes:j}};const K=Boolean(globalThis.DOMException);function M(t){if(K)return new DOMException(t?.reason??"The operation was aborted.","AbortError");const e=new Error(t?.reason??"The operation was aborted.");return e.name="AbortError",e}class W{static create(t,e){const n=new W(t,e),o=async()=>{if(n._options.timeout>N)throw new RangeError("The `timeout` option cannot be greater than 2147483647");await Promise.resolve();let t=await n._fetch();for(const e of n._options.hooks.afterResponse){const o=await e(n.request,n._options,n._decorateResponse(t.clone()));o instanceof globalThis.Response&&(t=o)}if(n._decorateResponse(t),!t.ok&&n._options.throwHttpErrors){let e=new R(t,n.request,n._options);for(const t of n._options.hooks.beforeError)e=await t(e);throw e}if(n._options.onDownloadProgress){if("function"!=typeof n._options.onDownloadProgress)throw new TypeError("The `onDownloadProgress` option must be a function");if(!S)throw new Error("Streams are not supported in your environment. `ReadableStream` is missing.");return n._stream(t.clone(),n._options.onDownloadProgress)}return t},i=n._options.retry.methods.includes(n.request.method.toLowerCase())?n._retry(o):o();for(const[t,o]of Object.entries(D))i[t]=async()=>{n.request.headers.set("accept",n.request.headers.get("accept")||o);const r=(await i).clone();if("json"===t){if(204===r.status)return"";if(0===(await r.clone().arrayBuffer()).byteLength)return"";if(e.parseJson)return e.parseJson(await r.text())}return r[t]()};return i}constructor(t,e={}){if(Object.defineProperty(this,"request",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"abortController",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_retryCount",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_input",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_options",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this._input=t,this._options={credentials:this._input.credentials||"same-origin",...e,headers:I(this._input.headers,e.headers),hooks:C({beforeRequest:[],beforeRetry:[],beforeError:[],afterResponse:[]},e.hooks),method:L(e.method??this._input.method),prefixUrl:String(e.prefixUrl||""),retry:H(e.retry),throwHttpErrors:!1!==e.throwHttpErrors,timeout:void 0===e.timeout?1e4:e.timeout,fetch:e.fetch??globalThis.fetch.bind(globalThis)},"string"!=typeof this._input&&!(this._input instanceof URL||this._input instanceof globalThis.Request))throw new TypeError("`input` must be a string, URL, or Request");if(this._options.prefixUrl&&"string"==typeof this._input){if(this._input.startsWith("/"))throw new Error("`input` must not begin with a slash when using `prefixUrl`");this._options.prefixUrl.endsWith("/")||(this._options.prefixUrl+="/"),this._input=this._options.prefixUrl+this._input}if(P){if(this.abortController=new globalThis.AbortController,this._options.signal){const t=this._options.signal;this._options.signal.addEventListener("abort",(()=>{this.abortController.abort(t.reason)}))}this._options.signal=this.abortController.signal}if(x&&(this._options.duplex="half"),this.request=new globalThis.Request(this._input,this._options),this._options.searchParams){const t="?"+("string"==typeof this._options.searchParams?this._options.searchParams.replace(/^\?/,""):new URLSearchParams(this._options.searchParams).toString()),e=this.request.url.replace(/(?:\?.*?)?(?=#|$)/,t);!(k&&this._options.body instanceof globalThis.FormData||this._options.body instanceof URLSearchParams)||this._options.headers&&this._options.headers["content-type"]||this.request.headers.delete("content-type"),this.request=new globalThis.Request(new globalThis.Request(e,{...this.request}),this._options)}void 0!==this._options.json&&(this._options.body=JSON.stringify(this._options.json),this.request.headers.set("content-type",this._options.headers.get("content-type")??"application/json"),this.request=new globalThis.Request(this.request,{body:this._options.body}))}_calculateRetryDelay(t){if(this._retryCount++,this._retryCount<this._options.retry.limit&&!(t instanceof A)){if(t instanceof R){if(!this._options.retry.statusCodes.includes(t.response.status))return 0;const e=t.response.headers.get("Retry-After");if(e&&this._options.retry.afterStatusCodes.includes(t.response.status)){let t=Number(e);return Number.isNaN(t)?t=Date.parse(e)-Date.now():t*=1e3,void 0!==this._options.retry.maxRetryAfter&&t>this._options.retry.maxRetryAfter?0:t}if(413===t.response.status)return 0}const e=.3;return Math.min(this._options.retry.backoffLimit,e*2**(this._retryCount-1)*1e3)}return 0}_decorateResponse(t){return this._options.parseJson&&(t.json=async()=>this._options.parseJson(await t.text())),t}async _retry(t){try{return await t()}catch(e){const n=Math.min(this._calculateRetryDelay(e),N);if(0!==n&&this._retryCount>0){await async function(t,{signal:e}){return new Promise(((n,o)=>{if(e){if(e.aborted)return void o(M(e));e.addEventListener("abort",i,{once:!0})}function i(){o(M(e)),clearTimeout(r)}const r=setTimeout((()=>{e?.removeEventListener("abort",i),n()}),t)}))}(n,{signal:this._options.signal});for(const t of this._options.hooks.beforeRetry){if(await t({request:this.request,options:this._options,error:e,retryCount:this._retryCount})===q)return}return this._retry(t)}throw e}}async _fetch(){for(const t of this._options.hooks.beforeRequest){const e=await t(this.request,this._options);if(e instanceof Request){this.request=e;break}if(e instanceof Response)return e}return!1===this._options.timeout?this._options.fetch(this.request.clone()):async function(t,e,n){return new Promise(((o,i)=>{const r=setTimeout((()=>{e&&e.abort(),i(new A(t))}),n.timeout);n.fetch(t).then(o).catch(i).then((()=>{clearTimeout(r)}))}))}(this.request.clone(),this.abortController,this._options)}_stream(t,e){const n=Number(t.headers.get("content-length"))||0;let o=0;return 204===t.status?(e&&e({percent:1,totalBytes:n,transferredBytes:o},new Uint8Array),new globalThis.Response(null,{status:t.status,statusText:t.statusText,headers:t.headers})):new globalThis.Response(new globalThis.ReadableStream({async start(i){const r=t.body.getReader();e&&e({percent:0,transferredBytes:0,totalBytes:n},new Uint8Array),await async function t(){const{done:s,value:a}=await r.read();if(s)i.close();else{if(e){o+=a.byteLength;e({percent:0===n?0:o/n,transferredBytes:o,totalBytes:n},a)}i.enqueue(a),await t()}}()}}),{status:t.status,statusText:t.statusText,headers:t.headers})}}
2
- /*! MIT License © Sindre Sorhus */const F=t=>{const e=(e,n)=>W.create(e,O(t,n));for(const n of U)e[n]=(e,o)=>W.create(e,O(t,o,{method:n}));return e.create=t=>F(O(t)),e.extend=e=>F(O(t,e)),e.stop=q,e};var B=F(),G=function(){function t(t){var e=t.baseUrl,n=t.tenantId;this.tenantId=n,this.api=B.create({prefixUrl:e})}return t.prototype.registrationOptions=function(t){var e=t.token,n=t.userName;return c(this,void 0,void 0,(function(){return l(this,(function(t){switch(t.label){case 0:return[4,this.api.post("client/user-authenticators/passkey/registration-options",{json:{username:n},headers:this.buildHeaders(e)})];case 1:return[2,t.sent().json()]}}))}))},t.prototype.authenticationOptions=function(t){var e=t.token;return c(this,void 0,void 0,(function(){return l(this,(function(t){switch(t.label){case 0:return[4,this.api.post("client/user-authenticators/passkey/authentication-options",{json:{},headers:this.buildHeaders(e)})];case 1:return[2,t.sent().json()]}}))}))},t.prototype.addAuthenticator=function(t){var e=t.token,n=u(t,["token"]);return c(this,void 0,void 0,(function(){return l(this,(function(t){switch(t.label){case 0:return[4,this.api.post("client/user-authenticators/passkey",{json:n,headers:this.buildHeaders(e)})];case 1:return[2,t.sent().json()]}}))}))},t.prototype.verify=function(t){var e=t.token,n=u(t,["token"]);return c(this,void 0,void 0,(function(){return l(this,(function(t){switch(t.label){case 0:return[4,this.api.post("client/verify/passkey",{json:n,headers:this.buildHeaders(e)})];case 1:return[2,t.sent().json()]}}))}))},t.prototype.buildHeaders=function(t){return{Authorization:t?"Bearer ".concat(t):"Basic ".concat(window.btoa(encodeURIComponent(this.tenantId)))}},t}(),V=function(){function t(t){var e=t.baseUrl,n=t.tenantId;this.api=new G({baseUrl:e,tenantId:n})}return t.prototype.signUp=function(t){var e=t.userName,n=t.token;return c(this,void 0,void 0,(function(){var t,o,i;return l(this,(function(r){switch(r.label){case 0:return[4,this.api.registrationOptions({userName:e,token:n})];case 1:return[4,_((t=r.sent()).options)];case 2:return o=r.sent(),[4,this.api.addAuthenticator({challengeId:t.challengeId,registrationCredential:o,token:n})];case 3:return[2,null==(i=r.sent())?void 0:i.accessToken]}}))}))},t.prototype.signIn=function(t){return c(this,void 0,void 0,(function(){var e,n,o;return l(this,(function(i){switch(i.label){case 0:if((null==t?void 0:t.token)&&t.autofill)throw new Error("Autofill is not supported when providing a token");return[4,this.api.authenticationOptions({token:null==t?void 0:t.token})];case 1:return[4,E((e=i.sent()).options,null==t?void 0:t.autofill)];case 2:return n=i.sent(),[4,this.api.verify({challengeId:e.challengeId,authenticationCredential:n,token:null==t?void 0:t.token})];case 3:return[2,null==(o=i.sent())?void 0:o.accessToken]}}))}))},t}(),z=function(){function t(){this.windowRef=null}return t.prototype.show=function(t){var e=t.url,n=t.width,o=void 0===n?400:n,i=t.height,r=function(t){var e=t.url,n=t.width,o=t.height,i=t.win;if(!i.top)return null;var r=i.top.outerHeight/2+i.top.screenY-o/2,s=i.top.outerWidth/2+i.top.screenX-n/2;return window.open(e,"","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=".concat(n,", height=").concat(o,", top=").concat(r,", left=").concat(s))}({url:e,width:o,height:void 0===i?500:i,win:window});if(!r)throw new Error("Window is not initialized");return this.windowRef=r,r},t.prototype.close=function(){if(!this.windowRef)throw new Error("Window is not initialized");this.windowRef.close()},t}();var J=['a[href]:not([tabindex^="-"])','area[href]:not([tabindex^="-"])','input:not([type="hidden"]):not([type="radio"]):not([disabled]):not([tabindex^="-"])','input[type="radio"]:not([disabled]):not([tabindex^="-"])','select:not([disabled]):not([tabindex^="-"])','textarea:not([disabled]):not([tabindex^="-"])','button:not([disabled]):not([tabindex^="-"])','iframe:not([tabindex^="-"])','audio[controls]:not([tabindex^="-"])','video[controls]:not([tabindex^="-"])','[contenteditable]:not([tabindex^="-"])','[tabindex]:not([tabindex^="-"])'];function Y(t){this._show=this.show.bind(this),this._hide=this.hide.bind(this),this._maintainFocus=this._maintainFocus.bind(this),this._bindKeypress=this._bindKeypress.bind(this),this.$el=t,this.shown=!1,this._id=this.$el.getAttribute("data-a11y-dialog")||this.$el.id,this._previouslyFocused=null,this._listeners={},this.create()}function X(t,e){return n=(e||document).querySelectorAll(t),Array.prototype.slice.call(n);var n}function Q(t){(t.querySelector("[autofocus]")||t).focus()}function Z(){X("[data-a11y-dialog]").forEach((function(t){new Y(t)}))}Y.prototype.create=function(){this.$el.setAttribute("aria-hidden",!0),this.$el.setAttribute("aria-modal",!0),this.$el.setAttribute("tabindex",-1),this.$el.hasAttribute("role")||this.$el.setAttribute("role","dialog"),this._openers=X('[data-a11y-dialog-show="'+this._id+'"]'),this._openers.forEach(function(t){t.addEventListener("click",this._show)}.bind(this));const t=this.$el;return this._closers=X("[data-a11y-dialog-hide]",this.$el).filter((function(e){return e.closest('[aria-modal="true"], [data-a11y-dialog]')===t})).concat(X('[data-a11y-dialog-hide="'+this._id+'"]')),this._closers.forEach(function(t){t.addEventListener("click",this._hide)}.bind(this)),this._fire("create"),this},Y.prototype.show=function(t){return this.shown||(this._previouslyFocused=document.activeElement,this.$el.removeAttribute("aria-hidden"),this.shown=!0,Q(this.$el),document.body.addEventListener("focus",this._maintainFocus,!0),document.addEventListener("keydown",this._bindKeypress),this._fire("show",t)),this},Y.prototype.hide=function(t){return this.shown?(this.shown=!1,this.$el.setAttribute("aria-hidden","true"),this._previouslyFocused&&this._previouslyFocused.focus&&this._previouslyFocused.focus(),document.body.removeEventListener("focus",this._maintainFocus,!0),document.removeEventListener("keydown",this._bindKeypress),this._fire("hide",t),this):this},Y.prototype.destroy=function(){return this.hide(),this._openers.forEach(function(t){t.removeEventListener("click",this._show)}.bind(this)),this._closers.forEach(function(t){t.removeEventListener("click",this._hide)}.bind(this)),this._fire("destroy"),this._listeners={},this},Y.prototype.on=function(t,e){return void 0===this._listeners[t]&&(this._listeners[t]=[]),this._listeners[t].push(e),this},Y.prototype.off=function(t,e){var n=(this._listeners[t]||[]).indexOf(e);return n>-1&&this._listeners[t].splice(n,1),this},Y.prototype._fire=function(t,e){var n=this._listeners[t]||[],o=new CustomEvent(t,{detail:e});this.$el.dispatchEvent(o),n.forEach(function(t){t(this.$el,e)}.bind(this))},Y.prototype._bindKeypress=function(t){const e=document.activeElement;e&&e.closest('[aria-modal="true"]')!==this.$el||(this.shown&&"Escape"===t.key&&"alertdialog"!==this.$el.getAttribute("role")&&(t.preventDefault(),this.hide(t)),this.shown&&"Tab"===t.key&&function(t,e){var n=function(t){return X(J.join(","),t).filter((function(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)}))}(t),o=n.indexOf(document.activeElement);e.shiftKey&&0===o?(n[n.length-1].focus(),e.preventDefault()):e.shiftKey||o!==n.length-1||(n[0].focus(),e.preventDefault())}(this.$el,t))},Y.prototype._maintainFocus=function(t){!this.shown||t.target.closest('[aria-modal="true"]')||t.target.closest("[data-a11y-dialog-ignore-focus-trap]")||Q(this.$el)},"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",Z):window.requestAnimationFrame?window.requestAnimationFrame(Z):window.setTimeout(Z,16));var tt="__authsignal-popup-container",et="__authsignal-popup-content",nt="__authsignal-popup-overlay",ot="__authsignal-popup-style",it="__authsignal-popup-iframe",rt="385px",st=function(){function t(t){var e=t.width;if(this.popup=null,document.querySelector("#".concat(tt)))throw new Error("Multiple instances of Authsignal popup is not supported.");this.create({width:e})}return t.prototype.create=function(t){var e=this,n=t.width,o=void 0===n?rt:n,i=o;CSS.supports("width",o)||(console.warn("Invalid CSS value for `popupOptions.width`. Using default value instead."),i=rt);var r=document.createElement("div");r.setAttribute("id",tt),r.setAttribute("aria-hidden","true");var s=document.createElement("div");s.setAttribute("id",nt),s.setAttribute("data-a11y-dialog-hide","true");var a=document.createElement("div");a.setAttribute("id",et),document.body.appendChild(r);var u=document.createElement("style");u.setAttribute("id",ot),u.textContent="\n #".concat(tt,",\n #").concat(nt," {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n\n #").concat(tt," {\n z-index: 2147483647;\n display: flex;\n }\n\n #").concat(tt,"[aria-hidden='true'] {\n display: none;\n }\n\n #").concat(nt," {\n background-color: rgba(0, 0, 0, 0.18);\n }\n\n #").concat(et," {\n margin: auto;\n z-index: 2147483647;\n position: relative;\n background-color: transparent;\n border-radius: 8px;\n width: ").concat(i,";\n }\n\n #").concat(et," iframe {\n width: 1px;\n min-width: 100%;\n border-radius: inherit;\n max-height: 95vh;\n height: ").concat("384px",";\n }\n "),document.head.insertAdjacentElement("beforeend",u),r.appendChild(s),r.appendChild(a),this.popup=new Y(r),this.popup.on("hide",(function(){e.destroy()}))},t.prototype.destroy=function(){var t=document.querySelector("#".concat(tt)),e=document.querySelector("#".concat(ot));t&&e&&(document.body.removeChild(t),document.head.removeChild(e)),window.removeEventListener("message",at)},t.prototype.show=function(t){var e,n=t.url;if(!this.popup)throw new Error("Popup is not initialized");var o=document.createElement("iframe");o.setAttribute("id",it),o.setAttribute("name","authsignal"),o.setAttribute("title","Authsignal multi-factor authentication"),o.setAttribute("src",n),o.setAttribute("frameborder","0"),o.setAttribute("allow","publickey-credentials-get *; publickey-credentials-create *; clipboard-write");var i=document.querySelector("#".concat(et));i&&i.appendChild(o),window.addEventListener("message",at),null===(e=this.popup)||void 0===e||e.show()},t.prototype.close=function(){if(!this.popup)throw new Error("Popup is not initialized");this.popup.hide()},t.prototype.on=function(t,e){if(!this.popup)throw new Error("Popup is not initialized");this.popup.on(t,e)},t}();function at(t){var e=document.querySelector("#".concat(it));e&&t.data.height&&(e.style.height=t.data.height+"px")}var ut="4a08uqve",ct=function(){function e(t){var e=t.cookieDomain,n=t.cookieName,o=void 0===n?"__as_aid":n,i=t.baseUrl,r=void 0===i?"https://api.authsignal.com/v1":i,u=t.tenantId;if(this.anonymousId="",this.profilingId="",this.cookieDomain="",this.anonymousIdCookieName="",this._token=void 0,this.cookieDomain=e||document.location.hostname.replace("www.",""),this.anonymousIdCookieName=o,!u)throw new Error("tenantId is required");this.passkey=new V({tenantId:u,baseUrl:r});var c,l=(c=this.anonymousIdCookieName)&&decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*"+encodeURIComponent(c).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1"))||null;l?this.anonymousId=l:(this.anonymousId=s(),a({name:this.anonymousIdCookieName,value:this.anonymousId,expire:1/0,domain:this.cookieDomain,secure:"http:"!==document.location.protocol}))}return e.prototype.launch=function(t,e){switch(null==e?void 0:e.mode){case"window":return this.launchWithWindow(t,e);case"popup":return this.launchWithPopup(t,e);default:this.launchWithRedirect(t)}},e.prototype.initAdvancedProfiling=function(t){var e=s();this.profilingId=e,a({name:"__as_pid",value:e,expire:1/0,domain:this.cookieDomain,secure:"http:"!==document.location.protocol});var n=t?"".concat(t,"/fp/tags.js?org_id=").concat(ut,"&session_id=").concat(e):"https://h.online-metrix.net/fp/tags.js?org_id=".concat(ut,"&session_id=").concat(e),o=document.createElement("script");o.src=n,o.async=!1,o.id="as_adv_profile",document.head.appendChild(o);var i=document.createElement("noscript");i.setAttribute("id","as_adv_profile_pixel"),i.setAttribute("aria-hidden","true");var r=document.createElement("iframe"),u=t?"".concat(t,"/fp/tags?org_id=").concat(ut,"&session_id=").concat(e):"https://h.online-metrix.net/fp/tags?org_id=".concat(ut,"&session_id=").concat(e);r.setAttribute("id","as_adv_profile_pixel"),r.setAttribute("src",u),r.setAttribute("style","width: 100px; height: 100px; border: 0; position: absolute; top: -5000px;"),i&&(i.appendChild(r),document.body.prepend(i))},e.prototype.launchWithRedirect=function(t){window.location.href=t},e.prototype.launchWithPopup=function(e,n){var o=this,i=n.popupOptions,r=new st({width:null==i?void 0:i.width}),s="".concat(e,"&mode=popup");return r.show({url:s}),new Promise((function(e){r.on("hide",(function(){e({token:o._token})})),window.addEventListener("message",(function(e){var n=null;try{n=JSON.parse(e.data)}catch(t){}(null==n?void 0:n.event)===t.AuthsignalWindowMessage.AUTHSIGNAL_CLOSE_POPUP&&(o._token=n.token,r.close())}),!1)}))},e.prototype.launchWithWindow=function(e,n){var o=this,i=n.windowOptions,r=new z,s="".concat(e,"&mode=popup");return r.show({url:s,width:null==i?void 0:i.width,height:null==i?void 0:i.height}),new Promise((function(e){window.addEventListener("message",(function(n){var i=null;try{i=JSON.parse(n.data)}catch(t){}(null==i?void 0:i.event)===t.AuthsignalWindowMessage.AUTHSIGNAL_CLOSE_POPUP&&(o._token=i.token,r.close(),e({token:o._token}))}),!1)}))},e}();return t.Authsignal=ct,Object.defineProperty(t,"__esModule",{value:!0}),t}({});
1
+ var authsignal=function(t){"use strict";let e;const n=new Uint8Array(16);function i(){if(!e&&(e="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!e))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return e(n)}const o=[];for(let t=0;t<256;++t)o.push((t+256).toString(16).slice(1));var r={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function a(t,e,n){if(r.randomUUID&&!e&&!t)return r.randomUUID();const a=(t=t||{}).random||(t.rng||i)();if(a[6]=15&a[6]|64,a[8]=63&a[8]|128,e){n=n||0;for(let t=0;t<16;++t)e[n+t]=a[t];return e}return function(t,e=0){return(o[t[e+0]]+o[t[e+1]]+o[t[e+2]]+o[t[e+3]]+"-"+o[t[e+4]]+o[t[e+5]]+"-"+o[t[e+6]]+o[t[e+7]]+"-"+o[t[e+8]]+o[t[e+9]]+"-"+o[t[e+10]]+o[t[e+11]]+o[t[e+12]]+o[t[e+13]]+o[t[e+14]]+o[t[e+15]]).toLowerCase()}(a)}var s=function(t){var e=t.name,n=t.value,i=t.expire,o=t.domain,r=t.secure,a=i===1/0?" expires=Fri, 31 Dec 9999 23:59:59 GMT":"; max-age="+i;document.cookie=encodeURIComponent(e)+"="+n+"; path=/;"+a+(o?"; domain="+o:"")+(r?"; secure":"")};function c(t,e){var n={};for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&e.indexOf(i)<0&&(n[i]=t[i]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(i=Object.getOwnPropertySymbols(t);o<i.length;o++)e.indexOf(i[o])<0&&Object.prototype.propertyIsEnumerable.call(t,i[o])&&(n[i[o]]=t[i[o]])}return n}function u(t,e,n,i){return new(n||(n=Promise))((function(o,r){function a(t){try{c(i.next(t))}catch(t){r(t)}}function s(t){try{c(i.throw(t))}catch(t){r(t)}}function c(t){var e;t.done?o(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(a,s)}c((i=i.apply(t,e||[])).next())}))}function l(t,e){var n,i,o,r,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return r={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(r[Symbol.iterator]=function(){return this}),r;function s(r){return function(s){return function(r){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,i&&(o=2&r[0]?i.return:r[0]?i.throw||((o=i.return)&&o.call(i),0):i.next)&&!(o=o.call(i,r[1])).done)return o;switch(i=0,o&&(r=[2&r[0],o.value]),r[0]){case 0:case 1:o=r;break;case 4:return a.label++,{value:r[1],done:!1};case 5:a.label++,i=r[1],r=[0];continue;case 7:r=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==r[0]&&2!==r[0])){a=0;continue}if(3===r[0]&&(!o||r[1]>o[0]&&r[1]<o[3])){a.label=r[1];break}if(6===r[0]&&a.label<o[1]){a.label=o[1],o=r;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(r);break}o[2]&&a.ops.pop(),a.trys.pop();continue}r=e.call(t,a)}catch(t){r=[6,t],i=0}finally{n=o=0}if(5&r[0])throw r[1];return{value:r[0]?r[1]:void 0,done:!0}}([r,s])}}}function d(t){const e=new Uint8Array(t);let n="";for(const t of e)n+=String.fromCharCode(t);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function h(t){const e=t.replace(/-/g,"+").replace(/_/g,"/"),n=(4-e.length%4)%4,i=e.padEnd(e.length+n,"="),o=atob(i),r=new ArrayBuffer(o.length),a=new Uint8Array(r);for(let t=0;t<o.length;t++)a[t]=o.charCodeAt(t);return r}function p(){return void 0!==window?.PublicKeyCredential&&"function"==typeof window.PublicKeyCredential}function f(t){const{id:e}=t;return{...t,id:h(e),transports:t.transports}}function w(t){return"localhost"===t||/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(t)}t.AuthsignalWindowMessage=void 0,(t.AuthsignalWindowMessage||(t.AuthsignalWindowMessage={})).AUTHSIGNAL_CLOSE_POPUP="AUTHSIGNAL_CLOSE_POPUP";class m extends Error{constructor({message:t,code:e,cause:n,name:i}){super(t,{cause:n}),this.name=i??n.name,this.code=e}}const y=new class{createNewAbortSignal(){if(this.controller){const t=new Error("Cancelling existing WebAuthn API call for new one");t.name="AbortError",this.controller.abort(t)}const t=new AbortController;return this.controller=t,t.signal}cancelCeremony(){if(this.controller){const t=new Error("Manually cancelling existing WebAuthn API call");t.name="AbortError",this.controller.abort(t),this.controller=void 0}}},b=["cross-platform","platform"];function g(t){if(t&&!(b.indexOf(t)<0))return t}async function v(t){if(!p())throw new Error("WebAuthn is not supported in this browser");var e;const n={publicKey:{...t,challenge:h(t.challenge),user:{...t.user,id:(e=t.user.id,(new TextEncoder).encode(e))},excludeCredentials:t.excludeCredentials?.map(f)}};let i;n.signal=y.createNewAbortSignal();try{i=await navigator.credentials.create(n)}catch(t){throw function({error:t,options:e}){const{publicKey:n}=e;if(!n)throw Error("options was missing required publicKey property");if("AbortError"===t.name){if(e.signal instanceof AbortSignal)return new m({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:t})}else if("ConstraintError"===t.name){if(!0===n.authenticatorSelection?.requireResidentKey)return new m({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:t});if("required"===n.authenticatorSelection?.userVerification)return new m({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:t})}else{if("InvalidStateError"===t.name)return new m({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:t});if("NotAllowedError"===t.name)return new m({message:t.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:t});if("NotSupportedError"===t.name)return 0===n.pubKeyCredParams.filter((t=>"public-key"===t.type)).length?new m({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:t}):new m({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:t});if("SecurityError"===t.name){const e=window.location.hostname;if(!w(e))return new m({message:`${window.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:t});if(n.rp.id!==e)return new m({message:`The RP ID "${n.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:t})}else if("TypeError"===t.name){if(n.user.id.byteLength<1||n.user.id.byteLength>64)return new m({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:t})}else if("UnknownError"===t.name)return new m({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:t})}return t}({error:t,options:n})}if(!i)throw new Error("Registration was not completed");const{id:o,rawId:r,response:a,type:s}=i;let c,u,l,b;if("function"==typeof a.getTransports&&(c=a.getTransports()),"function"==typeof a.getPublicKeyAlgorithm)try{u=a.getPublicKeyAlgorithm()}catch(t){_("getPublicKeyAlgorithm()",t)}if("function"==typeof a.getPublicKey)try{const t=a.getPublicKey();null!==t&&(l=d(t))}catch(t){_("getPublicKey()",t)}if("function"==typeof a.getAuthenticatorData)try{b=d(a.getAuthenticatorData())}catch(t){_("getAuthenticatorData()",t)}return{id:o,rawId:d(r),response:{attestationObject:d(a.attestationObject),clientDataJSON:d(a.clientDataJSON),transports:c,publicKeyAlgorithm:u,publicKey:l,authenticatorData:b},type:s,clientExtensionResults:i.getClientExtensionResults(),authenticatorAttachment:g(i.authenticatorAttachment)}}function _(t,e){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${t}. You should report this error to them.\n`,e)}async function E(t,e=!1){if(!p())throw new Error("WebAuthn is not supported in this browser");let n;0!==t.allowCredentials?.length&&(n=t.allowCredentials?.map(f));const i={...t,challenge:h(t.challenge),allowCredentials:n},o={};if(e){if(!await function(){const t=window.PublicKeyCredential;return void 0===t.isConditionalMediationAvailable?new Promise((t=>t(!1))):t.isConditionalMediationAvailable()}())throw Error("Browser does not support WebAuthn autofill");if(document.querySelectorAll("input[autocomplete$='webauthn']").length<1)throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');o.mediation="conditional",i.allowCredentials=[]}let r;o.publicKey=i,o.signal=y.createNewAbortSignal();try{r=await navigator.credentials.get(o)}catch(t){throw function({error:t,options:e}){const{publicKey:n}=e;if(!n)throw Error("options was missing required publicKey property");if("AbortError"===t.name){if(e.signal instanceof AbortSignal)return new m({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:t})}else{if("NotAllowedError"===t.name)return new m({message:t.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:t});if("SecurityError"===t.name){const e=window.location.hostname;if(!w(e))return new m({message:`${window.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:t});if(n.rpId!==e)return new m({message:`The RP ID "${n.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:t})}else if("UnknownError"===t.name)return new m({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:t})}return t}({error:t,options:o})}if(!r)throw new Error("Authentication was not completed");const{id:a,rawId:s,response:c,type:u}=r;let l;var b;return c.userHandle&&(b=c.userHandle,l=new TextDecoder("utf-8").decode(b)),{id:a,rawId:d(s),response:{authenticatorData:d(c.authenticatorData),clientDataJSON:d(c.clientDataJSON),signature:d(c.signature),userHandle:l},type:u,clientExtensionResults:r.getClientExtensionResults(),authenticatorAttachment:g(r.authenticatorAttachment)}}var A=function(){function t(t){var e=t.baseUrl,n=t.tenantId;this.tenantId=n,this.baseUrl=e}return t.prototype.registrationOptions=function(t){var e=t.token,n=t.userName,i=t.authenticatorAttachment;return u(this,void 0,void 0,(function(){var t;return l(this,(function(o){switch(o.label){case 0:return t=Boolean(i)?{username:n,authenticatorAttachment:i}:{username:n},[4,fetch("".concat(this.baseUrl,"/client/user-authenticators/passkey/registration-options"),{method:"POST",headers:this.buildHeaders(e),body:JSON.stringify(t)})];case 1:return[2,o.sent().json()]}}))}))},t.prototype.authenticationOptions=function(t){var e=t.token;return u(this,void 0,void 0,(function(){return l(this,(function(t){switch(t.label){case 0:return[4,fetch("".concat(this.baseUrl,"/client/user-authenticators/passkey/authentication-options"),{method:"POST",headers:this.buildHeaders(e),body:JSON.stringify({})})];case 1:return[2,t.sent().json()]}}))}))},t.prototype.addAuthenticator=function(t){var e=t.token,n=c(t,["token"]);return u(this,void 0,void 0,(function(){return l(this,(function(t){switch(t.label){case 0:return[4,fetch("".concat(this.baseUrl,"/client/user-authenticators/passkey"),{method:"POST",headers:this.buildHeaders(e),body:JSON.stringify(n)})];case 1:return[2,t.sent().json()]}}))}))},t.prototype.verify=function(t){var e=t.token,n=c(t,["token"]);return u(this,void 0,void 0,(function(){return l(this,(function(t){switch(t.label){case 0:return[4,fetch("".concat(this.baseUrl,"/client/verify/passkey"),{method:"POST",headers:this.buildHeaders(e),body:JSON.stringify(n)})];case 1:return[2,t.sent().json()]}}))}))},t.prototype.getPasskeyAuthenticator=function(t){return u(this,void 0,void 0,(function(){var e;return l(this,(function(n){switch(n.label){case 0:return[4,fetch("".concat(this.baseUrl,"/client/user-authenticators/passkey?credentialId=").concat(t),{method:"GET",headers:this.buildHeaders()})];case 1:if(!(e=n.sent()).ok)throw new Error(e.statusText);return[2,e.json()]}}))}))},t.prototype.buildHeaders=function(t){return{"Content-Type":"application/json",Authorization:t?"Bearer ".concat(t):"Basic ".concat(window.btoa(encodeURIComponent(this.tenantId)))}},t}(),R=function(){function t(t){var e=t.baseUrl,n=t.tenantId;this.passkeyLocalStorageKey="as_passkey_credential_id",this.api=new A({baseUrl:e,tenantId:n})}return t.prototype.signUp=function(t){var e=t.userName,n=t.token,i=t.authenticatorAttachment,o=void 0===i?"platform":i;return u(this,void 0,void 0,(function(){var t,i,r;return l(this,(function(a){switch(a.label){case 0:return[4,this.api.registrationOptions({userName:e,token:n,authenticatorAttachment:o})];case 1:return[4,v((t=a.sent()).options)];case 2:return i=a.sent(),[4,this.api.addAuthenticator({challengeId:t.challengeId,registrationCredential:i,token:n})];case 3:return(null==(r=a.sent())?void 0:r.isVerified)&&this.storeCredentialAgainstDevice(i),[2,null==r?void 0:r.accessToken]}}))}))},t.prototype.signIn=function(t){return u(this,void 0,void 0,(function(){var e,n,i;return l(this,(function(o){switch(o.label){case 0:if((null==t?void 0:t.token)&&t.autofill)throw new Error("Autofill is not supported when providing a token");return[4,this.api.authenticationOptions({token:null==t?void 0:t.token})];case 1:return[4,E((e=o.sent()).options,null==t?void 0:t.autofill)];case 2:return n=o.sent(),[4,this.api.verify({challengeId:e.challengeId,authenticationCredential:n,token:null==t?void 0:t.token})];case 3:return(null==(i=o.sent())?void 0:i.isVerified)&&this.storeCredentialAgainstDevice(n),[2,null==i?void 0:i.accessToken]}}))}))},t.prototype.isAvailableOnDevice=function(){return u(this,void 0,void 0,(function(){var t;return l(this,(function(e){switch(e.label){case 0:if(!(t=localStorage.getItem(this.passkeyLocalStorageKey)))return[2,!1];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,this.api.getPasskeyAuthenticator(t)];case 2:return e.sent(),[2,!0];case 3:return e.sent(),[2,!1];case 4:return[2]}}))}))},t.prototype.storeCredentialAgainstDevice=function(t){var e=t.id;"cross-platform"!==t.authenticatorAttachment&&localStorage.setItem(this.passkeyLocalStorageKey,e)},t}(),O=function(){function t(){this.windowRef=null}return t.prototype.show=function(t){var e=t.url,n=t.width,i=void 0===n?400:n,o=t.height,r=function(t){var e=t.url,n=t.width,i=t.height,o=t.win;if(!o.top)return null;var r=o.top.outerHeight/2+o.top.screenY-i/2,a=o.top.outerWidth/2+o.top.screenX-n/2;return window.open(e,"","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=".concat(n,", height=").concat(i,", top=").concat(r,", left=").concat(a))}({url:e,width:i,height:void 0===o?500:o,win:window});if(!r)throw new Error("Window is not initialized");return this.windowRef=r,r},t.prototype.close=function(){if(!this.windowRef)throw new Error("Window is not initialized");this.windowRef.close()},t}();var I=['a[href]:not([tabindex^="-"])','area[href]:not([tabindex^="-"])','input:not([type="hidden"]):not([type="radio"]):not([disabled]):not([tabindex^="-"])','input[type="radio"]:not([disabled]):not([tabindex^="-"])','select:not([disabled]):not([tabindex^="-"])','textarea:not([disabled]):not([tabindex^="-"])','button:not([disabled]):not([tabindex^="-"])','iframe:not([tabindex^="-"])','audio[controls]:not([tabindex^="-"])','video[controls]:not([tabindex^="-"])','[contenteditable]:not([tabindex^="-"])','[tabindex]:not([tabindex^="-"])'];function S(t){this._show=this.show.bind(this),this._hide=this.hide.bind(this),this._maintainFocus=this._maintainFocus.bind(this),this._bindKeypress=this._bindKeypress.bind(this),this.$el=t,this.shown=!1,this._id=this.$el.getAttribute("data-a11y-dialog")||this.$el.id,this._previouslyFocused=null,this._listeners={},this.create()}function k(t,e){return n=(e||document).querySelectorAll(t),Array.prototype.slice.call(n);var n}function C(t){(t.querySelector("[autofocus]")||t).focus()}function P(){k("[data-a11y-dialog]").forEach((function(t){new S(t)}))}S.prototype.create=function(){this.$el.setAttribute("aria-hidden",!0),this.$el.setAttribute("aria-modal",!0),this.$el.setAttribute("tabindex",-1),this.$el.hasAttribute("role")||this.$el.setAttribute("role","dialog"),this._openers=k('[data-a11y-dialog-show="'+this._id+'"]'),this._openers.forEach(function(t){t.addEventListener("click",this._show)}.bind(this));const t=this.$el;return this._closers=k("[data-a11y-dialog-hide]",this.$el).filter((function(e){return e.closest('[aria-modal="true"], [data-a11y-dialog]')===t})).concat(k('[data-a11y-dialog-hide="'+this._id+'"]')),this._closers.forEach(function(t){t.addEventListener("click",this._hide)}.bind(this)),this._fire("create"),this},S.prototype.show=function(t){return this.shown||(this._previouslyFocused=document.activeElement,this.$el.removeAttribute("aria-hidden"),this.shown=!0,C(this.$el),document.body.addEventListener("focus",this._maintainFocus,!0),document.addEventListener("keydown",this._bindKeypress),this._fire("show",t)),this},S.prototype.hide=function(t){return this.shown?(this.shown=!1,this.$el.setAttribute("aria-hidden","true"),this._previouslyFocused&&this._previouslyFocused.focus&&this._previouslyFocused.focus(),document.body.removeEventListener("focus",this._maintainFocus,!0),document.removeEventListener("keydown",this._bindKeypress),this._fire("hide",t),this):this},S.prototype.destroy=function(){return this.hide(),this._openers.forEach(function(t){t.removeEventListener("click",this._show)}.bind(this)),this._closers.forEach(function(t){t.removeEventListener("click",this._hide)}.bind(this)),this._fire("destroy"),this._listeners={},this},S.prototype.on=function(t,e){return void 0===this._listeners[t]&&(this._listeners[t]=[]),this._listeners[t].push(e),this},S.prototype.off=function(t,e){var n=(this._listeners[t]||[]).indexOf(e);return n>-1&&this._listeners[t].splice(n,1),this},S.prototype._fire=function(t,e){var n=this._listeners[t]||[],i=new CustomEvent(t,{detail:e});this.$el.dispatchEvent(i),n.forEach(function(t){t(this.$el,e)}.bind(this))},S.prototype._bindKeypress=function(t){const e=document.activeElement;e&&e.closest('[aria-modal="true"]')!==this.$el||(this.shown&&"Escape"===t.key&&"alertdialog"!==this.$el.getAttribute("role")&&(t.preventDefault(),this.hide(t)),this.shown&&"Tab"===t.key&&function(t,e){var n=function(t){return k(I.join(","),t).filter((function(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)}))}(t),i=n.indexOf(document.activeElement);e.shiftKey&&0===i?(n[n.length-1].focus(),e.preventDefault()):e.shiftKey||i!==n.length-1||(n[0].focus(),e.preventDefault())}(this.$el,t))},S.prototype._maintainFocus=function(t){!this.shown||t.target.closest('[aria-modal="true"]')||t.target.closest("[data-a11y-dialog-ignore-focus-trap]")||C(this.$el)},"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",P):window.requestAnimationFrame?window.requestAnimationFrame(P):window.setTimeout(P,16));var x="__authsignal-popup-container",U="__authsignal-popup-content",T="__authsignal-popup-overlay",N="__authsignal-popup-style",D="__authsignal-popup-iframe",L="385px",K=function(){function t(t){var e=t.width;if(this.popup=null,document.querySelector("#".concat(x)))throw new Error("Multiple instances of Authsignal popup is not supported.");this.create({width:e})}return t.prototype.create=function(t){var e=this,n=t.width,i=void 0===n?L:n,o=i;CSS.supports("width",i)||(console.warn("Invalid CSS value for `popupOptions.width`. Using default value instead."),o=L);var r=document.createElement("div");r.setAttribute("id",x),r.setAttribute("aria-hidden","true");var a=document.createElement("div");a.setAttribute("id",T),a.setAttribute("data-a11y-dialog-hide","true");var s=document.createElement("div");s.setAttribute("id",U),document.body.appendChild(r);var c=document.createElement("style");c.setAttribute("id",N),c.textContent="\n #".concat(x,",\n #").concat(T," {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n\n #").concat(x," {\n z-index: 2147483647;\n display: flex;\n }\n\n #").concat(x,"[aria-hidden='true'] {\n display: none;\n }\n\n #").concat(T," {\n background-color: rgba(0, 0, 0, 0.18);\n }\n\n #").concat(U," {\n margin: auto;\n z-index: 2147483647;\n position: relative;\n background-color: transparent;\n border-radius: 8px;\n width: ").concat(o,";\n }\n\n #").concat(U," iframe {\n width: 1px;\n min-width: 100%;\n border-radius: inherit;\n max-height: 95vh;\n height: ").concat("384px",";\n }\n "),document.head.insertAdjacentElement("beforeend",c),r.appendChild(a),r.appendChild(s),this.popup=new S(r),this.popup.on("hide",(function(){e.destroy()}))},t.prototype.destroy=function(){var t=document.querySelector("#".concat(x)),e=document.querySelector("#".concat(N));t&&e&&(document.body.removeChild(t),document.head.removeChild(e)),window.removeEventListener("message",$)},t.prototype.show=function(t){var e,n=t.url;if(!this.popup)throw new Error("Popup is not initialized");var i=document.createElement("iframe");i.setAttribute("id",D),i.setAttribute("name","authsignal"),i.setAttribute("title","Authsignal multi-factor authentication"),i.setAttribute("src",n),i.setAttribute("frameborder","0"),i.setAttribute("allow","publickey-credentials-get *; publickey-credentials-create *; clipboard-write");var o=document.querySelector("#".concat(U));o&&o.appendChild(i),window.addEventListener("message",$),null===(e=this.popup)||void 0===e||e.show()},t.prototype.close=function(){if(!this.popup)throw new Error("Popup is not initialized");this.popup.hide()},t.prototype.on=function(t,e){if(!this.popup)throw new Error("Popup is not initialized");this.popup.on(t,e)},t}();function $(t){var e=document.querySelector("#".concat(D));e&&t.data.height&&(e.style.height=t.data.height+"px")}var H="4a08uqve",W=function(){function e(t){var e=t.cookieDomain,n=t.cookieName,i=void 0===n?"__as_aid":n,o=t.baseUrl,r=void 0===o?"https://api.authsignal.com/v1":o,c=t.tenantId;if(this.anonymousId="",this.profilingId="",this.cookieDomain="",this.anonymousIdCookieName="",this._token=void 0,this.cookieDomain=e||document.location.hostname.replace("www.",""),this.anonymousIdCookieName=i,!c)throw new Error("tenantId is required");this.passkey=new R({tenantId:c,baseUrl:r});var u,l=(u=this.anonymousIdCookieName)&&decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*"+encodeURIComponent(u).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1"))||null;l?this.anonymousId=l:(this.anonymousId=a(),s({name:this.anonymousIdCookieName,value:this.anonymousId,expire:1/0,domain:this.cookieDomain,secure:"http:"!==document.location.protocol}))}return e.prototype.launch=function(t,e){switch(null==e?void 0:e.mode){case"window":return this.launchWithWindow(t,e);case"popup":return this.launchWithPopup(t,e);default:this.launchWithRedirect(t)}},e.prototype.initAdvancedProfiling=function(t){var e=a();this.profilingId=e,s({name:"__as_pid",value:e,expire:1/0,domain:this.cookieDomain,secure:"http:"!==document.location.protocol});var n=t?"".concat(t,"/fp/tags.js?org_id=").concat(H,"&session_id=").concat(e):"https://h.online-metrix.net/fp/tags.js?org_id=".concat(H,"&session_id=").concat(e),i=document.createElement("script");i.src=n,i.async=!1,i.id="as_adv_profile",document.head.appendChild(i);var o=document.createElement("noscript");o.setAttribute("id","as_adv_profile_pixel"),o.setAttribute("aria-hidden","true");var r=document.createElement("iframe"),c=t?"".concat(t,"/fp/tags?org_id=").concat(H,"&session_id=").concat(e):"https://h.online-metrix.net/fp/tags?org_id=".concat(H,"&session_id=").concat(e);r.setAttribute("id","as_adv_profile_pixel"),r.setAttribute("src",c),r.setAttribute("style","width: 100px; height: 100px; border: 0; position: absolute; top: -5000px;"),o&&(o.appendChild(r),document.body.prepend(o))},e.prototype.launchWithRedirect=function(t){window.location.href=t},e.prototype.launchWithPopup=function(e,n){var i=this,o=n.popupOptions,r=new K({width:null==o?void 0:o.width}),a="".concat(e,"&mode=popup");return r.show({url:a}),new Promise((function(e){r.on("hide",(function(){e({token:i._token})})),window.addEventListener("message",(function(e){var n=null;try{n=JSON.parse(e.data)}catch(t){}(null==n?void 0:n.event)===t.AuthsignalWindowMessage.AUTHSIGNAL_CLOSE_POPUP&&(i._token=n.token,r.close())}),!1)}))},e.prototype.launchWithWindow=function(e,n){var i=this,o=n.windowOptions,r=new O,a="".concat(e,"&mode=popup");return r.show({url:a,width:null==o?void 0:o.width,height:null==o?void 0:o.height}),new Promise((function(e){window.addEventListener("message",(function(n){var o=null;try{o=JSON.parse(n.data)}catch(t){}(null==o?void 0:o.event)===t.AuthsignalWindowMessage.AUTHSIGNAL_CLOSE_POPUP&&(i._token=o.token,r.close(),e({token:i._token}))}),!1)}))},e}();return t.Authsignal=W,Object.defineProperty(t,"__esModule",{value:!0}),t}({});
package/dist/passkey.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { PasskeyApiClient } from "./api";
2
+ import { AuthenticatorAttachment } from "@simplewebauthn/types";
2
3
  declare type PasskeyOptions = {
3
4
  baseUrl: string;
4
5
  tenantId: string;
@@ -6,11 +7,13 @@ declare type PasskeyOptions = {
6
7
  declare type SignUpParams = {
7
8
  userName?: string;
8
9
  token: string;
10
+ authenticatorAttachment?: AuthenticatorAttachment | null;
9
11
  };
10
12
  export declare class Passkey {
11
13
  api: PasskeyApiClient;
14
+ private passkeyLocalStorageKey;
12
15
  constructor({ baseUrl, tenantId }: PasskeyOptions);
13
- signUp({ userName, token }: SignUpParams): Promise<string | undefined>;
16
+ signUp({ userName, token, authenticatorAttachment }: SignUpParams): Promise<string | undefined>;
14
17
  signIn(): Promise<string | undefined>;
15
18
  signIn(params?: {
16
19
  token: string;
@@ -18,5 +21,7 @@ export declare class Passkey {
18
21
  signIn(params?: {
19
22
  autofill: boolean;
20
23
  }): Promise<string | undefined>;
24
+ isAvailableOnDevice(): Promise<boolean>;
25
+ private storeCredentialAgainstDevice;
21
26
  }
22
27
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authsignal/browser",
3
- "version": "0.3.6",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -28,9 +28,9 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@fingerprintjs/fingerprintjs": "^3.3.6",
31
- "@simplewebauthn/browser": "^8.2.1",
31
+ "@simplewebauthn/browser": "^9.0.1",
32
+ "@simplewebauthn/types": "^9.0.1",
32
33
  "a11y-dialog": "^7.5.2",
33
- "ky": "^0.33.3",
34
34
  "uuid": "^9.0.0"
35
35
  },
36
36
  "devDependencies": {