@muze-nl/metro-oidc 0.8.0 → 0.9.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.
package/dist/browser.js CHANGED
@@ -679,21 +679,250 @@
679
679
  return object;
680
680
  }
681
681
 
682
- // ../../node_modules/@muze-nl/assert/src/assert.mjs
683
- globalThis.assertEnabled = false;
682
+ // ../../node_modules/@muze-nl/assert/src/assert-core.mjs
683
+ var assert_core_exports = {};
684
+ __export(assert_core_exports, {
685
+ Optional: () => Optional,
686
+ Recommended: () => Recommended,
687
+ Required: () => Required,
688
+ allOf: () => allOf,
689
+ anyOf: () => anyOf,
690
+ assert: () => assert,
691
+ disable: () => disable,
692
+ enable: () => enable,
693
+ error: () => error,
694
+ fails: () => fails,
695
+ formatIssue: () => formatIssue,
696
+ formatIssues: () => formatIssues,
697
+ instanceOf: () => instanceOf,
698
+ issues: () => issues,
699
+ not: () => not,
700
+ oneOf: () => oneOf,
701
+ validEmail: () => validEmail,
702
+ validURL: () => validURL,
703
+ warn: () => warn
704
+ });
705
+ var assertEnabled = false;
684
706
  function enable() {
685
- globalThis.assertEnabled = true;
707
+ assertEnabled = true;
686
708
  }
