@auth0/auth0-spa-js 2.3.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 (43) hide show
  1. package/README.md +1 -1
  2. package/dist/auth0-spa-js.development.js +600 -14
  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 +641 -14
  13. package/dist/lib/auth0-spa-js.cjs.js.map +1 -1
  14. package/dist/typings/Auth0Client.d.ts +50 -0
  15. package/dist/typings/Auth0Client.utils.d.ts +1 -1
  16. package/dist/typings/api.d.ts +1 -1
  17. package/dist/typings/cache/shared.d.ts +1 -0
  18. package/dist/typings/dpop/dpop.d.ts +17 -0
  19. package/dist/typings/dpop/storage.d.ts +27 -0
  20. package/dist/typings/dpop/utils.d.ts +15 -0
  21. package/dist/typings/errors.d.ts +7 -0
  22. package/dist/typings/fetcher.d.ts +48 -0
  23. package/dist/typings/global.d.ts +19 -0
  24. package/dist/typings/http.d.ts +2 -1
  25. package/dist/typings/index.d.ts +2 -1
  26. package/dist/typings/utils.d.ts +6 -0
  27. package/dist/typings/version.d.ts +1 -1
  28. package/package.json +22 -19
  29. package/src/Auth0Client.ts +112 -5
  30. package/src/Auth0Client.utils.ts +4 -2
  31. package/src/api.ts +6 -1
  32. package/src/cache/shared.ts +1 -0
  33. package/src/dpop/dpop.ts +56 -0
  34. package/src/dpop/storage.ts +134 -0
  35. package/src/dpop/utils.ts +66 -0
  36. package/src/errors.ts +11 -0
  37. package/src/fetcher.ts +224 -0
  38. package/src/global.ts +21 -0
  39. package/src/http.ts +70 -5
  40. package/src/index.ts +4 -1
  41. package/src/utils.ts +15 -0
  42. package/src/version.ts +1 -1
  43. 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.3.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,12 +1172,18 @@
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" ]);
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" ]);
843
1187
  const isTokenExchange = options.grant_type === "urn:ietf:params:oauth:grant-type:token-exchange";
844
1188
  const allParams = Object.assign(Object.assign(Object.assign({}, options), isTokenExchange && audience && {
845
1189
  audience: audience
@@ -847,6 +1191,7 @@
847
1191
  scope: scope
848
1192
  });
849
1193
  const body = useFormData ? createQueryParams(allParams) : JSON.stringify(allParams);
1194
+ const isDpopSupported = isGrantTypeSupported(options.grant_type);
850
1195
  return await getJSON(`${baseUrl}/oauth/token`, timeout, audience || "default", scope, {
851
1196
  method: "POST",
852
1197
  body: body,
@@ -854,7 +1199,7 @@
854
1199
  "Content-Type": useFormData ? "application/x-www-form-urlencoded" : "application/json",
855
1200
  "Auth0-Client": btoa(JSON.stringify(auth0Client || DEFAULT_AUTH0_CLIENT))
856
1201
  }
857
- }, worker, useFormData);
1202
+ }, worker, useFormData, isDpopSupported ? dpop : undefined);
858
1203
  }
859
1204
  const dedupe = arr => Array.from(new Set(arr));
860
1205
  const getUniqueScopes = (...scopes) => dedupe(scopes.filter(Boolean).join(" ").trim().split(/\s+/)).join(" ");
@@ -1396,7 +1741,7 @@
1396
1741
  return new Worker(url, options);
1397
1742
  };
1398
1743
  }
