@muze-nl/metro-oidc 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.js CHANGED
@@ -278,10 +278,23 @@
278
278
  function callTracers(tracers, method, ...args) {
279
279
  for (const tracer of tracers) {
280
280
  if (tracer && typeof tracer[method] == "function") {
281
- tracer[method].call(tracer, ...args);
281
+ callTracer(tracer, method, args);
282
282
  }
283
283
  }
284
284
  }
285
+ function callTracer(tracer, method, args) {
286
+ const reportFailure = (error2) => {
287
+ metroConsole.error("metro: tracer." + method + "() failed", error2);
288
+ };
289
+ try {
290
+ const result = tracer[method].call(tracer, ...args);
291
+ if (typeof result?.then == "function") {
292
+ result.then(void 0, reportFailure);
293
+ }
294
+ } catch (error2) {
295
+ reportFailure(error2);
296
+ }
297
+ }
285
298
  function isPlainObject(value) {
286
299
  return value && typeof value == "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
287
300
  }
@@ -679,21 +692,250 @@
679
692
  return object;
680
693
  }
681
694
 
682
- // ../../node_modules/@muze-nl/assert/src/assert.mjs
683
- globalThis.assertEnabled = false;
695
+ // ../../node_modules/@muze-nl/assert/src/assert-core.mjs
696
+ var assert_core_exports = {};
697
+ __export(assert_core_exports, {
698
+ Optional: () => Optional,
699
+ Recommended: () => Recommended,
700
+ Required: () => Required,
701
+ allOf: () => allOf,
702
+ anyOf: () => anyOf,
703
+ assert: () => assert,
704
+ disable: () => disable,
705
+ enable: () => enable,
706
+ error: () => error,
707
+ fails: () => fails,
708
+ formatIssue: () => formatIssue,
709
+ formatIssues: () => formatIssues,
710
+ instanceOf: () => instanceOf,
711
+ issues: () => issues,
712
+ not: () => not,
713
+ oneOf: () => oneOf,
714
+ validEmail: () => validEmail,
715
+ validURL: () => validURL,
716
+ warn: () => warn
717
+ });
718
+ var assertEnabled = false;
684
719
  function enable() {
685
- globalThis.assertEnabled = true;
720
+ assertEnabled = true;
686
721
  }