687
709
  function disable() {
688
- globalThis.assertEnabled = false;
710
+ assertEnabled = false;
711
+ }
712
+ function appendPath(path = "", key) {
713
+ if (typeof path == "undefined" || path == null) {
714
+ path = "";
715
+ }
716
+ if (typeof key == "number") {
717
+ return `${path}[${key}]`;
718
+ }
719
+ return `${path}.${key}`;
720
+ }
721
+ function pathToArray(path = "") {
722
+ if (Array.isArray(path)) {
723
+ return path;
724
+ }
725
+ if (!path) {
726
+ return [];
727
+ }
728
+ let result = [];
729
+ let matcher = /(?:^|\.)([^.\[\]]+)|\[(\d+)\]/g;
730
+ let match;
731
+ while (match = matcher.exec(path)) {
732
+ if (typeof match[1] != "undefined") {
733
+ result.push(match[1]);
734
+ } else if (typeof match[2] != "undefined") {
735
+ result.push(Number(match[2]));
736
+ }
737
+ }
738
+ return result;
739
+ }
740
+ function pathToString(path = []) {
741
+ if (typeof path == "string") {
742
+ return path.startsWith(".") ? path.slice(1) : path;
743
+ }
744
+ return path.map((part, index) => {
745
+ if (typeof part == "number") {
746
+ return `[${part}]`;
747
+ }
748
+ return `${index ? "." : ""}${part}`;
749
+ }).join("");
750
+ }
751
+ function describeFunction(value) {
752
+ if (value === String) {
753
+ return "string";
754
+ }
755
+ if (value === Number) {
756
+ return "number";
757
+ }
758
+ if (value === Boolean) {
759
+ return "boolean";
760
+ }
761
+ return value.name || "function";
762
+ }
763
+ function clip(text, maxLength = 60) {
764
+ if (text.length <= maxLength) {
765
+ return text;
766
+ }
767
+ return text.slice(0, maxLength - 1) + "\u2026";
768
+ }
769
+ function quoteString(value) {
770
+ return `'${clip(String(value).replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n"))}'`;
771
+ }
772
+ function jsonSummary(value) {
773
+ try {
774
+ let json = JSON.stringify(value);
775
+ if (typeof json == "string") {
776
+ return clip(json);
777
+ }
778
+ } catch (e) {
779
+ }
780
+ let name = value?.constructor?.name;
781
+ if (name && name != "Object") {
782
+ return name;
783
+ }
784
+ return Object.prototype.toString.call(value);
785
+ }
786
+ function formatValue(value) {
787
+ if (typeof value == "string") {
788
+ return quoteString(value);
789
+ }
790
+ if (typeof value == "undefined") {
791
+ return "undefined";
792
+ }
793
+ if (value === null) {
794
+ return "null";
795
+ }
796
+ if (typeof value == "function") {
797
+ return describeFunction(value);
798
+ }
799
+ if (value instanceof RegExp) {
800
+ return value.toString();
801
+ }
802
+ if (typeof value == "number" || typeof value == "boolean" || typeof value == "bigint") {
803
+ return String(value);
804
+ }
805
+ if (typeof value == "symbol") {
806
+ return value.toString();
807
+ }
808
+ return jsonSummary(value);
809
+ }
810
+ function describeExpected(value) {
811
+ if (value === String || value === Number || value === Boolean) {
812
+ return describeFunction(value);
813
+ }
814
+ if (typeof value == "function") {
815
+ return describeFunction(value);
816
+ }
817
+ if (value instanceof RegExp) {
818
+ return value.toString();
819
+ }
820
+ if (Array.isArray(value)) {
821
+ return "[" + value.map(describeExpected).join(", ") + "]";
822
+ }
823
+ return formatValue(value);
824
+ }
825
+ function describeOneOf(patterns) {
826
+ return patterns.map(describeExpected).join(", ");
827
+ }
828
+ function conciseMessage(message2, actual, expected) {
829
+ if (message2 == "data and pattern are not equal") {
830
+ return `expected ${formatValue(expected)}, found ${formatValue(actual)}`;
831
+ }
832
+ if (message2 == "data does not match pattern" || /^data\[\d+\] does not match pattern$/.test(message2)) {
833
+ return `expected ${describeExpected(expected)}, found ${formatValue(actual)}`;
834
+ }
835
+ if (message2 == "data is undefined, should match pattern") {
836
+ return `missing; expected ${describeExpected(expected)}`;
837
+ }
838
+ if (message2 == "data is required") {
839
+ return "required";
840
+ }
841
+ if (message2 == "data is an empty string, which is not allowed") {
842
+ return "empty string is not allowed";
843
+ }
844
+ if (message2 == "data is not an object, pattern is") {
845
+ return "data is not an object";
846
+ }
847
+ if (message2 == "data is not an instanceof pattern") {
848
+ return `expected instance of ${describeExpected(expected)}, found ${formatValue(actual)}`;
849
+ }
850
+ if (message2 == "data does not match oneOf patterns" || message2 == "data does not match anyOf patterns") {
851
+ return `expected one of ${describeOneOf(expected)}, found ${formatValue(actual)}`;
852
+ }
853
+ if (message2 == "data matches pattern, when required not to") {
854
+ return `must not match ${describeExpected(expected)}`;
855
+ }
856
+ return message2;
857
+ }
858
+ function formatIssue(issue, options = {}) {
859
+ if (!issue || typeof issue != "object") {
860
+ return String(issue);
861
+ }
862
+ let path = issue.pathString || pathToString(issue.path || []) || "value";
863
+ let indent = options.indent ?? "";
864
+ return `${indent}${path}: ${issue.message}`;
865
+ }
866
+ function formatIssues(issues2, options = {}) {
867
+ if (!issues2) {
868
+ return false;
869
+ }
870
+ let indent = options.indent ?? " - ";
871
+ return (Array.isArray(issues2) ? issues2 : [issues2]).map((issue) => formatIssue(issue, { ...options, indent }));
872
+ }
873
+ function issueFromProblem(problem) {
874
+ if (!problem || typeof problem != "object") {
875
+ return {
876
+ path: [],
877
+ pathString: "",
878
+ message: String(problem),
879
+ expected: void 0,
880
+ actual: void 0
881
+ };
882
+ }
883
+ let path = pathToArray(problem.path);
884
+ let pathString = pathToString(path);
885
+ let actual = problem.actual ?? problem.found;
886
+ let expected = describeExpected(problem.expected);
887
+ let message2 = conciseMessage(problem.message, actual, problem.expected);
888
+ return {
889
+ path,
890
+ pathString,
891
+ message: message2,
892
+ expected,
893
+ actual
894
+ };
895
+ }
896
+ function problemsToIssues(problems) {
897
+ if (!problems) {
898
+ return [];
899
+ }
900
+ let result = [];
901
+ for (let problem of Array.isArray(problems) ? problems : [problems]) {
902
+ if (!problem) {
903
+ continue;
904
+ }
905
+ if (problem && typeof problem == "object" && problem.problems) {
906
+ let nested = problemsToIssues(problem.problems);
907
+ if (nested.length) {
908
+ result = result.concat(nested);
909
+ continue;
910
+ }
911
+ }
912
+ result.push(issueFromProblem(problem));
913
+ }
914
+ return result;
689
915
  }
690
916
  function assert(source, test) {
691
- if (globalThis.assertEnabled) {
917
+ if (assertEnabled) {
692
918
  let problems = fails(source, test);
693
919
  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 }
920
+ let assertionIssues = problemsToIssues(problems);
921
+ let formattedIssues = formatIssues(assertionIssues);
922
+ let message2 = "Assertions failed:\n" + formattedIssues.join("\n");
923
+ console.error("\u{1F170}\uFE0F " + message2);
924
+ throw new Error(message2, {
925
+ cause: { problems, issues: assertionIssues, source }
697
926
  });
698
927
  }
699
928
  }