1399
- var WorkerFactory = createBase64WorkerFactory("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24oKSB7CiAgICAidXNlIHN0cmljdCI7CiAgICBjbGFzcyBHZW5lcmljRXJyb3IgZXh0ZW5kcyBFcnJvciB7CiAgICAgICAgY29uc3RydWN0b3IoZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uKSB7CiAgICAgICAgICAgIHN1cGVyKGVycm9yX2Rlc2NyaXB0aW9uKTsKICAgICAgICAgICAgdGhpcy5lcnJvciA9IGVycm9yOwogICAgICAgICAgICB0aGlzLmVycm9yX2Rlc2NyaXB0aW9uID0gZXJyb3JfZGVzY3JpcHRpb247CiAgICAgICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBHZW5lcmljRXJyb3IucHJvdG90eXBlKTsKICAgICAgICB9CiAgICAgICAgc3RhdGljIGZyb21QYXlsb2FkKHtlcnJvcjogZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uOiBlcnJvcl9kZXNjcmlwdGlvbn0pIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBHZW5lcmljRXJyb3IoZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uKTsKICAgICAgICB9CiAgICB9CiAgICBjbGFzcyBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IgZXh0ZW5kcyBHZW5lcmljRXJyb3IgewogICAgICAgIGNvbnN0cnVjdG9yKGF1ZGllbmNlLCBzY29wZSkgewogICAgICAgICAgICBzdXBlcigibWlzc2luZ19yZWZyZXNoX3Rva2VuIiwgYE1pc3NpbmcgUmVmcmVzaCBUb2tlbiAoYXVkaWVuY2U6ICcke3ZhbHVlT3JFbXB0eVN0cmluZyhhdWRpZW5jZSwgWyAiZGVmYXVsdCIgXSl9Jywgc2NvcGU6ICcke3ZhbHVlT3JFbXB0eVN0cmluZyhzY29wZSl9JylgKTsKICAgICAgICAgICAgdGhpcy5hdWRpZW5jZSA9IGF1ZGllbmNlOwogICAgICAgICAgICB0aGlzLnNjb3BlID0gc2NvcGU7CiAgICAgICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IucHJvdG90eXBlKTsKICAgICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiB2YWx1ZU9yRW1wdHlTdHJpbmcodmFsdWUsIGV4Y2x1ZGUgPSBbXSkgewogICAgICAgIHJldHVybiB2YWx1ZSAmJiAhZXhjbHVkZS5pbmNsdWRlcyh2YWx1ZSkgPyB2YWx1ZSA6ICIiOwogICAgfQogICAgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHsKICAgICAgICB2YXIgdCA9IHt9OwogICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKSB0W3BdID0gc1twXTsKICAgICAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSAiZnVuY3Rpb24iKSBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSkgdFtwW2ldXSA9IHNbcFtpXV07CiAgICAgICAgfQogICAgICAgIHJldHVybiB0OwogICAgfQogICAgdHlwZW9mIFN1cHByZXNzZWRFcnJvciA9PT0gImZ1bmN0aW9uIiA/IFN1cHByZXNzZWRFcnJvciA6IGZ1bmN0aW9uKGVycm9yLCBzdXBwcmVzc2VkLCBtZXNzYWdlKSB7CiAgICAgICAgdmFyIGUgPSBuZXcgRXJyb3IobWVzc2FnZSk7CiAgICAgICAgcmV0dXJuIGUubmFtZSA9ICJTdXBwcmVzc2VkRXJyb3IiLCBlLmVycm9yID0gZXJyb3IsIGUuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGU7CiAgICB9OwogICAgY29uc3Qgc3RyaXBVbmRlZmluZWQgPSBwYXJhbXMgPT4gT2JqZWN0LmtleXMocGFyYW1zKS5maWx0ZXIoKGsgPT4gdHlwZW9mIHBhcmFtc1trXSAhPT0gInVuZGVmaW5lZCIpKS5yZWR1Y2UoKChhY2MsIGtleSkgPT4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBhY2MpLCB7CiAgICAgICAgW2tleV06IHBhcmFtc1trZXldCiAgICB9KSksIHt9KTsKICAgIGNvbnN0IGNyZWF0ZVF1ZXJ5UGFyYW1zID0gX2EgPT4gewogICAgICAgIHZhciB7Y2xpZW50SWQ6IGNsaWVudF9pZH0gPSBfYSwgcGFyYW1zID0gX19yZXN0KF9hLCBbICJjbGllbnRJZCIgXSk7CiAgICAgICAgcmV0dXJuIG5ldyBVUkxTZWFyY2hQYXJhbXMoc3RyaXBVbmRlZmluZWQoT2JqZWN0LmFzc2lnbih7CiAgICAgICAgICAgIGNsaWVudF9pZDogY2xpZW50X2lkCiAgICAgICAgfSwgcGFyYW1zKSkpLnRvU3RyaW5nKCk7CiAgICB9OwogICAgbGV0IHJlZnJlc2hUb2tlbnMgPSB7fTsKICAgIGNvbnN0IGNhY2hlS2V5ID0gKGF1ZGllbmNlLCBzY29wZSkgPT4gYCR7YXVkaWVuY2V9fCR7c2NvcGV9YDsKICAgIGNvbnN0IGdldFJlZnJlc2hUb2tlbiA9IChhdWRpZW5jZSwgc2NvcGUpID0+IHJlZnJlc2hUb2tlbnNbY2FjaGVLZXkoYXVkaWVuY2UsIHNjb3BlKV07CiAgICBjb25zdCBzZXRSZWZyZXNoVG9rZW4gPSAocmVmcmVzaFRva2VuLCBhdWRpZW5jZSwgc2NvcGUpID0+IHJlZnJlc2hUb2tlbnNbY2FjaGVLZXkoYXVkaWVuY2UsIHNjb3BlKV0gPSByZWZyZXNoVG9rZW47CiAgICBjb25zdCBkZWxldGVSZWZyZXNoVG9rZW4gPSAoYXVkaWVuY2UsIHNjb3BlKSA9PiBkZWxldGUgcmVmcmVzaFRva2Vuc1tjYWNoZUtleShhdWRpZW5jZSwgc2NvcGUpXTsKICAgIGNvbnN0IHdhaXQgPSB0aW1lID0+IG5ldyBQcm9taXNlKChyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgdGltZSkpKTsKICAgIGNvbnN0IGZvcm1EYXRhVG9PYmplY3QgPSBmb3JtRGF0YSA9PiB7CiAgICAgICAgY29uc3QgcXVlcnlQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKGZvcm1EYXRhKTsKICAgICAgICBjb25zdCBwYXJzZWRRdWVyeSA9IHt9OwogICAgICAgIHF1ZXJ5UGFyYW1zLmZvckVhY2goKCh2YWwsIGtleSkgPT4gewogICAgICAgICAgICBwYXJzZWRRdWVyeVtrZXldID0gdmFsOwogICAgICAgIH0pKTsKICAgICAgICByZXR1cm4gcGFyc2VkUXVlcnk7CiAgICB9OwogICAgY29uc3QgbWVzc2FnZUhhbmRsZXIgPSBhc3luYyAoe2RhdGE6IHt0aW1lb3V0OiB0aW1lb3V0LCBhdXRoOiBhdXRoLCBmZXRjaFVybDogZmV0Y2hVcmwsIGZldGNoT3B0aW9uczogZmV0Y2hPcHRpb25zLCB1c2VGb3JtRGF0YTogdXNlRm9ybURhdGF9LCBwb3J0czogW3BvcnRdfSkgPT4gewogICAgICAgIGxldCBqc29uOwogICAgICAgIGNvbnN0IHthdWRpZW5jZTogYXVkaWVuY2UsIHNjb3BlOiBzY29wZX0gPSBhdXRoIHx8IHt9OwogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGNvbnN0IGJvZHkgPSB1c2VGb3JtRGF0YSA/IGZvcm1EYXRhVG9PYmplY3QoZmV0Y2hPcHRpb25zLmJvZHkpIDogSlNPTi5wYXJzZShmZXRjaE9wdGlvbnMuYm9keSk7CiAgICAgICAgICAgIGlmICghYm9keS5yZWZyZXNoX3Rva2VuICYmIGJvZHkuZ3JhbnRfdHlwZSA9PT0gInJlZnJlc2hfdG9rZW4iKSB7CiAgICAgICAgICAgICAgICBjb25zdCByZWZyZXNoVG9rZW4gPSBnZXRSZWZyZXNoVG9rZW4oYXVkaWVuY2UsIHNjb3BlKTsKICAgICAgICAgICAgICAgIGlmICghcmVmcmVzaFRva2VuKSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE1pc3NpbmdSZWZyZXNoVG9rZW5FcnJvcihhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZmV0Y2hPcHRpb25zLmJvZHkgPSB1c2VGb3JtRGF0YSA/IGNyZWF0ZVF1ZXJ5UGFyYW1zKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgYm9keSksIHsKICAgICAgICAgICAgICAgICAgICByZWZyZXNoX3Rva2VuOiByZWZyZXNoVG9rZW4KICAgICAgICAgICAgICAgIH0pKSA6IEpTT04uc3RyaW5naWZ5KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgYm9keSksIHsKICAgICAgICAgICAgICAgICAgICByZWZyZXNoX3Rva2VuOiByZWZyZXNoVG9rZW4KICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgYWJvcnRDb250cm9sbGVyOwogICAgICAgICAgICBpZiAodHlwZW9mIEFib3J0Q29udHJvbGxlciA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgICAgYWJvcnRDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcjsKICAgICAgICAgICAgICAgIGZldGNoT3B0aW9ucy5zaWduYWwgPSBhYm9ydENvbnRyb2xsZXIuc2lnbmFsOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxldCByZXNwb25zZTsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gYXdhaXQgUHJvbWlzZS5yYWNlKFsgd2FpdCh0aW1lb3V0KSwgZmV0Y2goZmV0Y2hVcmwsIE9iamVjdC5hc3NpZ24oe30sIGZldGNoT3B0aW9ucykpIF0pOwogICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgcG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yLm1lc3NhZ2UKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICghcmVzcG9uc2UpIHsKICAgICAgICAgICAgICAgIGlmIChhYm9ydENvbnRyb2xsZXIpIGFib3J0Q29udHJvbGxlci5hYm9ydCgpOwogICAgICAgICAgICAgICAgcG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgZXJyb3I6ICJUaW1lb3V0IHdoZW4gZXhlY3V0aW5nICdmZXRjaCciCiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpOwogICAgICAgICAgICBpZiAoanNvbi5yZWZyZXNoX3Rva2VuKSB7CiAgICAgICAgICAgICAgICBzZXRSZWZyZXNoVG9rZW4oanNvbi5yZWZyZXNoX3Rva2VuLCBhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICAgICAgZGVsZXRlIGpzb24ucmVmcmVzaF90b2tlbjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGRlbGV0ZVJlZnJlc2hUb2tlbihhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgb2s6IHJlc3BvbnNlLm9rLAogICAgICAgICAgICAgICAganNvbjoganNvbgogICAgICAgICAgICB9KTsKICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICBwb3J0LnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgIG9rOiBmYWxzZSwKICAgICAgICAgICAgICAgIGpzb246IHsKICAgICAgICAgICAgICAgICAgICBlcnJvcjogZXJyb3IuZXJyb3IsCiAgICAgICAgICAgICAgICAgICAgZXJyb3JfZGVzY3JpcHRpb246IGVycm9yLm1lc3NhZ2UKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgfTsKICAgIHsKICAgICAgICBhZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgbWVzc2FnZUhhbmRsZXIpOwogICAgfQp9KSgpOwoK", null, false);
1744
+ var WorkerFactory = createBase64WorkerFactory("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24oKSB7CiAgICAidXNlIHN0cmljdCI7CiAgICBjbGFzcyBHZW5lcmljRXJyb3IgZXh0ZW5kcyBFcnJvciB7CiAgICAgICAgY29uc3RydWN0b3IoZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uKSB7CiAgICAgICAgICAgIHN1cGVyKGVycm9yX2Rlc2NyaXB0aW9uKTsKICAgICAgICAgICAgdGhpcy5lcnJvciA9IGVycm9yOwogICAgICAgICAgICB0aGlzLmVycm9yX2Rlc2NyaXB0aW9uID0gZXJyb3JfZGVzY3JpcHRpb247CiAgICAgICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBHZW5lcmljRXJyb3IucHJvdG90eXBlKTsKICAgICAgICB9CiAgICAgICAgc3RhdGljIGZyb21QYXlsb2FkKHtlcnJvcjogZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uOiBlcnJvcl9kZXNjcmlwdGlvbn0pIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBHZW5lcmljRXJyb3IoZXJyb3IsIGVycm9yX2Rlc2NyaXB0aW9uKTsKICAgICAgICB9CiAgICB9CiAgICBjbGFzcyBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IgZXh0ZW5kcyBHZW5lcmljRXJyb3IgewogICAgICAgIGNvbnN0cnVjdG9yKGF1ZGllbmNlLCBzY29wZSkgewogICAgICAgICAgICBzdXBlcigibWlzc2luZ19yZWZyZXNoX3Rva2VuIiwgYE1pc3NpbmcgUmVmcmVzaCBUb2tlbiAoYXVkaWVuY2U6ICcke3ZhbHVlT3JFbXB0eVN0cmluZyhhdWRpZW5jZSwgWyAiZGVmYXVsdCIgXSl9Jywgc2NvcGU6ICcke3ZhbHVlT3JFbXB0eVN0cmluZyhzY29wZSl9JylgKTsKICAgICAgICAgICAgdGhpcy5hdWRpZW5jZSA9IGF1ZGllbmNlOwogICAgICAgICAgICB0aGlzLnNjb3BlID0gc2NvcGU7CiAgICAgICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IucHJvdG90eXBlKTsKICAgICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiB2YWx1ZU9yRW1wdHlTdHJpbmcodmFsdWUsIGV4Y2x1ZGUgPSBbXSkgewogICAgICAgIHJldHVybiB2YWx1ZSAmJiAhZXhjbHVkZS5pbmNsdWRlcyh2YWx1ZSkgPyB2YWx1ZSA6ICIiOwogICAgfQogICAgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHsKICAgICAgICB2YXIgdCA9IHt9OwogICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKSB0W3BdID0gc1twXTsKICAgICAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSAiZnVuY3Rpb24iKSBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSkgdFtwW2ldXSA9IHNbcFtpXV07CiAgICAgICAgfQogICAgICAgIHJldHVybiB0OwogICAgfQogICAgdHlwZW9mIFN1cHByZXNzZWRFcnJvciA9PT0gImZ1bmN0aW9uIiA/IFN1cHByZXNzZWRFcnJvciA6IGZ1bmN0aW9uKGVycm9yLCBzdXBwcmVzc2VkLCBtZXNzYWdlKSB7CiAgICAgICAgdmFyIGUgPSBuZXcgRXJyb3IobWVzc2FnZSk7CiAgICAgICAgcmV0dXJuIGUubmFtZSA9ICJTdXBwcmVzc2VkRXJyb3IiLCBlLmVycm9yID0gZXJyb3IsIGUuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGU7CiAgICB9OwogICAgY29uc3Qgc3RyaXBVbmRlZmluZWQgPSBwYXJhbXMgPT4gT2JqZWN0LmtleXMocGFyYW1zKS5maWx0ZXIoKGsgPT4gdHlwZW9mIHBhcmFtc1trXSAhPT0gInVuZGVmaW5lZCIpKS5yZWR1Y2UoKChhY2MsIGtleSkgPT4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBhY2MpLCB7CiAgICAgICAgW2tleV06IHBhcmFtc1trZXldCiAgICB9KSksIHt9KTsKICAgIGNvbnN0IGNyZWF0ZVF1ZXJ5UGFyYW1zID0gX2EgPT4gewogICAgICAgIHZhciB7Y2xpZW50SWQ6IGNsaWVudF9pZH0gPSBfYSwgcGFyYW1zID0gX19yZXN0KF9hLCBbICJjbGllbnRJZCIgXSk7CiAgICAgICAgcmV0dXJuIG5ldyBVUkxTZWFyY2hQYXJhbXMoc3RyaXBVbmRlZmluZWQoT2JqZWN0LmFzc2lnbih7CiAgICAgICAgICAgIGNsaWVudF9pZDogY2xpZW50X2lkCiAgICAgICAgfSwgcGFyYW1zKSkpLnRvU3RyaW5nKCk7CiAgICB9OwogICAgY29uc3QgZnJvbUVudHJpZXMgPSBpdGVyYWJsZSA9PiBbIC4uLml0ZXJhYmxlIF0ucmVkdWNlKCgob2JqLCBba2V5LCB2YWxdKSA9PiB7CiAgICAgICAgb2JqW2tleV0gPSB2YWw7CiAgICAgICAgcmV0dXJuIG9iajsKICAgIH0pLCB7fSk7CiAgICBsZXQgcmVmcmVzaFRva2VucyA9IHt9OwogICAgY29uc3QgY2FjaGVLZXkgPSAoYXVkaWVuY2UsIHNjb3BlKSA9PiBgJHthdWRpZW5jZX18JHtzY29wZX1gOwogICAgY29uc3QgZ2V0UmVmcmVzaFRva2VuID0gKGF1ZGllbmNlLCBzY29wZSkgPT4gcmVmcmVzaFRva2Vuc1tjYWNoZUtleShhdWRpZW5jZSwgc2NvcGUpXTsKICAgIGNvbnN0IHNldFJlZnJlc2hUb2tlbiA9IChyZWZyZXNoVG9rZW4sIGF1ZGllbmNlLCBzY29wZSkgPT4gcmVmcmVzaFRva2Vuc1tjYWNoZUtleShhdWRpZW5jZSwgc2NvcGUpXSA9IHJlZnJlc2hUb2tlbjsKICAgIGNvbnN0IGRlbGV0ZVJlZnJlc2hUb2tlbiA9IChhdWRpZW5jZSwgc2NvcGUpID0+IGRlbGV0ZSByZWZyZXNoVG9rZW5zW2NhY2hlS2V5KGF1ZGllbmNlLCBzY29wZSldOwogICAgY29uc3Qgd2FpdCA9IHRpbWUgPT4gbmV3IFByb21pc2UoKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCB0aW1lKSkpOwogICAgY29uc3QgZm9ybURhdGFUb09iamVjdCA9IGZvcm1EYXRhID0+IHsKICAgICAgICBjb25zdCBxdWVyeVBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoZm9ybURhdGEpOwogICAgICAgIGNvbnN0IHBhcnNlZFF1ZXJ5ID0ge307CiAgICAgICAgcXVlcnlQYXJhbXMuZm9yRWFjaCgoKHZhbCwga2V5KSA9PiB7CiAgICAgICAgICAgIHBhcnNlZFF1ZXJ5W2tleV0gPSB2YWw7CiAgICAgICAgfSkpOwogICAgICAgIHJldHVybiBwYXJzZWRRdWVyeTsKICAgIH07CiAgICBjb25zdCBtZXNzYWdlSGFuZGxlciA9IGFzeW5jICh7ZGF0YToge3RpbWVvdXQ6IHRpbWVvdXQsIGF1dGg6IGF1dGgsIGZldGNoVXJsOiBmZXRjaFVybCwgZmV0Y2hPcHRpb25zOiBmZXRjaE9wdGlvbnMsIHVzZUZvcm1EYXRhOiB1c2VGb3JtRGF0YX0sIHBvcnRzOiBbcG9ydF19KSA9PiB7CiAgICAgICAgbGV0IGhlYWRlcnMgPSB7fTsKICAgICAgICBsZXQganNvbjsKICAgICAgICBjb25zdCB7YXVkaWVuY2U6IGF1ZGllbmNlLCBzY29wZTogc2NvcGV9ID0gYXV0aCB8fCB7fTsKICAgICAgICB0cnkgewogICAgICAgICAgICBjb25zdCBib2R5ID0gdXNlRm9ybURhdGEgPyBmb3JtRGF0YVRvT2JqZWN0KGZldGNoT3B0aW9ucy5ib2R5KSA6IEpTT04ucGFyc2UoZmV0Y2hPcHRpb25zLmJvZHkpOwogICAgICAgICAgICBpZiAoIWJvZHkucmVmcmVzaF90b2tlbiAmJiBib2R5LmdyYW50X3R5cGUgPT09ICJyZWZyZXNoX3Rva2VuIikgewogICAgICAgICAgICAgICAgY29uc3QgcmVmcmVzaFRva2VuID0gZ2V0UmVmcmVzaFRva2VuKGF1ZGllbmNlLCBzY29wZSk7CiAgICAgICAgICAgICAgICBpZiAoIXJlZnJlc2hUb2tlbikgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBNaXNzaW5nUmVmcmVzaFRva2VuRXJyb3IoYXVkaWVuY2UsIHNjb3BlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZldGNoT3B0aW9ucy5ib2R5ID0gdXNlRm9ybURhdGEgPyBjcmVhdGVRdWVyeVBhcmFtcyhPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGJvZHkpLCB7CiAgICAgICAgICAgICAgICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuCiAgICAgICAgICAgICAgICB9KSkgOiBKU09OLnN0cmluZ2lmeShPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGJvZHkpLCB7CiAgICAgICAgICAgICAgICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGV0IGFib3J0Q29udHJvbGxlcjsKICAgICAgICAgICAgaWYgKHR5cGVvZiBBYm9ydENvbnRyb2xsZXIgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgICAgICAgIGFib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXI7CiAgICAgICAgICAgICAgICBmZXRjaE9wdGlvbnMuc2lnbmFsID0gYWJvcnRDb250cm9sbGVyLnNpZ25hbDsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgcmVzcG9uc2U7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICByZXNwb25zZSA9IGF3YWl0IFByb21pc2UucmFjZShbIHdhaXQodGltZW91dCksIGZldGNoKGZldGNoVXJsLCBPYmplY3QuYXNzaWduKHt9LCBmZXRjaE9wdGlvbnMpKSBdKTsKICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgIHBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgIGVycm9yOiBlcnJvci5tZXNzYWdlCiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIXJlc3BvbnNlKSB7CiAgICAgICAgICAgICAgICBpZiAoYWJvcnRDb250cm9sbGVyKSBhYm9ydENvbnRyb2xsZXIuYWJvcnQoKTsKICAgICAgICAgICAgICAgIHBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgIGVycm9yOiAiVGltZW91dCB3aGVuIGV4ZWN1dGluZyAnZmV0Y2gnIgogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaGVhZGVycyA9IGZyb21FbnRyaWVzKHJlc3BvbnNlLmhlYWRlcnMpOwogICAgICAgICAgICBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpOwogICAgICAgICAgICBpZiAoanNvbi5yZWZyZXNoX3Rva2VuKSB7CiAgICAgICAgICAgICAgICBzZXRSZWZyZXNoVG9rZW4oanNvbi5yZWZyZXNoX3Rva2VuLCBhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICAgICAgZGVsZXRlIGpzb24ucmVmcmVzaF90b2tlbjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGRlbGV0ZVJlZnJlc2hUb2tlbihhdWRpZW5jZSwgc2NvcGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHBvcnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgb2s6IHJlc3BvbnNlLm9rLAogICAgICAgICAgICAgICAganNvbjoganNvbiwKICAgICAgICAgICAgICAgIGhlYWRlcnM6IGhlYWRlcnMKICAgICAgICAgICAgfSk7CiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgcG9ydC5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICBvazogZmFsc2UsCiAgICAgICAgICAgICAgICBqc29uOiB7CiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yLmVycm9yLAogICAgICAgICAgICAgICAgICAgIGVycm9yX2Rlc2NyaXB0aW9uOiBlcnJvci5tZXNzYWdlCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgaGVhZGVyczogaGVhZGVycwogICAgICAgICAgICB9KTsKICAgICAgICB9CiAgICB9OwogICAgewogICAgICAgIGFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCBtZXNzYWdlSGFuZGxlcik7CiAgICB9Cn0pKCk7Cgo=", null, false);
1400
1745
  const singlePromiseMap = {};