687
722
  function disable() {
688
- globalThis.assertEnabled = false;
723
+ assertEnabled = false;
724
+ }
725
+ function appendPath(path = "", key) {
726
+ if (typeof path == "undefined" || path == null) {
727
+ path = "";
728
+ }
729
+ if (typeof key == "number") {
730
+ return `${path}[${key}]`;
731
+ }
732
+ return `${path}.${key}`;
733
+ }
734
+ function pathToArray(path = "") {
735
+ if (Array.isArray(path)) {
736
+ return path;
737
+ }
738
+ if (!path) {
739
+ return [];
740
+ }
741
+ let result = [];
742
+ let matcher = /(?:^|\.)([^.\[\]]+)|\[(\d+)\]/g;
743
+ let match;
744
+ while (match = matcher.exec(path)) {
745
+ if (typeof match[1] != "undefined") {
746
+ result.push(match[1]);
747
+ } else if (typeof match[2] != "undefined") {
748
+ result.push(Number(match[2]));
749
+ }
750
+ }
751
+ return result;
752
+ }
753
+ function pathToString(path = []) {
754
+ if (typeof path == "string") {
755
+ return path.startsWith(".") ? path.slice(1) : path;
756
+ }
757
+ return path.map((part, index) => {
758
+ if (typeof part == "number") {
759
+ return `[${part}]`;
760
+ }
761
+ return `${index ? "." : ""}${part}`;
762
+ }).join("");
763
+ }
764
+ function describeFunction(value) {
765
+ if (value === String) {
766
+ return "string";
767
+ }
768
+ if (value === Number) {
769
+ return "number";
770
+ }
771
+ if (value === Boolean) {
772
+ return "boolean";
773
+ }
774
+ return value.name || "function";
775
+ }
776
+ function clip(text, maxLength = 60) {
777
+ if (text.length <= maxLength) {
778
+ return text;
779
+ }
780
+ return text.slice(0, maxLength - 1) + "\u2026";
781
+ }
782
+ function quoteString(value) {
783
+ return `'${clip(String(value).replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n"))}'`;
784
+ }
785
+ function jsonSummary(value) {
786
+ try {
787
+ let json = JSON.stringify(value);
788
+ if (typeof json == "string") {
789
+ return clip(json);
790
+ }
791
+ } catch (e) {
792
+ }
793
+ let name = value?.constructor?.name;
794
+ if (name && name != "Object") {
795
+ return name;
796
+ }
797
+ return Object.prototype.toString.call(value);
798
+ }
799
+ function formatValue(value) {
800
+ if (typeof value == "string") {
801
+ return quoteString(value);
802
+ }
803
+ if (typeof value == "undefined") {
804
+ return "undefined";
805
+ }
806
+ if (value === null) {
807
+ return "null";
808
+ }
809
+ if (typeof value == "function") {
810
+ return describeFunction(value);
811
+ }
812
+ if (value instanceof RegExp) {
813
+ return value.toString();
814
+ }
815
+ if (typeof value == "number" || typeof value == "boolean" || typeof value == "bigint") {
816
+ return String(value);
817
+ }
818
+ if (typeof value == "symbol") {
819
+ return value.toString();
820
+ }
821
+ return jsonSummary(value);
822
+ }
823
+ function describeExpected(value) {
824
+ if (value === String || value === Number || value === Boolean) {
825
+ return describeFunction(value);
826
+ }
827
+ if (typeof value == "function") {
828
+ return describeFunction(value);
829
+ }
830
+ if (value instanceof RegExp) {
831
+ return value.toString();
832
+ }
833
+ if (Array.isArray(value)) {
834
+ return "[" + value.map(describeExpected).join(", ") + "]";
835
+ }
836
+ return formatValue(value);
837
+ }
838
+ function describeOneOf(patterns) {
839
+ return patterns.map(describeExpected).join(", ");
840
+ }
841
+ function conciseMessage(message2, actual, expected) {
842
+ if (message2 == "data and pattern are not equal") {
843
+ return `expected ${formatValue(expected)}, found ${formatValue(actual)}`;
844
+ }
845
+ if (message2 == "data does not match pattern" || /^data\[\d+\] does not match pattern$/.test(message2)) {
846
+ return `expected ${describeExpected(expected)}, found ${formatValue(actual)}`;
847
+ }
848
+ if (message2 == "data is undefined, should match pattern") {
849
+ return `missing; expected ${describeExpected(expected)}`;
850
+ }
851
+ if (message2 == "data is required") {
852
+ return "required";
853
+ }
854
+ if (message2 == "data is an empty string, which is not allowed") {
855
+ return "empty string is not allowed";
856
+ }
857
+ if (message2 == "data is not an object, pattern is") {
858
+ return "data is not an object";
859
+ }
860
+ if (message2 == "data is not an instanceof pattern") {
861
+ return `expected instance of ${describeExpected(expected)}, found ${formatValue(actual)}`;
862
+ }
863
+ if (message2 == "data does not match oneOf patterns" || message2 == "data does not match anyOf patterns") {
864
+ return `expected one of ${describeOneOf(expected)}, found ${formatValue(actual)}`;
865
+ }
866
+ if (message2 == "data matches pattern, when required not to") {
867
+ return `must not match ${describeExpected(expected)}`;
868
+ }
869
+ return message2;
870
+ }
871
+ function formatIssue(issue, options = {}) {
872
+ if (!issue || typeof issue != "object") {
873
+ return String(issue);
874
+ }
875
+ let path = issue.pathString || pathToString(issue.path || []) || "value";
876
+ let indent = options.indent ?? "";
877
+ return `${indent}${path}: ${issue.message}`;
878
+ }
879
+ function formatIssues(issues2, options = {}) {
880
+ if (!issues2) {
881
+ return false;
882
+ }
883
+ let indent = options.indent ?? " - ";
884
+ return (Array.isArray(issues2) ? issues2 : [issues2]).map((issue) => formatIssue(issue, { ...options, indent }));
885
+ }
886
+ function issueFromProblem(problem) {
887
+ if (!problem || typeof problem != "object") {
888
+ return {
889
+ path: [],
890
+ pathString: "",
891
+ message: String(problem),
892
+ expected: void 0,
893
+ actual: void 0
894
+ };
895
+ }
896
+ let path = pathToArray(problem.path);
897
+ let pathString = pathToString(path);
898
+ let actual = problem.actual ?? problem.found;
899
+ let expected = describeExpected(problem.expected);
900
+ let message2 = conciseMessage(problem.message, actual, problem.expected);
901
+ return {
902
+ path,
903
+ pathString,
904
+ message: message2,
905
+ expected,
906
+ actual
907
+ };
908
+ }
909
+ function problemsToIssues(problems) {
910
+ if (!problems) {
911
+ return [];
912
+ }
913
+ let result = [];
914
+ for (let problem of Array.isArray(problems) ? problems : [problems]) {
915
+ if (!problem) {
916
+ continue;
917
+ }
918
+ if (problem && typeof problem == "object" && problem.problems) {
919
+ let nested = problemsToIssues(problem.problems);
920
+ if (nested.length) {
921
+ result = result.concat(nested);
922
+ continue;
923
+ }
924
+ }
925
+ result.push(issueFromProblem(problem));
926
+ }
927
+ return result;
689
928
  }
