@auth0/auth0-spa-js 2.2.0 → 2.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.
Files changed (45) hide show
  1. package/README.md +1 -1
  2. package/dist/auth0-spa-js.development.js +615 -17
  3. package/dist/auth0-spa-js.development.js.map +1 -1
  4. package/dist/auth0-spa-js.production.esm.js +1 -1
  5. package/dist/auth0-spa-js.production.esm.js.map +1 -1
  6. package/dist/auth0-spa-js.production.js +1 -1
  7. package/dist/auth0-spa-js.production.js.map +1 -1
  8. package/dist/auth0-spa-js.worker.development.js +10 -2
  9. package/dist/auth0-spa-js.worker.development.js.map +1 -1
  10. package/dist/auth0-spa-js.worker.production.js +1 -1
  11. package/dist/auth0-spa-js.worker.production.js.map +1 -1
  12. package/dist/lib/auth0-spa-js.cjs.js +656 -17
  13. package/dist/lib/auth0-spa-js.cjs.js.map +1 -1
  14. package/dist/typings/Auth0Client.d.ts +54 -4
  15. package/dist/typings/Auth0Client.utils.d.ts +1 -1
  16. package/dist/typings/TokenExchange.d.ts +3 -2
  17. package/dist/typings/api.d.ts +1 -1
  18. package/dist/typings/cache/shared.d.ts +1 -0
  19. package/dist/typings/dpop/dpop.d.ts +17 -0
  20. package/dist/typings/dpop/storage.d.ts +27 -0
  21. package/dist/typings/dpop/utils.d.ts +15 -0
  22. package/dist/typings/errors.d.ts +7 -0
  23. package/dist/typings/fetcher.d.ts +48 -0
  24. package/dist/typings/global.d.ts +21 -0
  25. package/dist/typings/http.d.ts +2 -1
  26. package/dist/typings/index.d.ts +2 -1
  27. package/dist/typings/utils.d.ts +6 -0
  28. package/dist/typings/version.d.ts +1 -1
  29. package/package.json +22 -19
  30. package/src/Auth0Client.ts +126 -11
  31. package/src/Auth0Client.utils.ts +4 -2
  32. package/src/TokenExchange.ts +3 -2
  33. package/src/api.ts +17 -3
  34. package/src/cache/shared.ts +1 -0
  35. package/src/dpop/dpop.ts +56 -0
  36. package/src/dpop/storage.ts +134 -0
  37. package/src/dpop/utils.ts +66 -0
  38. package/src/errors.ts +11 -0
  39. package/src/fetcher.ts +224 -0
  40. package/src/global.ts +23 -0
  41. package/src/http.ts +70 -5
  42. package/src/index.ts +4 -1
  43. package/src/utils.ts +15 -0
  44. package/src/version.ts +1 -1
  45. package/src/worker/token.worker.ts +11 -5
@@ -540,7 +540,7 @@
540
540
  exports.default = SuperTokensLock;
541
541
  }));
542
542
  var Lock = unwrapExports(browserTabsLock);
543
- var version = "2.2.0";
543
+ var version = "2.4.0";
544
544
  const DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS = 60;
545
545
  const DEFAULT_POPUP_CONFIG_OPTIONS = {
546
546
  timeoutInSeconds: DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS
@@ -612,6 +612,13 @@
612
612
  Object.setPrototypeOf(this, MissingRefreshTokenError.prototype);
613
613
  }
614
614
  }
615
+ class UseDpopNonceError extends GenericError {
616
+ constructor(newDpopNonce) {
617
+ super("use_dpop_nonce", "Server rejected DPoP proof: wrong nonce");
618
+ this.newDpopNonce = newDpopNonce;
619
+ Object.setPrototypeOf(this, UseDpopNonceError.prototype);
620
+ }
621
+ }
615
622
  function valueOrEmptyString(value, exclude = []) {
616
623
  return value && !exclude.includes(value) ? value : "";
617
624
  }
@@ -760,6 +767,319 @@
760
767
  }
761
768
  return parseInt(value, 10) || undefined;
762
769
  };