1401
1746
  const singlePromise = (cb, key) => {
1402
1747
  let promise = singlePromiseMap[key];
@@ -1463,7 +1808,7 @@
1463
1808
  localstorage: () => new LocalStorageCache
1464
1809
  };
1465
1810
  const cacheFactory = location => cacheLocationBuilders[location];
1466
- 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({
1467
1812
  client_id: clientOptions.clientId
1468
1813
  }, clientOptions.authorizationParams), authorizationParams), {
1469
1814
  scope: getUniqueScopes(scope, authorizationParams.scope),
@@ -1473,7 +1818,8 @@
1473
1818
  nonce: nonce,
1474
1819
  redirect_uri: redirect_uri || clientOptions.authorizationParams.redirect_uri,
1475
1820
  code_challenge: code_challenge,
1476
- code_challenge_method: "S256"
1821
+ code_challenge_method: "S256",
1822
+ dpop_jkt: thumbprint
1477
1823
  });
1478
1824
  const patchOpenUrlWithOnRedirect = options => {
1479
1825
  const {openUrl: openUrl, onRedirect: onRedirect} = options, originalOptions = __rest(options, [ "openUrl", "onRedirect" ]);
@@ -1482,6 +1828,208 @@
1482
1828
  });
1483
1829
  return result;