@@ -741,9 +970,10 @@
741
970
  if (!Array.isArray(data)) {
742
971
  return error("data is not an array", data, "anyOf", path);
743
972
  }
744
- for (let value of data) {
745
- if (oneOf(...patterns)(value)) {
746
- return error("data does not match anyOf patterns", value, patterns, path);
973
+ for (let [index, value] of data.entries()) {
974
+ let itemPath = appendPath(path, index);
975
+ if (oneOf(...patterns)(value, root, itemPath)) {
976
+ return error("data does not match anyOf patterns", value, patterns, itemPath);
747
977
  }
748
978
  }
749
979
  return false;
@@ -795,8 +1025,15 @@
795
1025
  }
796
1026
  };
797
1027
  }
1028
+ function issues(data, pattern, root) {
1029
+ let problems = fails(data, pattern, root);
1030
+ if (!problems) {
1031
+ return false;
1032
+ }
1033
+ return problemsToIssues(problems);
1034
+ }
798
1035
  function fails(data, pattern, root, path = "") {
799
- if (!root) {
1036
+ if (typeof root == "undefined") {
800
1037
  root = data;
801
1038
  }
802
1039
  let problems = [];
@@ -817,9 +1054,9 @@
817
1054
  }
818
1055
  } else if (pattern instanceof RegExp) {
819
1056
  if (Array.isArray(data)) {
820
- let index = data.findIndex((element, index2) => fails(element, pattern, root, path + "[" + index2 + "]"));
1057
+ let index = data.findIndex((element, index2) => fails(element, pattern, root, appendPath(path, index2)));
821
1058
  if (index > -1) {
822
- problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, path + "[" + index + "]"));
1059
+ problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, appendPath(path, index)));
823
1060
  }
824
1061
  } else if (typeof data == "undefined") {
825
1062
  problems.push(error("data is undefined, should match pattern", data, pattern, path));
@@ -838,22 +1075,23 @@
838
1075
  } else if (Array.isArray(pattern)) {
839
1076
  if (!Array.isArray(data)) {
840
1077
  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);
1078
+ } else {
1079
+ for (let p of pattern) {
1080
+ for (let index of data.keys()) {
1081
+ let problem = fails(data[index], p, root, appendPath(path, index));
1082
+ if (Array.isArray(problem)) {
1083
+ problems = problems.concat(problem);
1084
+ } else if (problem) {
1085
+ problems.push(problem);
1086
+ }
849
1087
  }
850
1088
  }
851
1089
  }
852
1090
  } else if (pattern && typeof pattern == "object") {
853
1091
  if (Array.isArray(data)) {
854
- let index = data.findIndex((element, index2) => fails(element, pattern, root, path + "[" + index2 + "]"));
1092
+ let index = data.findIndex((element, index2) => fails(element, pattern, root, appendPath(path, index2)));
855
1093
  if (index > -1) {
856
- problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, path + "[" + index + "]"));
1094
+ problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, appendPath(path, index)));
857
1095
  }
858
1096
  } else if (!data || typeof data != "object") {
859
1097
  problems.push(error("data is not an object, pattern is", data, pattern, path));
@@ -868,7 +1106,7 @@
868
1106
  }
869
1107
  } else {
870
1108
  for (const [patternKey, subpattern] of Object.entries(pattern)) {
871
- let result = fails(data[patternKey], subpattern, root, path + "." + patternKey);
1109
+ let result = fails(data[patternKey], subpattern, root, appendPath(path, patternKey));
872
1110
  if (result) {
873
1111
  problems = problems.concat(result);
874
1112
  }
@@ -885,9 +1123,12 @@
885
1123
  }
886
1124
  return false;
887
1125
  }