690
929
  function assert(source, test) {
691
- if (globalThis.assertEnabled) {
930
+ if (assertEnabled) {
692
931
  let problems = fails(source, test);
693
932
  if (problems) {
694
- console.error("\u{1F170}\uFE0F Assertions failed because of:", problems, "in this source:", source);
695
- throw new Error("Assertions failed", {
696
- cause: { problems, source }
933
+ let assertionIssues = problemsToIssues(problems);
934
+ let formattedIssues = formatIssues(assertionIssues);
935
+ let message2 = "Assertions failed:\n" + formattedIssues.join("\n");
936
+ console.error("\u{1F170}\uFE0F " + message2);
937
+ throw new Error(message2, {
938
+ cause: { problems, issues: assertionIssues, source }
697
939
  });
698
940
  }
699
941
  }
@@ -741,9 +983,10 @@
741
983
  if (!Array.isArray(data)) {
742
984
  return error("data is not an array", data, "anyOf", path);
743
985
  }
744
- for (let value of data) {
745
- if (oneOf(...patterns)(value)) {
746
- return error("data does not match anyOf patterns", value, patterns, path);
986
+ for (let [index, value] of data.entries()) {
987
+ let itemPath = appendPath(path, index);
988
+ if (oneOf(...patterns)(value, root, itemPath)) {
989
+ return error("data does not match anyOf patterns", value, patterns, itemPath);
747
990
  }
748
991
  }
749
992
  return false;
@@ -795,8 +1038,15 @@
795
1038
  }
796
1039
  };
797
1040
  }
1041
+ function issues(data, pattern, root) {
1042
+ let problems = fails(data, pattern, root);
1043
+ if (!problems) {
1044
+ return false;
1045
+ }
1046
+ return problemsToIssues(problems);
1047
+ }
798
1048
  function fails(data, pattern, root, path = "") {
799
- if (!root) {
1049
+ if (typeof root == "undefined") {
800
1050
  root = data;
801
1051
  }
802
1052
  let problems = [];
@@ -817,9 +1067,9 @@
817
1067
  }
818
1068
  } else if (pattern instanceof RegExp) {
819
1069
  if (Array.isArray(data)) {
820
- let index = data.findIndex((element, index2) => fails(element, pattern, root, path + "[" + index2 + "]"));
1070
+ let index = data.findIndex((element, index2) => fails(element, pattern, root, appendPath(path, index2)));
821
1071
  if (index > -1) {
822
- problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, path + "[" + index + "]"));
1072
+ problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, appendPath(path, index)));
823
1073
  }
824
1074
  } else if (typeof data == "undefined") {
825
1075
  problems.push(error("data is undefined, should match pattern", data, pattern, path));
@@ -838,22 +1088,23 @@
838
1088
  } else if (Array.isArray(pattern)) {
839
1089
  if (!Array.isArray(data)) {
840
1090
  problems.push(error("data is not an array", data, [], path));
841
- }
842
- for (let p of pattern) {
843
- for (let index of data.keys()) {
844
- let problem = fails(data[index], p, root, path + "[" + index + "]");
845
- if (Array.isArray(problem)) {
846
- problems = problems.concat(problem);
847
- } else if (problem) {
848
- problems.push(problem);
1091
+ } else {
1092
+ for (let p of pattern) {
1093
+ for (let index of data.keys()) {
1094
+ let problem = fails(data[index], p, root, appendPath(path, index));
1095
+ if (Array.isArray(problem)) {
1096
+ problems = problems.concat(problem);
1097
+ } else if (problem) {
1098
+ problems.push(problem);
1099
+ }
849
1100
  }
850
1101
  }
851
1102
  }
852
1103
  } else if (pattern && typeof pattern == "object") {
853
1104
  if (Array.isArray(data)) {
854
- let index = data.findIndex((element, index2) => fails(element, pattern, root, path + "[" + index2 + "]"));
1105
+ let index = data.findIndex((element, index2) => fails(element, pattern, root, appendPath(path, index2)));
855
1106
  if (index > -1) {
856
- problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, path + "[" + index + "]"));
1107
+ problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, appendPath(path, index)));
857
1108
  }