1484
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
+ }
1485
2033
  const lock = new Lock;
1486
2034
  class Auth0Client {
1487
2035
  constructor(options) {
@@ -1525,6 +2073,7 @@
1525
2073
  this.transactionManager = new TransactionManager(transactionStorage, this.options.clientId, this.options.cookieDomain);
1526
2074
  this.nowProvider = this.options.nowProvider || DEFAULT_NOW_PROVIDER;
1527
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;
1528
2077
  this.domainUrl = getDomain(this.options.domain);
1529
2078
  this.tokenIssuer = getTokenIssuer(this.options.issuer, this.domainUrl);
1530
2079
  if (typeof window !== "undefined" && window.Worker && this.options.useRefreshTokens && cacheLocation === CACHE_LOCATION_MEMORY) {
@@ -1568,12 +2117,14 @@
1568
2117
  }
1569
2118
  }
1570
2119
  async _prepareAuthorizeUrl(authorizationParams, authorizeOptions, fallbackRedirectUri) {
2120
+ var _a;
1571
2121
  const state = encode(createRandomString());
1572
2122
  const nonce = encode(createRandomString());
1573
2123
  const code_verifier = createRandomString();
1574
2124
  const code_challengeBuffer = await sha256(code_verifier);
1575
2125
  const code_challenge = bufferToBase64UrlEncoded(code_challengeBuffer);
1576
- 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);
1577
2128
  const url = this._authorizeUrl(params);
1578
2129
  return {
1579
2130
  nonce: nonce,
@@ -1738,9 +2289,10 @@
1738
2289
  }
1739
2290
  }