888
- function error(message2, found, expected, path, problems) {
1126
+ function error(message2, found, expected, path = "", problems) {
1127
+ let pathParts = pathToArray(path);
889
1128
  let result = {
890
1129
  path,
1130
+ pathString: pathToString(pathParts),
1131
+ pathParts,
891
1132
  message: message2,
892
1133
  found,
893
1134
  expected
@@ -900,24 +1141,9 @@
900
1141
  function warn(message2, data, pattern, path) {
901
1142
  console.warn("\u{1F170}\uFE0F Assert: " + path, message2, pattern, data);
902
1143
  }
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
- };
1144
+
1145
+ // ../../node_modules/@muze-nl/assert/src/assert.mjs
1146
+ globalThis.assert = { ...assert_core_exports };
921
1147
 
922
1148
  // ../metro-oauth2/src/tokenstore.mjs
923
1149
  function tokenStore(site) {
@@ -1019,7 +1245,7 @@
1019
1245
  }
1020
1246
  return oauth2authorized(req, next);
1021
1247
  };
1022
- async function oauth2authorized(req, next) {
1248
+ async function oauth2authorized(req, next, retryState = {}) {
1023
1249
  getTokensFromLocation();
1024
1250
  const accessToken = options.tokens.get("access_token");
1025
1251
  const refreshToken = options.tokens.get("refresh_token");
@@ -1037,12 +1263,21 @@
1037
1263
  }
1038
1264
  return oauth2authorized(req, next);
1039
1265
  } else {
1040
- req = request(req, {
1266
+ const authorizedReq = request(req, {
1041
1267
  headers: {
1042
1268
  Authorization: accessToken.type + " " + accessToken.value
1043
1269
  }
1044
1270
  });
1045
- return next(req);
1271
+ const res = await next(authorizedReq);
1272
+ if (!shouldAuthorizeResponse(res) || retryState.handledRejectedToken) {
1273
+ return res;
1274
+ }
1275
+ options.tokens.delete("access_token");
1276
+ const token = refreshToken ? await refreshAccessToken() : await fetchAccessToken();
1277
+ if (!token) {
1278
+ return response("false");
1279
+ }
1280
+ return oauth2authorized(req, next, { handledRejectedToken: true });
1046
1281
  }
1047
1282
  }
1048
1283
  function getTokensFromLocation() {
@@ -1741,17 +1976,31 @@
1741
1976
  if (res && isJSON(res.headers?.get("Content-Type"))) {
1742
1977
  let tempRes = res.clone();
1743
1978
  let body = await tempRes.text();
1979
+ if (body === "") {
1980
+ return res;
1981
+ }
1744
1982
  try {
1745
1983
  let json2 = JSON.parse(body, options.reviver);
1746
1984
  return res.with({
1747
1985
  body: json2
1748
1986
  });
1749
- } catch (e) {
1987
+ } catch (error2) {
1988
+ if (!res.ok) {
1989
+ return res;
1990
+ }
1991
+ throw parseError(req, res, error2);
1750
1992
  }
1751
1993
  }
1752
1994
  return res;
1753
1995
  };
1754
1996
  }
1997
+ function parseError(req, res, cause) {
1998
+ const message2 = "jsonmw: could not parse " + res.headers.get("Content-Type") + " response from " + req.url;
1999
+ const error2 = new Error(message2, { cause });
2000
+ error2.request = req;
2001
+ error2.response = res;
2002
+ return error2;
2003
+ }
1755
2004
  var jsonRE = /^application\/([a-zA-Z0-9\-_]+\+)?json\b/;
1756
2005
  function isJSON(contentType) {
1757
2006
  return jsonRE.exec(contentType);
@@ -3261,6 +3510,7 @@
3261
3510
  }
3262
3511
  };
3263
3512
  options = Object.assign({}, defaultOptions, options);
3513
+ const requestedClientInfo = options.client_info;
3264
3514
  assert(options, {
3265
3515
  client: Required(instanceOf(client().constructor)),
3266
3516
  // required because it is set in defaultOptions
@@ -3276,7 +3526,10 @@
3276
3526
  options.openid_configuration = options.store.get("openid_configuration");
3277
3527
  }
3278
3528
  if (!options.client_info?.client_id && options.store.has("client_info")) {
3279
- options.client_info = options.store.get("client_info");
3529
+ const storedClientInfo = options.store.get("client_info");
3530
+ if (clientInfoMatchesRequest(storedClientInfo, requestedClientInfo)) {
3531
+ options.client_info = storedClientInfo;
3532
+ }
3280
3533
  }
3281
3534
  return async (req, next) => {
3282
3535
  let res;
@@ -3389,6 +3642,16 @@
3389
3642
  return res;
3390
3643
  };
3391
3644
  }
3645
+ function clientInfoMatchesRequest(storedClientInfo, requestedClientInfo) {
3646
+ if (!storedClientInfo?.client_id) {
3647
+ return false;
3648
+ }
3649
+ if (!Array.isArray(requestedClientInfo?.redirect_uris)) {
3650
+ return true;
3651
+ }
3652
+ const storedRedirectUris = new Set(storedClientInfo.redirect_uris || []);
3653
+ return requestedClientInfo.redirect_uris.every((uri) => storedRedirectUris.has(uri));
3654
+ }
3392
3655
  function isRedirected2() {
3393
3656
  return isRedirected();
3394
3657
  }