858
1109
  } else if (!data || typeof data != "object") {
859
1110
  problems.push(error("data is not an object, pattern is", data, pattern, path));
@@ -868,7 +1119,7 @@
868
1119
  }
869
1120
  } else {
870
1121
  for (const [patternKey, subpattern] of Object.entries(pattern)) {
871
- let result = fails(data[patternKey], subpattern, root, path + "." + patternKey);
1122
+ let result = fails(data[patternKey], subpattern, root, appendPath(path, patternKey));
872
1123
  if (result) {
873
1124
  problems = problems.concat(result);
874
1125
  }
@@ -885,9 +1136,12 @@
885
1136
  }
886
1137
  return false;
887
1138
  }
888
- function error(message2, found, expected, path, problems) {
1139
+ function error(message2, found, expected, path = "", problems) {
1140
+ let pathParts = pathToArray(path);
889
1141
  let result = {
890
1142
  path,
1143
+ pathString: pathToString(pathParts),
1144
+ pathParts,
891
1145
  message: message2,
892
1146
  found,
893
1147
  expected
@@ -900,24 +1154,9 @@
900
1154
  function warn(message2, data, pattern, path) {
901
1155
  console.warn("\u{1F170}\uFE0F Assert: " + path, message2, pattern, data);
902
1156
  }
903
- globalThis.assert = {
904
- warn,
905
- error,
906
- assert,
907
- enable,
908
- disable,
909
- Required,
910
- Recommended,
911
- Optional,
912
- oneOf,
913
- anyOf,
914
- allOf,
915
- validURL,
916
- validEmail,
917
- instanceOf,
918
- not,
919
- fails
920
- };
1157
+
1158
+ // ../../node_modules/@muze-nl/assert/src/assert.mjs
1159
+ globalThis.assert = { ...assert_core_exports };
921
1160
 
922
1161
  // ../metro-oauth2/src/tokenstore.mjs
923
1162
  function tokenStore(site) {
@@ -1019,7 +1258,7 @@
1019
1258
  }
1020
1259
  return oauth2authorized(req, next);
1021
1260
  };
1022
- async function oauth2authorized(req, next) {
1261
+ async function oauth2authorized(req, next, retryState = {}) {
1023
1262
  getTokensFromLocation();
1024
1263
  const accessToken = options.tokens.get("access_token");
1025
1264
  const refreshToken = options.tokens.get("refresh_token");
@@ -1037,12 +1276,21 @@
1037
1276
  }
1038
1277
  return oauth2authorized(req, next);
1039
1278
  } else {
1040
- req = request(req, {
1279
+ const authorizedReq = request(req, {
1041
1280
  headers: {
1042
1281
  Authorization: accessToken.type + " " + accessToken.value
1043
1282
  }
1044
1283
  });
1045
- return next(req);
1284
+ const res = await next(authorizedReq);
1285
+ if (!shouldAuthorizeResponse(res) || retryState.handledRejectedToken) {
1286
+ return res;
1287
+ }
1288
+ options.tokens.delete("access_token");
1289
+ const token = refreshToken ? await refreshAccessToken() : await fetchAccessToken();
1290
+ if (!token) {
1291
+ return response("false");
1292
+ }
1293
+ return oauth2authorized(req, next, { handledRejectedToken: true });
1046
1294
  }
1047
1295
  }
1048
1296
  function getTokensFromLocation() {
@@ -1741,17 +1989,31 @@
1741
1989
  if (res && isJSON(res.headers?.get("Content-Type"))) {
1742
1990
  let tempRes = res.clone();
1743
1991
  let body = await tempRes.text();
1992
+ if (body === "") {
1993
+ return res;
1994
+ }
1744
1995
  try {
1745
1996
  let json2 = JSON.parse(body, options.reviver);
1746
1997
  return res.with({
1747
1998
  body: json2
1748
1999
  });
1749
- } catch (e) {
2000
+ } catch (error2) {
2001
+ if (!res.ok) {
2002
+ return res;
2003
+ }
2004
+ throw parseError(req, res, error2);
1750
2005
  }
1751
2006
  }
1752
2007
  return res;
1753
2008
  };
1754
2009
  }
2010
+ function parseError(req, res, cause) {
2011
+ const message2 = "jsonmw: could not parse " + res.headers.get("Content-Type") + " response from " + req.url;
2012
+ const error2 = new Error(message2, { cause });
2013
+ error2.request = req;
2014
+ error2.response = res;
2015
+ return error2;
2016
+ }
1755
2017
  var jsonRE = /^application\/([a-zA-Z0-9\-_]+\+)?json\b/;
1756
2018
  function isJSON(contentType) {
1757
2019
  return jsonRE.exec(contentType);
@@ -3261,6 +3523,7 @@
3261
3523
  }
3262
3524
  };
3263
3525
  options = Object.assign({}, defaultOptions, options);
3526
+ const requestedClientInfo = options.client_info;
3264
3527
  assert(options, {
3265
3528
  client: Required(instanceOf(client().constructor)),
3266
3529
  // required because it is set in defaultOptions
@@ -3276,7 +3539,10 @@
3276
3539
  options.openid_configuration = options.store.get("openid_configuration");
3277
3540
  }
3278
3541
  if (!options.client_info?.client_id && options.store.has("client_info")) {
3279
- options.client_info = options.store.get("client_info");
3542
+ const storedClientInfo = options.store.get("client_info");
3543
+ if (clientInfoMatchesRequest(storedClientInfo, requestedClientInfo)) {
3544
+ options.client_info = storedClientInfo;
3545
+ }
3280
3546
  }
3281
3547
  return async (req, next) => {
3282
3548
  let res;
@@ -3389,6 +3655,16 @@
3389
3655
  return res;
3390
3656
  };
3391
3657
  }
3658
+ function clientInfoMatchesRequest(storedClientInfo, requestedClientInfo) {
3659
+ if (!storedClientInfo?.client_id) {
3660
+ return false;
3661
+ }
3662
+ if (!Array.isArray(requestedClientInfo?.redirect_uris)) {
3663
+ return true;
3664
+ }
3665
+ const storedRedirectUris = new Set(storedClientInfo.redirect_uris || []);
3666
+ return requestedClientInfo.redirect_uris.every((uri) => storedRedirectUris.has(uri));
3667
+ }
3392
3668
  function isRedirected2() {
3393
3669
  return isRedirected();
3394
3670
  }