1740
2291
  const authResult = this.options.useRefreshTokens ? await this._getTokenUsingRefreshToken(getTokenOptions) : await this._getTokenFromIFrame(getTokenOptions);
1741
- 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;
1742
2293
  return Object.assign(Object.assign({
1743
2294
  id_token: id_token,
2295
+ token_type: token_type,
1744
2296
  access_token: access_token
1745
2297
  }, oauthTokenScope ? {
1746
2298
  scope: oauthTokenScope
@@ -1789,7 +2341,8 @@
1789
2341
  return url + federatedQuery;
1790
2342
  }
1791
2343
  async logout(options = {}) {
1792
- 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" ]);
1793
2346
  if (options.clientId === null) {
1794
2347
  await this.cacheManager.clear();
1795
2348
  } else {
@@ -1802,6 +2355,7 @@
1802
2355
  cookieDomain: this.options.cookieDomain
1803
2356
  });
1804
2357
  this.userCache.remove(CACHE_KEY_ID_TOKEN_SUFFIX);
2358
+ await ((_a = this.dpop) === null || _a === void 0 ? void 0 : _a.clear());
1805
2359
  const url = this._buildLogoutUrl(logoutOptions);
1806
2360
  if (openUrl) {
1807
2361
  await openUrl(url);
@@ -1923,10 +2477,11 @@
1923
2477
  clientId: clientId
1924
2478
  }), 60);