770
+ const fromEntries = iterable => [ ...iterable ].reduce(((obj, [key, val]) => {
771
+ obj[key] = val;
772
+ return obj;
773
+ }), {});
774
+ const encoder = new TextEncoder;
775
+ const decoder = new TextDecoder;
776
+ function buf(input) {
777
+ if (typeof input === "string") {
778
+ return encoder.encode(input);
779
+ }
780
+ return decoder.decode(input);
781
+ }
782
+ function checkRsaKeyAlgorithm(algorithm) {
783
+ if (typeof algorithm.modulusLength !== "number" || algorithm.modulusLength < 2048) {
784
+ throw new OperationProcessingError(`${algorithm.name} modulusLength must be at least 2048 bits`);
785
+ }
786
+ }
787
+ function subtleAlgorithm(key) {
788
+ switch (key.algorithm.name) {
789
+ case "ECDSA":
790
+ return {
791
+ name: key.algorithm.name,
792
+ hash: "SHA-256"
793
+ };
794
+
795
+ case "RSA-PSS":
796
+ checkRsaKeyAlgorithm(key.algorithm);
797
+ return {
798
+ name: key.algorithm.name,
799
+ saltLength: 256 >> 3
800
+ };
801
+
802
+ case "RSASSA-PKCS1-v1_5":
803
+ checkRsaKeyAlgorithm(key.algorithm);
804
+ return {
805
+ name: key.algorithm.name
806
+ };
807
+
808
+ case "Ed25519":
809
+ return {
810
+ name: key.algorithm.name
811
+ };
812
+ }
813
+ throw new UnsupportedOperationError;
814
+ }
815
+ async function jwt(header, claimsSet, key) {
816
+ if (key.usages.includes("sign") === false) {
817
+ throw new TypeError('private CryptoKey instances used for signing assertions must include "sign" in their "usages"');
818
+ }
819
+ const input = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(claimsSet)))}`;
820
+ const signature = b64u(await crypto.subtle.sign(subtleAlgorithm(key), key, buf(input)));
821
+ return `${input}.${signature}`;
822
+ }
823
+ let encodeBase64Url;
824
+ if (Uint8Array.prototype.toBase64) {
825
+ encodeBase64Url = input => {
826
+ if (input instanceof ArrayBuffer) {
827
+ input = new Uint8Array(input);
828
+ }
829
+ return input.toBase64({
830
+ alphabet: "base64url",
831
+ omitPadding: true
832
+ });
833
+ };
834
+ } else {
835
+ const CHUNK_SIZE = 32768;
836
+ encodeBase64Url = input => {
837
+ if (input instanceof ArrayBuffer) {
838
+ input = new Uint8Array(input);
839
+ }
840
+ const arr = [];
841
+ for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) {
842
+ arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
843
+ }
844
+ return btoa(arr.join("")).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
845
+ };
846
+ }
847
+ function b64u(input) {
848
+ return encodeBase64Url(input);
849
+ }
850
+ class UnsupportedOperationError extends Error {
851
+ constructor(message) {
852
+ var _a;
853
+ super(message !== null && message !== void 0 ? message : "operation not supported");
854
+ this.name = this.constructor.name;
855
+ (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor);
856
+ }
857
+ }
858
+ class OperationProcessingError extends Error {
859
+ constructor(message) {
860
+ var _a;
861
+ super(message);
862
+ this.name = this.constructor.name;
863
+ (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor);
864
+ }
865
+ }
866
+ function psAlg(key) {
867
+ switch (key.algorithm.hash.name) {
868
+ case "SHA-256":
869
+ return "PS256";
870
+
871
+ default:
872
+ throw new UnsupportedOperationError("unsupported RsaHashedKeyAlgorithm hash name");
873
+ }
874
+ }
875
+ function rsAlg(key) {
876
+ switch (key.algorithm.hash.name) {
877
+ case "SHA-256":
878
+ return "RS256";
879
+
880
+ default:
881
+ throw new UnsupportedOperationError("unsupported RsaHashedKeyAlgorithm hash name");
882
+ }
883
+ }
884
+ function esAlg(key) {
885
+ switch (key.algorithm.namedCurve) {
886
+ case "P-256":
887
+ return "ES256";
888
+
889
+ default:
890
+ throw new UnsupportedOperationError("unsupported EcKeyAlgorithm namedCurve");
891
+ }
892
+ }
893
+ function determineJWSAlgorithm(key) {
894
+ switch (key.algorithm.name) {
895
+ case "RSA-PSS":
896
+ return psAlg(key);
897
+
898
+ case "RSASSA-PKCS1-v1_5":
899
+ return rsAlg(key);
900
+
901
+ case "ECDSA":
902
+ return esAlg(key);
903
+
904
+ case "Ed25519":
905
+ return "Ed25519";
906
+
907
+ default:
908
+ throw new UnsupportedOperationError("unsupported CryptoKey algorithm name");
909
+ }
910
+ }
911
+ function isCryptoKey(key) {
912
+ return key instanceof CryptoKey;
913
+ }
914
+ function isPrivateKey(key) {
915
+ return isCryptoKey(key) && key.type === "private";
916
+ }
917
+ function isPublicKey(key) {
918
+ return isCryptoKey(key) && key.type === "public";
919
+ }
920
+ function epochTime() {
921
+ return Math.floor(Date.now() / 1e3);
922
+ }
923
+ async function generateProof$1(keypair, htu, htm, nonce, accessToken, additional) {
924
+ const privateKey = keypair === null || keypair === void 0 ? void 0 : keypair.privateKey;
925
+ const publicKey = keypair === null || keypair === void 0 ? void 0 : keypair.publicKey;
926
+ if (!isPrivateKey(privateKey)) {
927
+ throw new TypeError('"keypair.privateKey" must be a private CryptoKey');
928
+ }
929
+ if (!isPublicKey(publicKey)) {
930
+ throw new TypeError('"keypair.publicKey" must be a public CryptoKey');
931
+ }
932
+ if (publicKey.extractable !== true) {
933
+ throw new TypeError('"keypair.publicKey.extractable" must be true');
934
+ }
935
+ if (typeof htu !== "string") {
936
+ throw new TypeError('"htu" must be a string');
937
+ }
938
+ if (typeof htm !== "string") {
939
+ throw new TypeError('"htm" must be a string');
940
+ }
941
+ if (nonce !== undefined && typeof nonce !== "string") {
942
+ throw new TypeError('"nonce" must be a string or undefined');
943
+ }
944
+ if (accessToken !== undefined && typeof accessToken !== "string") {
945
+ throw new TypeError('"accessToken" must be a string or undefined');
946
+ }
947
+ if (additional !== undefined && (typeof additional !== "object" || additional === null || Array.isArray(additional))) {
948
+ throw new TypeError('"additional" must be an object');
949
+ }
950
+ return jwt({
951
+ alg: determineJWSAlgorithm(privateKey),
952
+ typ: "dpop+jwt",
953
+ jwk: await publicJwk(publicKey)
954
+ }, Object.assign(Object.assign({}, additional), {
955
+ iat: epochTime(),
956
+ jti: crypto.randomUUID(),
957
+ htm: htm,
958
+ nonce: nonce,
959
+ htu: htu,
960
+ ath: accessToken ? b64u(await crypto.subtle.digest("SHA-256", buf(accessToken))) : undefined
961
+ }), privateKey);
962
+ }
963
+ async function publicJwk(key) {
964
+ const {kty: kty, e: e, n: n, x: x, y: y, crv: crv} = await crypto.subtle.exportKey("jwk", key);
965
+ return {
966
+ kty: kty,
967
+ crv: crv,
968
+ e: e,
969
+ n: n,
970
+ x: x,
971
+ y: y
972
+ };
973
+ }
974
+ async function generateKeyPair$1(alg, options) {
975
+ var _a;
976
+ let algorithm;
977
+ if (typeof alg !== "string" || alg.length === 0) {
978
+ throw new TypeError('"alg" must be a non-empty string');
979
+ }
980
+ switch (alg) {
981
+ case "PS256":
982
+ algorithm = {
983
+ name: "RSA-PSS",
984
+ hash: "SHA-256",
985
+ modulusLength: 2048,
986
+ publicExponent: new Uint8Array([ 1, 0, 1 ])
987
+ };
988
+ break;
989
+
990
+ case "RS256":
991
+ algorithm = {
992
+ name: "RSASSA-PKCS1-v1_5",
993
+ hash: "SHA-256",
994
+ modulusLength: 2048,
995
+ publicExponent: new Uint8Array([ 1, 0, 1 ])
996
+ };
997
+ break;
998
+
999
+ case "ES256":
1000
+ algorithm = {
1001
+ name: "ECDSA",
1002
+ namedCurve: "P-256"
1003
+ };
1004
+ break;
1005
+
1006
+ case "Ed25519":
1007
+ algorithm = {
1008
+ name: "Ed25519"
1009
+ };
1010
+ break;
1011
+
1012
+ default:
1013
+ throw new UnsupportedOperationError;
1014
+ }
1015
+ return crypto.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, [ "sign", "verify" ]);
1016
+ }
1017
+ async function calculateThumbprint$1(publicKey) {
1018
+ if (!isPublicKey(publicKey)) {
1019
+ throw new TypeError('"publicKey" must be a public CryptoKey');
1020
+ }
1021
+ if (publicKey.extractable !== true) {
1022
+ throw new TypeError('"publicKey.extractable" must be true');
1023
+ }
1024
+ const jwk = await publicJwk(publicKey);
1025
+ let components;
1026
+ switch (jwk.kty) {
1027
+ case "EC":
1028
+ components = {
1029
+ crv: jwk.crv,
1030
+ kty: jwk.kty,
1031
+ x: jwk.x,
1032
+ y: jwk.y
1033
+ };
1034
+ break;
1035
+
1036
+ case "OKP":
1037
+ components = {
1038
+ crv: jwk.crv,
1039
+ kty: jwk.kty,
1040
+ x: jwk.x
1041
+ };
1042
+ break;
1043
+
1044
+ case "RSA":
1045
+ components = {
1046
+ e: jwk.e,
1047
+ kty: jwk.kty,
1048
+ n: jwk.n
1049
+ };
1050
+ break;
1051
+
1052
+ default:
1053
+ throw new UnsupportedOperationError("unsupported JWK kty");
1054
+ }
1055
+ return b64u(await crypto.subtle.digest({
1056
+ name: "SHA-256"
1057
+ }, buf(JSON.stringify(components))));
1058
+ }
1059
+ const DPOP_NONCE_HEADER = "dpop-nonce";
1060
+ const KEY_PAIR_ALGORITHM = "ES256";
1061
+ const SUPPORTED_GRANT_TYPES = [ "authorization_code", "refresh_token", "urn:ietf:params:oauth:grant-type:token-exchange" ];
1062
+ function generateKeyPair() {
1063
+ return generateKeyPair$1(KEY_PAIR_ALGORITHM, {
1064
+ extractable: false
1065
+ });
1066
+ }
1067
+ function calculateThumbprint(keyPair) {
1068
+ return calculateThumbprint$1(keyPair.publicKey);
1069
+ }
1070
+ function normalizeUrl(url) {
1071
+ const parsedUrl = new URL(url);
1072
+ parsedUrl.search = "";
1073
+ parsedUrl.hash = "";
1074
+ return parsedUrl.href;
1075
+ }
1076
+ function generateProof({keyPair: keyPair, url: url, method: method, nonce: nonce, accessToken: accessToken}) {
1077
+ const normalizedUrl = normalizeUrl(url);
1078
+ return generateProof$1(keyPair, normalizedUrl, method, nonce, accessToken);
1079
+ }
1080
+ function isGrantTypeSupported(grantType) {
1081
+ return SUPPORTED_GRANT_TYPES.includes(grantType);
1082
+ }
763
1083
  const sendMessage = (message, to) => new Promise((function(resolve, reject) {
764
1084
  const messageChannel = new MessageChannel;
765
1085
  messageChannel.port1.onmessage = function(event) {
@@ -777,7 +1097,8 @@
777
1097
  const response = await fetch(fetchUrl, fetchOptions);
778
1098
  return {
779
1099
  ok: response.ok,
780
- json: await response.json()
1100
+ json: await response.json(),
1101
+ headers: fromEntries(response.headers)
781
1102
  };
782
1103
  };
783
1104
  const fetchWithoutWorker = async (fetchUrl, fetchOptions, timeout) => {
@@ -810,7 +1131,17 @@
810
1131
  return fetchWithoutWorker(fetchUrl, fetchOptions, timeout);
811
1132
  }
812
1133
  };
813
- async function getJSON(url, timeout, audience, scope, options, worker, useFormData) {
1134
+ async function getJSON(url, timeout, audience, scope, options, worker, useFormData, dpop, isDpopRetry) {
1135
+ if (dpop) {
1136
+ const dpopProof = await dpop.generateProof({
1137
+ url: url,
1138
+ method: options.method || "GET",
1139
+ nonce: await dpop.getNonce()
1140
+ });
1141
+ options.headers = Object.assign(Object.assign({}, options.headers), {
1142
+ dpop: dpopProof
1143
+ });
1144
+ }
814
1145
  let fetchError = null;
815
1146
  let response;
816
1147
  for (let i = 0; i < DEFAULT_SILENT_TOKEN_RETRY_COUNT; i++) {
@@ -825,7 +1156,14 @@
825
1156
  if (fetchError) {
826
1157
  throw fetchError;
827
1158
  }
828
- const _a = response.json, {error: error, error_description: error_description} = _a, data = __rest(_a, [ "error", "error_description" ]), {ok: ok} = response;
1159
+ const _a = response.json, {error: error, error_description: error_description} = _a, data = __rest(_a, [ "error", "error_description" ]), {headers: headers, ok: ok} = response;
1160
+ let newDpopNonce;
1161
+ if (dpop) {
1162
+ newDpopNonce = headers[DPOP_NONCE_HEADER];
1163
+ if (newDpopNonce) {
1164
+ await dpop.setNonce(newDpopNonce);
1165
+ }
1166
+ }
829
1167
  if (!ok) {
830
1168
  const errorMessage = error_description || `HTTP error. Unable to fetch ${url}`;
831
1169
  if (error === "mfa_required") {
@@ -834,13 +1172,26 @@
834
1172
  if (error === "missing_refresh_token") {
835
1173
  throw new MissingRefreshTokenError(audience, scope);
836
1174
  }
1175
+ if (error === "use_dpop_nonce") {
1176
+ if (!dpop || !newDpopNonce || isDpopRetry) {
1177
+ throw new UseDpopNonceError(newDpopNonce);
1178
+ }
1179
+ return getJSON(url, timeout, audience, scope, options, worker, useFormData, dpop, true);
1180
+ }
837
1181
  throw new GenericError(error || "request_error", errorMessage);
838
1182
  }
839
1183
  return data;
840
1184
  }
841
1185
  async function oauthToken(_a, worker) {
842
- var {baseUrl: baseUrl, timeout: timeout, audience: audience, scope: scope, auth0Client: auth0Client, useFormData: useFormData} = _a, options = __rest(_a, [ "baseUrl", "timeout", "audience", "scope", "auth0Client", "useFormData" ]);
843
- const body = useFormData ? createQueryParams(options) : JSON.stringify(options);
1186
+ var {baseUrl: baseUrl, timeout: timeout, audience: audience, scope: scope, auth0Client: auth0Client, useFormData: useFormData, dpop: dpop} = _a, options = __rest(_a, [ "baseUrl", "timeout", "audience", "scope", "auth0Client", "useFormData", "dpop" ]);
1187
+ const isTokenExchange = options.grant_type === "urn:ietf:params:oauth:grant-type:token-exchange";
1188
+ const allParams = Object.assign(Object.assign(Object.assign({}, options), isTokenExchange && audience && {
1189
+ audience: audience
1190
+ }), isTokenExchange && scope && {
1191
+ scope: scope
1192
+ });
1193
+ const body = useFormData ? createQueryParams(allParams) : JSON.stringify(allParams);
1194
+ const isDpopSupported = isGrantTypeSupported(options.grant_type);
844
1195
  return await getJSON(`${baseUrl}/oauth/token`, timeout, audience || "default", scope, {
845
1196
  method: "POST",
846
1197
  body: body,
@@ -848,7 +1199,7 @@
848
1199
  "Content-Type": useFormData ? "application/x-www-form-urlencoded" : "application/json",
849
1200
  "Auth0-Client": btoa(JSON.stringify(auth0Client || DEFAULT_AUTH0_CLIENT))
850
1201
  }
851
- }, worker, useFormData);
1202
+ }, worker, useFormData, isDpopSupported ? dpop : undefined);
852
1203
  }
853
1204
  const dedupe = arr => Array.from(new Set(arr));
854
1205
  const getUniqueScopes = (...scopes) => dedupe(scopes.filter(Boolean).join(" ").trim().split(/\s+/)).join(" ");
@@ -1390,7 +1741,7 @@
1390
1741
  return new Worker(url, options);
1391
1742
  };
1392
1743
  }
1393
- var WorkerFactory = createBase64WorkerFactory("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24oKSB7CiAgICAidXNlIHN0cmljdCI7CiAgICBjbGFzcyBHZW5lcmljRXJyb3IgZXh0ZW5kcyBFcnJvciB7CiAgICAgICAgY29uc3RydWN0b3IoZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uKSB7CiAgICAgICAgICAgIHN1cGVyKGVycm9yX2Rlc2NyaXB0aW9uKTsKICAgICAgICAgICAgdGhpcy5lcnJvciA9IGVycm9yOwogICAgICAgICAgICB0aGlzLmVycm9yX2Rlc2NyaXB0aW9uID0gZXJyb3JfZGVzY3JpcHRpb247CiAgICAgICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBHZW5lcmljRXJyb3IucHJvdG90eXBlKTsKICAgICAgICB9CiAgICAgICAgc3RhdGljIGZyb21QYXlsb2FkKHtlcnJvcjogZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uOiBlcnJvcl9kZXNjcmlwdGlvbn0pIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBHZW5lcmljRXJyb3IoZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uKTsKICAgICAgICB9CiAgICB9CiAgICBjbGFzcyBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IgZXh0ZW5kcyBHZW5lcmljRXJyb3IgewogICAgICAgIGNvbnN0cnVjdG9yKGF1ZGllbmNlLCBzY29wZSkgewogICAgICAgICAgICBzdXBlcigibWlzc2luZ19yZWZyZXNoX3Rva2VuIiwgYE1pc3NpbmcgUmVmcmVzaCBUb2tlbiAoYXVkaWVuY2U6ICcke3ZhbHVlT3JFbXB0eVN0cmluZyhhdWRpZW5jZSwgWyAiZGVmYXVsdCIgXSl9Jywgc2NvcGU6ICcke3ZhbHVlT3JFbXB0eVN0cmluZyhzY29wZSl9JylgKTsKICAgICAgICAgICAgdGhpcy5hdWRpZW5jZSA9IGF1ZGllbmNlOwogICAgICAgICAgICB0aGlzLnNjb3BlID0gc2NvcGU7CiAgICAgICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IucHJvdG90eXBlKTsKICAgICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiB2YWx1ZU9yRW1wdHlTdHJpbmcodmFsdWUsIGV4Y2x1ZGUgPSBbXSkgewogICAgICAgIHJldHVybiB2YWx1ZSAmJiAhZXhjbHVkZS5pbmNsdWRlcyh2YWx1ZSkgPyB2YWx1ZSA6ICIiOwogICAgfQogICAgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHsKICAgICAgICB2YXIgdCA9IHt9OwogICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKSB0W3BdID0gc1twXTsKICAgICAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSAiZnVuY3Rpb24iKSBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSkgdFtwW2ldXSA9IHNbcFtpXV07CiAgICAgICAgfQogICAgICAgIHJldHVybiB0OwogICAgfQogICAgdHlwZW9mIFN1cHByZXNzZWRFcnJvciA9PT0gImZ1bmN0aW9uIiA/IFN1cHByZXNzZWRFcnJvciA6IGZ1bmN0aW9uKGVycm9yLCBzdXBwcmVzc2VkLCBtZXNzYWdlKSB7CiAgICAgICAgdmFyIGUgPSBuZXcgRXJyb3IobWVzc2FnZSk7CiAgICAgICAgcmV0dXJuIGUubmFtZSA9ICJTdXBwcmVzc2VkRXJyb3IiLCBlLmVycm9yID0gZXJyb3IsIGUuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGU7CiAgICB9OwogICAgY29uc3Qgc3RyaXBVbmRlZmluZWQgPSBwYXJhbXMgPT4gT2JqZWN0LmtleXMocGFyYW1zKS5maWx0ZXIoKGsgPT4gdHlwZW9mIHBhcmFtc1trXSAhPT0gInVuZGVmaW5lZCIpKS5yZWR1Y2UoKChhY2MsIGtleSkgPT4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBhY2MpLCB7CiAgICAgICAgW2tleV06IHBhcmFtc1trZXldCiAgICB9KSksIHt9KTsKICAgIGNvbnN0IGNyZWF0ZVF1ZXJ5UGFyYW1zID0gX2EgPT4gewogICAgICAgIHZhciB7Y2xpZW50SWQ6IGNsaWVudF9pZH0gPSBfYSwgcGFyYW1zID0gX19yZXN0KF9hLCBbICJjbGllbnRJZCIgXSk7CiAgICAgICAgcmV0dXJuIG5ldyBVUkxTZWFyY2hQYXJhbXMoc3RyaXBVbmRlZmluZWQoT2JqZWN0LmFzc2lnbih7CiAgICAgICAgICAgIGNsaWVudF9pZDogY2xpZW50X2lkCiAgICAgICAgfSwgcGFyYW1zKSkpLnRvU3RyaW5nKCk7CiAgICB9OwogICAgbGV0IHJlZnJlc2hUb2tlbnMgPSB7fTsKICAgIGNvbnN0IGNhY2hlS2V5ID0gKGF1ZGllbmNlLCBzY29wZSkgPT4gYCR7YXVkaWVuY2V9fCR7c2NvcGV9YDsKICAgIGNvbnN0IGdldFJlZnJlc2hUb2tlbiA9IChhdWRpZW5jZSwgc2NvcGUpID0+IHJlZnJlc2hUb2tlbnNbY2FjaGVLZXkoYXVkaWVuY2UsIHNjb3BlKV07CiAgICBjb25zdCBzZXRSZWZyZXNoVG9rZW4gPSAocmVmcmVzaFRva2VuLCBhdWRpZW5jZSwgc2NvcGUpID0+IHJlZnJlc2hUb2tlbnNbY2FjaGVLZXkoYXVkaWVuY2UsIHNjb3BlKV0gPSByZWZyZXNoVG9rZW47CiAgICBjb25zdCBkZWxldGVSZWZyZXNoVG9rZW4gPSAoYXVkaWVuY2UsIHNjb3BlKSA9PiBkZWxldGUgcmVmcmVzaFRva2Vuc1tjYWNoZUtleShhdWRpZW5jZSwgc2NvcGUpXTsKICAgIGNvbnN0IHdhaXQgPSB0aW1lID0+IG5ldyBQcm9taXNlKChyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgdGltZSkpKTsKICAgIGNvbnN0IGZvcm1EYXRhVG9PYmplY3QgPSBmb3JtRGF0YSA9PiB7CiAgICAgICAgY29uc3QgcXVlcnlQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKGZvcm1EYXRhKTsKICAgICAgICBjb25zdCBwYXJzZWRRdWVyeSA9IHt9OwogICAgICAgIHF1ZXJ5UGFyYW1zLmZvckVhY2goKCh2YWwsIGtleSkgPT4gewogICAgICAgICAgICBwYXJzZWRRdWVyeVtrZXldID0gdmFsOwogICAgICAgIH0pKTsKICAgICAgICByZXR1cm4gcGFyc2VkUXVlcnk7CiAgICB9OwogICAgY29uc3QgbWVzc2FnZUhhbmRsZXIgPSBhc3luYyAoe2RhdGE6IHt0aW1lb3V0OiB0aW1lb3V0LCBhdXRoOiBhdXRoLCBmZXRjaFVybDogZmV0Y2hVcmwsIGZldGNoT3B0aW9uczogZmV0Y2hPcHRpb25zLCB1c2VGb3JtRGF0YTogdXNlRm9ybURhdGF9LCBwb3J0czogW3BvcnRdfSkgPT4gewogICAgICAgIGxldCBqc29uOwogICAgICAgIGNvbnN0IHthdWRpZW5jZTogYXVkaWVuY2UsIHNjb3BlOiBzY29wZX0gPSBhdXRoIHx8IHt9OwogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGNvbnN0IGJvZHkgPSB1c2VGb3JtRGF0YSA/IGZvcm1EYXRhVG9PYmplY3QoZmV0Y2hPcHRpb25zLmJvZHkpIDogSlNPTi5wYXJzZShmZXRjaE9wdGlvbnMuYm9keSk7CiAgICAgICAgICAgIGlmICghYm9keS5yZWZyZXNoX3Rva2VuICYmIGJvZHkuZ3JhbnRfdHlwZSA9PT0gInJlZnJlc2hfdG9rZW4iKSB7CiAgICAgICAgICAgICAgICBjb25zdCByZWZyZXNoVG9rZW4gPSBnZXRSZWZyZXNoVG9rZW4oYXVkaWVuY2UsIHNjb3BlKTsKICAgICAgICAgICAgICAgIGlmICghcmVmcmVzaFRva2VuKSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE1pc3NpbmdSZWZyZXNoVG9rZW5FcnJvcihhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZmV0Y2hPcHRpb25zLmJvZHkgPSB1c2VGb3JtRGF0YSA/IGNyZWF0ZVF1ZXJ5UGFyYW1zKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgYm9keSksIHsKICAgICAgICAgICAgICAgICAgICByZWZyZXNoX3Rva2VuOiByZWZyZXNoVG9rZW4KICAgICAgICAgICAgICAgIH0pKSA6IEpTT04uc3RyaW5naWZ5KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgYm9keSksIHsKICAgICAgICAgICAgICAgICAgICByZWZyZXNoX3Rva2VuOiByZWZyZXNoVG9rZW4KICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgYWJvcnRDb250cm9sbGVyOwogICAgICAgICAgICBpZiAodHlwZW9mIEFib3J0Q29udHJvbGxlciA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgICAgYWJvcnRDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcjsKICAgICAgICAgICAgICAgIGZldGNoT3B0aW9ucy5zaWduYWwgPSBhYm9ydENvbnRyb2xsZXIuc2lnbmFsOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxldCByZXNwb25zZTsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gYXdhaXQgUHJvbWlzZS5yYWNlKFsgd2FpdCh0aW1lb3V0KSwgZmV0Y2goZmV0Y2hVcmwsIE9iamVjdC5hc3NpZ24oe30sIGZldGNoT3B0aW9ucykpIF0pOwogICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgcG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yLm1lc3NhZ2UKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICghcmVzcG9uc2UpIHsKICAgICAgICAgICAgICAgIGlmIChhYm9ydENvbnRyb2xsZXIpIGFib3J0Q29udHJvbGxlci5hYm9ydCgpOwogICAgICAgICAgICAgICAgcG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgZXJyb3I6ICJUaW1lb3V0IHdoZW4gZXhlY3V0aW5nICdmZXRjaCciCiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpOwogICAgICAgICAgICBpZiAoanNvbi5yZWZyZXNoX3Rva2VuKSB7CiAgICAgICAgICAgICAgICBzZXRSZWZyZXNoVG9rZW4oanNvbi5yZWZyZXNoX3Rva2VuLCBhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICAgICAgZGVsZXRlIGpzb24ucmVmcmVzaF90b2tlbjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGRlbGV0ZVJlZnJlc2hUb2tlbihhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgb2s6IHJlc3BvbnNlLm9rLAogICAgICAgICAgICAgICAganNvbjoganNvbgogICAgICAgICAgICB9KTsKICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICBwb3J0LnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgIG9rOiBmYWxzZSwKICAgICAgICAgICAgICAgIGpzb246IHsKICAgICAgICAgICAgICAgICAgICBlcnJvcjogZXJyb3IuZXJyb3IsCiAgICAgICAgICAgICAgICAgICAgZXJyb3JfZGVzY3JpcHRpb246IGVycm9yLm1lc3NhZ2UKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgfTsKICAgIHsKICAgICAgICBhZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgbWVzc2FnZUhhbmRsZXIpOwogICAgfQp9KSgpOwoK", null, false);
1744
+ var WorkerFactory = createBase64WorkerFactory("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24oKSB7CiAgICAidXNlIHN0cmljdCI7CiAgICBjbGFzcyBHZW5lcmljRXJyb3IgZXh0ZW5kcyBFcnJvciB7CiAgICAgICAgY29uc3RydWN0b3IoZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uKSB7CiAgICAgICAgICAgIHN1cGVyKGVycm9yX2Rlc2NyaXB0aW9uKTsKICAgICAgICAgICAgdGhpcy5lcnJvciA9IGVycm9yOwogICAgICAgICAgICB0aGlzLmVycm9yX2Rlc2NyaXB0aW9uID0gZXJyb3JfZGVzY3JpcHRpb247CiAgICAgICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBHZW5lcmljRXJyb3IucHJvdG90eXBlKTsKICAgICAgICB9CiAgICAgICAgc3RhdGljIGZyb21QYXlsb2FkKHtlcnJvcjogZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uOiBlcnJvcl9kZXNjcmlwdGlvbn0pIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBHZW5lcmljRXJyb3IoZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uKTsKICAgICAgICB9CiAgICB9CiAgICBjbGFzcyBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IgZXh0ZW5kcyBHZW5lcmljRXJyb3IgewogICAgICAgIGNvbnN0cnVjdG9yKGF1ZGllbmNlLCBzY29wZSkgewogICAgICAgICAgICBzdXBlcigibWlzc2luZ19yZWZyZXNoX3Rva2VuIiwgYE1pc3NpbmcgUmVmcmVzaCBUb2tlbiAoYXVkaWVuY2U6ICcke3ZhbHVlT3JFbXB0eVN0cmluZyhhdWRpZW5jZSwgWyAiZGVmYXVsdCIgXSl9Jywgc2NvcGU6ICcke3ZhbHVlT3JFbXB0eVN0cmluZyhzY29wZSl9JylgKTsKICAgICAgICAgICAgdGhpcy5hdWRpZW5jZSA9IGF1ZGllbmNlOwogICAgICAgICAgICB0aGlzLnNjb3BlID0gc2NvcGU7CiAgICAgICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IucHJvdG90eXBlKTsKICAgICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiB2YWx1ZU9yRW1wdHlTdHJpbmcodmFsdWUsIGV4Y2x1ZGUgPSBbXSkgewogICAgICAgIHJldHVybiB2YWx1ZSAmJiAhZXhjbHVkZS5pbmNsdWRlcyh2YWx1ZSkgPyB2YWx1ZSA6ICIiOwogICAgfQogICAgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHsKICAgICAgICB2YXIgdCA9IHt9OwogICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKSB0W3BdID0gc1twXTsKICAgICAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSAiZnVuY3Rpb24iKSBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSkgdFtwW2ldXSA9IHNbcFtpXV07CiAgICAgICAgfQogICAgICAgIHJldHVybiB0OwogICAgfQogICAgdHlwZW9mIFN1cHByZXNzZWRFcnJvciA9PT0gImZ1bmN0aW9uIiA/IFN1cHByZXNzZWRFcnJvciA6IGZ1bmN0aW9uKGVycm9yLCBzdXBwcmVzc2VkLCBtZXNzYWdlKSB7CiAgICAgICAgdmFyIGUgPSBuZXcgRXJyb3IobWVzc2FnZSk7CiAgICAgICAgcmV0dXJuIGUubmFtZSA9ICJTdXBwcmVzc2VkRXJyb3IiLCBlLmVycm9yID0gZXJyb3IsIGUuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGU7CiAgICB9OwogICAgY29uc3Qgc3RyaXBVbmRlZmluZWQgPSBwYXJhbXMgPT4gT2JqZWN0LmtleXMocGFyYW1zKS5maWx0ZXIoKGsgPT4gdHlwZW9mIHBhcmFtc1trXSAhPT0gInVuZGVmaW5lZCIpKS5yZWR1Y2UoKChhY2MsIGtleSkgPT4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBhY2MpLCB7CiAgICAgICAgW2tleV06IHBhcmFtc1trZXldCiAgICB9KSksIHt9KTsKICAgIGNvbnN0IGNyZWF0ZVF1ZXJ5UGFyYW1zID0gX2EgPT4gewogICAgICAgIHZhciB7Y2xpZW50SWQ6IGNsaWVudF9pZH0gPSBfYSwgcGFyYW1zID0gX19yZXN0KF9hLCBbICJjbGllbnRJZCIgXSk7CiAgICAgICAgcmV0dXJuIG5ldyBVUkxTZWFyY2hQYXJhbXMoc3RyaXBVbmRlZmluZWQoT2JqZWN0LmFzc2lnbih7CiAgICAgICAgICAgIGNsaWVudF9pZDogY2xpZW50X2lkCiAgICAgICAgfSwgcGFyYW1zKSkpLnRvU3RyaW5nKCk7CiAgICB9OwogICAgY29uc3QgZnJvbUVudHJpZXMgPSBpdGVyYWJsZSA9PiBbIC4uLml0ZXJhYmxlIF0ucmVkdWNlKCgob2JqLCBba2V5LCB2YWxdKSA9PiB7CiAgICAgICAgb2JqW2tleV0gPSB2YWw7CiAgICAgICAgcmV0dXJuIG9iajsKICAgIH0pLCB7fSk7CiAgICBsZXQgcmVmcmVzaFRva2VucyA9IHt9OwogICAgY29uc3QgY2FjaGVLZXkgPSAoYXVkaWVuY2UsIHNjb3BlKSA9PiBgJHthdWRpZW5jZX18JHtzY29wZX1gOwogICAgY29uc3QgZ2V0UmVmcmVzaFRva2VuID0gKGF1ZGllbmNlLCBzY29wZSkgPT4gcmVmcmVzaFRva2Vuc1tjYWNoZUtleShhdWRpZW5jZSwgc2NvcGUpXTsKICAgIGNvbnN0IHNldFJlZnJlc2hUb2tlbiA9IChyZWZyZXNoVG9rZW4sIGF1ZGllbmNlLCBzY29wZSkgPT4gcmVmcmVzaFRva2Vuc1tjYWNoZUtleShhdWRpZW5jZSwgc2NvcGUpXSA9IHJlZnJlc2hUb2tlbjsKICAgIGNvbnN0IGRlbGV0ZVJlZnJlc2hUb2tlbiA9IChhdWRpZW5jZSwgc2NvcGUpID0+IGRlbGV0ZSByZWZyZXNoVG9rZW5zW2NhY2hlS2V5KGF1ZGllbmNlLCBzY29wZSldOwogICAgY29uc3Qgd2FpdCA9IHRpbWUgPT4gbmV3IFByb21pc2UoKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCB0aW1lKSkpOwogICAgY29uc3QgZm9ybURhdGFUb09iamVjdCA9IGZvcm1EYXRhID0+IHsKICAgICAgICBjb25zdCBxdWVyeVBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoZm9ybURhdGEpOwogICAgICAgIGNvbnN0IHBhcnNlZFF1ZXJ5ID0ge307CiAgICAgICAgcXVlcnlQYXJhbXMuZm9yRWFjaCgoKHZhbCwga2V5KSA9PiB7CiAgICAgICAgICAgIHBhcnNlZFF1ZXJ5W2tleV0gPSB2YWw7CiAgICAgICAgfSkpOwogICAgICAgIHJldHVybiBwYXJzZWRRdWVyeTsKICAgIH07CiAgICBjb25zdCBtZXNzYWdlSGFuZGxlciA9IGFzeW5jICh7ZGF0YToge3RpbWVvdXQ6IHRpbWVvdXQsIGF1dGg6IGF1dGgsIGZldGNoVXJsOiBmZXRjaFVybCwgZmV0Y2hPcHRpb25zOiBmZXRjaE9wdGlvbnMsIHVzZUZvcm1EYXRhOiB1c2VGb3JtRGF0YX0sIHBvcnRzOiBbcG9ydF19KSA9PiB7CiAgICAgICAgbGV0IGhlYWRlcnMgPSB7fTsKICAgICAgICBsZXQganNvbjsKICAgICAgICBjb25zdCB7YXVkaWVuY2U6IGF1ZGllbmNlLCBzY29wZTogc2NvcGV9ID0gYXV0aCB8fCB7fTsKICAgICAgICB0cnkgewogICAgICAgICAgICBjb25zdCBib2R5ID0gdXNlRm9ybURhdGEgPyBmb3JtRGF0YVRvT2JqZWN0KGZldGNoT3B0aW9ucy5ib2R5KSA6IEpTT04ucGFyc2UoZmV0Y2hPcHRpb25zLmJvZHkpOwogICAgICAgICAgICBpZiAoIWJvZHkucmVmcmVzaF90b2tlbiAmJiBib2R5LmdyYW50X3R5cGUgPT09ICJyZWZyZXNoX3Rva2VuIikgewogICAgICAgICAgICAgICAgY29uc3QgcmVmcmVzaFRva2VuID0gZ2V0UmVmcmVzaFRva2VuKGF1ZGllbmNlLCBzY29wZSk7CiAgICAgICAgICAgICAgICBpZiAoIXJlZnJlc2hUb2tlbikgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IoYXVkaWVuY2UsIHNjb3BlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZldGNoT3B0aW9ucy5ib2R5ID0gdXNlRm9ybURhdGEgPyBjcmVhdGVRdWVyeVBhcmFtcyhPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGJvZHkpLCB7CiAgICAgICAgICAgICAgICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuCiAgICAgICAgICAgICAgICB9KSkgOiBKU09OLnN0cmluZ2lmeShPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGJvZHkpLCB7CiAgICAgICAgICAgICAgICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGV0IGFib3J0Q29udHJvbGxlcjsKICAgICAgICAgICAgaWYgKHR5cGVvZiBBYm9ydENvbnRyb2xsZXIgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgICAgICAgIGFib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXI7CiAgICAgICAgICAgICAgICBmZXRjaE9wdGlvbnMuc2lnbmFsID0gYWJvcnRDb250cm9sbGVyLnNpZ25hbDsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgcmVzcG9uc2U7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICByZXNwb25zZSA9IGF3YWl0IFByb21pc2UucmFjZShbIHdhaXQodGltZW91dCksIGZldGNoKGZldGNoVXJsLCBPYmplY3QuYXNzaWduKHt9LCBmZXRjaE9wdGlvbnMpKSBdKTsKICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgIHBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgIGVycm9yOiBlcnJvci5tZXNzYWdlCiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIXJlc3BvbnNlKSB7CiAgICAgICAgICAgICAgICBpZiAoYWJvcnRDb250cm9sbGVyKSBhYm9ydENvbnRyb2xsZXIuYWJvcnQoKTsKICAgICAgICAgICAgICAgIHBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgIGVycm9yOiAiVGltZW91dCB3aGVuIGV4ZWN1dGluZyAnZmV0Y2gnIgogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaGVhZGVycyA9IGZyb21FbnRyaWVzKHJlc3BvbnNlLmhlYWRlcnMpOwogICAgICAgICAgICBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpOwogICAgICAgICAgICBpZiAoanNvbi5yZWZyZXNoX3Rva2VuKSB7CiAgICAgICAgICAgICAgICBzZXRSZWZyZXNoVG9rZW4oanNvbi5yZWZyZXNoX3Rva2VuLCBhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICAgICAgZGVsZXRlIGpzb24ucmVmcmVzaF90b2tlbjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGRlbGV0ZVJlZnJlc2hUb2tlbihhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgb2s6IHJlc3BvbnNlLm9rLAogICAgICAgICAgICAgICAganNvbjoganNvbiwKICAgICAgICAgICAgICAgIGhlYWRlcnM6IGhlYWRlcnMKICAgICAgICAgICAgfSk7CiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgcG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICBvazogZmFsc2UsCiAgICAgICAgICAgICAgICBqc29uOiB7CiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yLmVycm9yLAogICAgICAgICAgICAgICAgICAgIGVycm9yX2Rlc2NyaXB0aW9uOiBlcnJvci5tZXNzYWdlCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgaGVhZGVyczogaGVhZGVycwogICAgICAgICAgICB9KTsKICAgICAgICB9CiAgICB9OwogICAgewogICAgICAgIGFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCBtZXNzYWdlSGFuZGxlcik7CiAgICB9Cn0pKCk7Cgo=", null, false);
1394
1745
  const singlePromiseMap = {};
1395
1746
  const singlePromise = (cb, key) => {
1396
1747
  let promise = singlePromiseMap[key];
@@ -1457,7 +1808,7 @@
1457
1808
  localstorage: () => new LocalStorageCache
1458
1809
  };
1459
1810
  const cacheFactory = location => cacheLocationBuilders[location];
1460
- const getAuthorizeParams = (clientOptions, scope, authorizationParams, state, nonce, code_challenge, redirect_uri, response_mode) => Object.assign(Object.assign(Object.assign({
1811
+ const getAuthorizeParams = (clientOptions, scope, authorizationParams, state, nonce, code_challenge, redirect_uri, response_mode, thumbprint) => Object.assign(Object.assign(Object.assign({
1461
1812
  client_id: clientOptions.clientId
1462
1813
  }, clientOptions.authorizationParams), authorizationParams), {
1463
1814
  scope: getUniqueScopes(scope, authorizationParams.scope),
@@ -1467,7 +1818,8 @@
1467
1818
  nonce: nonce,
1468
1819
  redirect_uri: redirect_uri || clientOptions.authorizationParams.redirect_uri,
1469
1820
  code_challenge: code_challenge,
1470
- code_challenge_method: "S256"
1821
+ code_challenge_method: "S256",
1822
+ dpop_jkt: thumbprint
1471
1823
  });
1472
1824
  const patchOpenUrlWithOnRedirect = options => {
1473
1825
  const {openUrl: openUrl, onRedirect: onRedirect} = options, originalOptions = __rest(options, [ "openUrl", "onRedirect" ]);
@@ -1476,6 +1828,208 @@
1476
1828
  });
1477
1829
  return result;
1478
1830
  };
1831
+ const VERSION = 1;
1832
+ const NAME = "auth0-spa-js";
1833
+ const TABLES = {
1834
+ NONCE: "nonce",
1835
+ KEYPAIR: "keypair"
1836
+ };
1837
+ const AUTH0_NONCE_ID = "auth0";
1838
+ class DpopStorage {
1839
+ constructor(clientId) {
1840
+ this.clientId = clientId;
1841
+ }
1842
+ getVersion() {
1843
+ return VERSION;
1844
+ }
1845
+ createDbHandle() {
1846
+ const req = window.indexedDB.open(NAME, this.getVersion());
1847
+ return new Promise(((resolve, reject) => {
1848
+ req.onupgradeneeded = () => Object.values(TABLES).forEach((t => req.result.createObjectStore(t)));
1849
+ req.onerror = () => reject(req.error);
1850
+ req.onsuccess = () => resolve(req.result);
1851
+ }));
1852
+ }
1853
+ async getDbHandle() {
1854
+ if (!this.dbHandle) {
1855
+ this.dbHandle = await this.createDbHandle();
1856
+ }
1857
+ return this.dbHandle;
1858
+ }
1859
+ async executeDbRequest(table, mode, requestFactory) {
1860
+ const db = await this.getDbHandle();
1861
+ const txn = db.transaction(table, mode);
1862
+ const store = txn.objectStore(table);
1863
+ const request = requestFactory(store);
1864
+ return new Promise(((resolve, reject) => {
1865
+ request.onsuccess = () => resolve(request.result);
1866
+ request.onerror = () => reject(request.error);
1867
+ }));
1868
+ }
1869
+ buildKey(id) {
1870
+ const finalId = id ? `_${id}` : AUTH0_NONCE_ID;
1871
+ return `${this.clientId}::${finalId}`;
1872
+ }
1873
+ setNonce(nonce, id) {
1874
+ return this.save(TABLES.NONCE, this.buildKey(id), nonce);
1875
+ }
1876
+ setKeyPair(keyPair) {
1877
+ return this.save(TABLES.KEYPAIR, this.buildKey(), keyPair);
1878
+ }
1879
+ async save(table, key, obj) {
1880
+ return void await this.executeDbRequest(table, "readwrite", (table => table.put(obj, key)));
1881
+ }
1882
+ findNonce(id) {
1883
+ return this.find(TABLES.NONCE, this.buildKey(id));
1884
+ }
1885
+ findKeyPair() {
1886
+ return this.find(TABLES.KEYPAIR, this.buildKey());
1887
+ }
1888
+ find(table, key) {
1889
+ return this.executeDbRequest(table, "readonly", (table => table.get(key)));
1890
+ }
1891
+ async deleteBy(table, predicate) {
1892
+ const allKeys = await this.executeDbRequest(table, "readonly", (table => table.getAllKeys()));
1893
+ allKeys === null || allKeys === void 0 ? void 0 : allKeys.filter(predicate).map((k => this.executeDbRequest(table, "readwrite", (table => table.delete(k)))));
1894
+ }
1895
+ deleteByClientId(table, clientId) {
1896
+ return this.deleteBy(table, (k => typeof k === "string" && k.startsWith(`${clientId}::`)));
1897
+ }
1898
+ clearNonces() {
1899
+ return this.deleteByClientId(TABLES.NONCE, this.clientId);
1900
+ }
1901
+ clearKeyPairs() {
1902
+ return this.deleteByClientId(TABLES.KEYPAIR, this.clientId);
1903
+ }
1904
+ }
1905
+ class Dpop {
1906
+ constructor(clientId) {
1907
+ this.storage = new DpopStorage(clientId);
1908
+ }
1909
+ getNonce(id) {
1910
+ return this.storage.findNonce(id);
1911
+ }
1912
+ setNonce(nonce, id) {
1913
+ return this.storage.setNonce(nonce, id);
1914
+ }
1915
+ async getOrGenerateKeyPair() {
1916
+ let keyPair = await this.storage.findKeyPair();
1917
+ if (!keyPair) {
1918
+ keyPair = await generateKeyPair();
1919
+ await this.storage.setKeyPair(keyPair);
1920
+ }
1921
+ return keyPair;
1922
+ }
1923
+ async generateProof(params) {
1924
+ const keyPair = await this.getOrGenerateKeyPair();
1925
+ return generateProof(Object.assign({
1926
+ keyPair: keyPair
1927
+ }, params));
1928
+ }
1929
+ async calculateThumbprint() {
1930
+ const keyPair = await this.getOrGenerateKeyPair();
1931
+ return calculateThumbprint(keyPair);
1932
+ }
1933
+ async clear() {
1934
+ await Promise.all([ this.storage.clearNonces(), this.storage.clearKeyPairs() ]);
1935
+ }
1936
+ }
1937
+ class Fetcher {
1938
+ constructor(config, hooks) {
1939
+ this.hooks = hooks;
1940
+ this.config = Object.assign(Object.assign({}, config), {
1941
+ fetch: config.fetch || (typeof window === "undefined" ? fetch : window.fetch.bind(window))
1942
+ });
1943
+ }
1944
+ isAbsoluteUrl(url) {
1945
+ return /^(https?:)?\/\//i.test(url);
1946
+ }
1947
+ buildUrl(baseUrl, url) {
1948
+ if (url) {
1949
+ if (this.isAbsoluteUrl(url)) {
1950
+ return url;
1951
+ }
1952
+ if (baseUrl) {
1953
+ return `${baseUrl.replace(/\/?\/$/, "")}/${url.replace(/^\/+/, "")}`;
1954
+ }
1955
+ }
1956
+ throw new TypeError("`url` must be absolute or `baseUrl` non-empty.");
1957
+ }
1958
+ getAccessToken() {
1959
+ return this.config.getAccessToken ? this.config.getAccessToken() : this.hooks.getAccessToken();
1960
+ }
1961
+ buildBaseRequest(info, init) {
1962
+ const request = new Request(info, init);
1963
+ if (!this.config.baseUrl) {
1964
+ return request;
1965
+ }
1966
+ return new Request(this.buildUrl(this.config.baseUrl, request.url), request);
1967
+ }
1968
+ async setAuthorizationHeader(request, accessToken) {
1969
+ request.headers.set("authorization", `${this.config.dpopNonceId ? "DPoP" : "Bearer"} ${accessToken}`);
1970
+ }
1971
+ async setDpopProofHeader(request, accessToken) {
1972
+ if (!this.config.dpopNonceId) {
1973
+ return;
1974
+ }
1975
+ const dpopNonce = await this.hooks.getDpopNonce();
1976
+ const dpopProof = await this.hooks.generateDpopProof({
1977
+ accessToken: accessToken,
1978
+ method: request.method,
1979
+ nonce: dpopNonce,
1980
+ url: request.url
1981
+ });
1982
+ request.headers.set("dpop", dpopProof);
1983
+ }
1984
+ async prepareRequest(request) {
1985
+ const accessToken = await this.getAccessToken();
1986
+ this.setAuthorizationHeader(request, accessToken);
1987
+ await this.setDpopProofHeader(request, accessToken);
1988
+ }
1989
+ getHeader(headers, name) {
1990
+ if (Array.isArray(headers)) {
1991
+ return new Headers(headers).get(name) || "";
1992
+ }
1993
+ if (typeof headers.get === "function") {
1994
+ return headers.get(name) || "";
1995
+ }
1996
+ return headers[name] || "";
1997
+ }
1998
+ hasUseDpopNonceError(response) {
1999
+ if (response.status !== 401) {
2000
+ return false;
2001
+ }
2002
+ const wwwAuthHeader = this.getHeader(response.headers, "www-authenticate");
2003
+ return wwwAuthHeader.includes("use_dpop_nonce");
2004
+ }
2005
+ async handleResponse(response, callbacks) {
2006
+ const newDpopNonce = this.getHeader(response.headers, DPOP_NONCE_HEADER);
2007
+ if (newDpopNonce) {
2008
+ await this.hooks.setDpopNonce(newDpopNonce);
2009
+ }
2010
+ if (!this.hasUseDpopNonceError(response)) {
2011
+ return response;
2012
+ }
2013
+ if (!newDpopNonce || !callbacks.onUseDpopNonceError) {
2014
+ throw new UseDpopNonceError(newDpopNonce);
2015
+ }
2016
+ return callbacks.onUseDpopNonceError();
2017
+ }
2018
+ async internalFetchWithAuth(info, init, callbacks) {
2019
+ const request = this.buildBaseRequest(info, init);
2020
+ await this.prepareRequest(request);
2021
+ const response = await this.config.fetch(request);
2022
+ return this.handleResponse(response, callbacks);
2023
+ }
2024
+ fetchWithAuth(info, init) {
2025
+ const callbacks = {
2026
+ onUseDpopNonceError: () => this.internalFetchWithAuth(info, init, Object.assign(Object.assign({}, callbacks), {
2027
+ onUseDpopNonceError: undefined
2028
+ }))
2029
+ };
2030
+ return this.internalFetchWithAuth(info, init, callbacks);
2031
+ }
2032
+ }
1479
2033
  const lock = new Lock;
1480
2034
  class Auth0Client {
1481
2035
  constructor(options) {
@@ -1519,6 +2073,7 @@
1519
2073
  this.transactionManager = new TransactionManager(transactionStorage, this.options.clientId, this.options.cookieDomain);
1520
2074
  this.nowProvider = this.options.nowProvider || DEFAULT_NOW_PROVIDER;
1521
2075
  this.cacheManager = new CacheManager(cache, !cache.allKeys ? new CacheKeyManifest(cache, this.options.clientId) : undefined, this.nowProvider);
2076
+ this.dpop = this.options.useDpop ? new Dpop(this.options.clientId) : undefined;
1522
2077
  this.domainUrl = getDomain(this.options.domain);
1523
2078
  this.tokenIssuer = getTokenIssuer(this.options.issuer, this.domainUrl);
1524
2079
  if (typeof window !== "undefined" && window.Worker && this.options.useRefreshTokens && cacheLocation === CACHE_LOCATION_MEMORY) {
@@ -1562,12 +2117,14 @@
1562
2117
  }
1563
2118
  }
1564
2119
  async _prepareAuthorizeUrl(authorizationParams, authorizeOptions, fallbackRedirectUri) {
2120
+ var _a;
1565
2121
  const state = encode(createRandomString());
1566
2122
  const nonce = encode(createRandomString());
1567
2123
  const code_verifier = createRandomString();
1568
2124
  const code_challengeBuffer = await sha256(code_verifier);
1569
2125
  const code_challenge = bufferToBase64UrlEncoded(code_challengeBuffer);
1570
- const params = getAuthorizeParams(this.options, this.scope, authorizationParams, state, nonce, code_challenge, authorizationParams.redirect_uri || this.options.authorizationParams.redirect_uri || fallbackRedirectUri, authorizeOptions === null || authorizeOptions === void 0 ? void 0 : authorizeOptions.response_mode);
2126
+ const thumbprint = await ((_a = this.dpop) === null || _a === void 0 ? void 0 : _a.calculateThumbprint());
2127
+ const params = getAuthorizeParams(this.options, this.scope, authorizationParams, state, nonce, code_challenge, authorizationParams.redirect_uri || this.options.authorizationParams.redirect_uri || fallbackRedirectUri, authorizeOptions === null || authorizeOptions === void 0 ? void 0 : authorizeOptions.response_mode, thumbprint);
1571
2128
  const url = this._authorizeUrl(params);
1572
2129
  return {
1573
2130
  nonce: nonce,
@@ -1732,9 +2289,10 @@
1732
2289
  }
1733
2290
  }
1734
2291
  const authResult = this.options.useRefreshTokens ? await this._getTokenUsingRefreshToken(getTokenOptions) : await this._getTokenFromIFrame(getTokenOptions);
1735
- const {id_token: id_token, access_token: access_token, oauthTokenScope: oauthTokenScope, expires_in: expires_in} = authResult;
2292
+ const {id_token: id_token, token_type: token_type, access_token: access_token, oauthTokenScope: oauthTokenScope, expires_in: expires_in} = authResult;
1736
2293
  return Object.assign(Object.assign({
1737
2294
  id_token: id_token,
2295
+ token_type: token_type,
1738
2296
  access_token: access_token
1739
2297
  }, oauthTokenScope ? {
1740
2298
  scope: oauthTokenScope
@@ -1783,7 +2341,8 @@
1783
2341
  return url + federatedQuery;
1784
2342
  }
1785
2343
  async logout(options = {}) {
1786
- const _a = patchOpenUrlWithOnRedirect(options), {openUrl: openUrl} = _a, logoutOptions = __rest(_a, [ "openUrl" ]);
2344
+ var _a;
2345
+ const _b = patchOpenUrlWithOnRedirect(options), {openUrl: openUrl} = _b, logoutOptions = __rest(_b, [ "openUrl" ]);
1787
2346
  if (options.clientId === null) {
1788
2347
  await this.cacheManager.clear();
1789
2348
  } else {
@@ -1796,6 +2355,7 @@
1796
2355
  cookieDomain: this.options.cookieDomain
1797
2356
  });
1798
2357
  this.userCache.remove(CACHE_KEY_ID_TOKEN_SUFFIX);
2358
+ await ((_a = this.dpop) === null || _a === void 0 ? void 0 : _a.clear());
1799
2359
  const url = this._buildLogoutUrl(logoutOptions);
1800
2360
  if (openUrl) {
1801
2361
  await openUrl(url);
@@ -1819,7 +2379,13 @@
1819
2379
  throw new GenericError("login_required", "The application is running in a Cross-Origin Isolated context, silently retrieving a token without refresh token is not possible.");
1820
2380
  }
1821
2381
  const authorizeTimeout = options.timeoutInSeconds || this.options.authorizeTimeoutInSeconds;
1822
- const codeResult = await runIframe(url, this.domainUrl, authorizeTimeout);
2382
+ let eventOrigin;
2383
+ try {
2384
+ eventOrigin = new URL(this.domainUrl).origin;
2385
+ } catch (_a) {
2386
+ eventOrigin = this.domainUrl;
2387
+ }
2388
+ const codeResult = await runIframe(url, eventOrigin, authorizeTimeout);
1823
2389
  if (stateIn !== codeResult.state) {
1824
2390
  throw new GenericError("state_mismatch", "Invalid state");
1825
2391
  }
@@ -1911,10 +2477,11 @@
1911
2477
  clientId: clientId
1912
2478
  }), 60);
1913
2479
  if (entry && entry.access_token) {
1914
- const {access_token: access_token, oauthTokenScope: oauthTokenScope, expires_in: expires_in} = entry;
2480
+ const {token_type: token_type, access_token: access_token, oauthTokenScope: oauthTokenScope, expires_in: expires_in} = entry;
1915
2481
  const cache = await this._getIdTokenFromCache();
1916
2482
  return cache && Object.assign(Object.assign({
1917
2483
  id_token: cache.id_token,
2484
+ token_type: token_type ? token_type : "Bearer",
1918
2485
  access_token: access_token
1919
2486
  }, oauthTokenScope ? {
1920
2487
  scope: oauthTokenScope
@@ -1930,7 +2497,8 @@
1930
2497
  client_id: this.options.clientId,
1931
2498
  auth0Client: this.options.auth0Client,
1932
2499
  useFormData: this.options.useFormData,
1933
- timeout: this.httpTimeoutMs
2500
+ timeout: this.httpTimeoutMs,
2501
+ dpop: this.dpop
1934
2502
  }, options), this.worker);
1935
2503
  const decodedToken = await this._verifyIdToken(authResult.id_token, nonceIn, organization);
1936
2504
  await this._saveEntryInCache(Object.assign(Object.assign(Object.assign(Object.assign({}, authResult), {
@@ -1957,7 +2525,36 @@
1957
2525
  subject_token: options.subject_token,
1958
2526
  subject_token_type: options.subject_token_type,
1959
2527
  scope: getUniqueScopes(options.scope, this.scope),
1960
- audience: this.options.authorizationParams.audience
2528
+ audience: options.audience || this.options.authorizationParams.audience
2529
+ });
2530
+ }
2531
+ _assertDpop(dpop) {
2532
+ if (!dpop) {
2533
+ throw new Error("`useDpop` option must be enabled before using DPoP.");
2534
+ }
2535
+ }
2536
+ getDpopNonce(id) {
2537
+ this._assertDpop(this.dpop);
2538
+ return this.dpop.getNonce(id);
2539
+ }
2540
+ setDpopNonce(nonce, id) {
2541
+ this._assertDpop(this.dpop);
2542
+ return this.dpop.setNonce(nonce, id);
2543
+ }
2544
+ generateDpopProof(params) {
2545
+ this._assertDpop(this.dpop);
2546
+ return this.dpop.generateProof(params);
2547
+ }
2548
+ createFetcher(config = {}) {
2549
+ if (this.options.useDpop && !config.dpopNonceId) {
2550
+ throw new TypeError("When `useDpop` is enabled, `dpopNonceId` must be set when calling `createFetcher()`.");
2551
+ }
2552
+ return new Fetcher(config, {
2553
+ isDpopEnabled: () => !!this.options.useDpop,
2554
+ getAccessToken: () => this.getTokenSilently(),
2555
+ getDpopNonce: () => this.getDpopNonce(config.dpopNonceId),
2556
+ setDpopNonce: nonce => this.setDpopNonce(nonce),
2557
+ generateDpopProof: params => this.generateDpopProof(params)
1961
2558
  });
1962
2559
  }
1963
2560
  }
@@ -1978,6 +2575,7 @@
1978
2575
  exports.PopupCancelledError = PopupCancelledError;
1979
2576
  exports.PopupTimeoutError = PopupTimeoutError;
1980
2577
  exports.TimeoutError = TimeoutError;
2578
+ exports.UseDpopNonceError = UseDpopNonceError;
1981
2579
  exports.User = User;
1982
2580
  exports.createAuth0Client = createAuth0Client;
1983
2581
  Object.defineProperty(exports, "__esModule", {