1925
2479
  if (entry && entry.access_token) {
1926
- 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;
1927
2481
  const cache = await this._getIdTokenFromCache();
1928
2482
  return cache && Object.assign(Object.assign({
1929
2483
  id_token: cache.id_token,
2484
+ token_type: token_type ? token_type : "Bearer",
1930
2485
  access_token: access_token
1931
2486
  }, oauthTokenScope ? {
1932
2487
  scope: oauthTokenScope
@@ -1942,7 +2497,8 @@
1942
2497
  client_id: this.options.clientId,
1943
2498
  auth0Client: this.options.auth0Client,
1944
2499
  useFormData: this.options.useFormData,
1945
- timeout: this.httpTimeoutMs
2500
+ timeout: this.httpTimeoutMs,
2501
+ dpop: this.dpop
1946
2502
  }, options), this.worker);
1947
2503
  const decodedToken = await this._verifyIdToken(authResult.id_token, nonceIn, organization);
1948
2504
  await this._saveEntryInCache(Object.assign(Object.assign(Object.assign(Object.assign({}, authResult), {
@@ -1972,6 +2528,35 @@
1972
2528
  audience: options.audience || this.options.authorizationParams.audience
1973
2529
  });
1974
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)
2558
+ });
2559
+ }
1975
2560
  }
1976
2561
  class User {}
1977
2562
  async function createAuth0Client(options) {
@@ -1990,6 +2575,7 @@
1990
2575
  exports.PopupCancelledError = PopupCancelledError;
1991
2576
  exports.PopupTimeoutError = PopupTimeoutError;
1992
2577
  exports.TimeoutError = TimeoutError;
2578
+ exports.UseDpopNonceError = UseDpopNonceError;
1993
2579
  exports.User = User;
1994
2580
  exports.createAuth0Client = createAuth0Client;
1995
2581
  Object.defineProperty(exports, "__esModule", {