authscape 1.0.766 → 1.0.768
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/index.js +102 -80
- package/package.json +1 -1
- package/src/components/AuthScapeApp.js +45 -20
- package/src/services/apiService.js +55 -53
- package/src/services/authService.js +3 -3
package/index.js
CHANGED
|
@@ -76,19 +76,30 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
|
76
76
|
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
77
77
|
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } // Re-export toast and transitions so pages can import from authscape
|
|
78
78
|
// ============================================================================
|
|
79
|
-
//
|
|
79
|
+
// Auth Redirect Circuit Breaker
|
|
80
80
|
// ============================================================================
|
|
81
|
-
var
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
81
|
+
var AUTH_REDIRECT_KEY = 'authscape_redirect_count';
|
|
82
|
+
var AUTH_REDIRECT_TS_KEY = 'authscape_redirect_ts';
|
|
83
|
+
var AUTH_MAX_REDIRECTS = 3;
|
|
84
|
+
var AUTH_REDIRECT_WINDOW_MS = 30000; // 30 seconds
|
|
85
|
+
|
|
86
|
+
var checkAndIncrementRedirect = function checkAndIncrementRedirect() {
|
|
87
|
+
if (typeof window === 'undefined') return false;
|
|
88
|
+
var now = Date.now();
|
|
89
|
+
var storedTs = parseInt(sessionStorage.getItem(AUTH_REDIRECT_TS_KEY) || '0', 10);
|
|
90
|
+
var count = parseInt(sessionStorage.getItem(AUTH_REDIRECT_KEY) || '0', 10);
|
|
91
|
+
if (now - storedTs > AUTH_REDIRECT_WINDOW_MS) {
|
|
92
|
+
count = 0;
|
|
93
|
+
sessionStorage.setItem(AUTH_REDIRECT_TS_KEY, String(now));
|
|
94
|
+
}
|
|
95
|
+
count += 1;
|
|
96
|
+
sessionStorage.setItem(AUTH_REDIRECT_KEY, String(count));
|
|
97
|
+
return count <= AUTH_MAX_REDIRECTS;
|
|
98
|
+
};
|
|
99
|
+
var resetRedirectCounter = function resetRedirectCounter() {
|
|
100
|
+
if (typeof window === 'undefined') return;
|
|
101
|
+
sessionStorage.removeItem(AUTH_REDIRECT_KEY);
|
|
102
|
+
sessionStorage.removeItem(AUTH_REDIRECT_TS_KEY);
|
|
92
103
|
};
|
|
93
104
|
|
|
94
105
|
// ============================================================================
|
|
@@ -758,6 +769,7 @@ function AuthScapeApp(_ref10) {
|
|
|
758
769
|
var queryCodeUsed = (0, _react.useRef)(null);
|
|
759
770
|
var ga4React = (0, _react.useRef)(null);
|
|
760
771
|
var errorTrackingInitializedRef = (0, _react.useRef)(false);
|
|
772
|
+
var loginRedirectPending = (0, _react.useRef)(false);
|
|
761
773
|
var searchParams = (0, _navigation.useSearchParams)();
|
|
762
774
|
var queryCode = (_searchParams$get = searchParams === null || searchParams === void 0 ? void 0 : searchParams.get("code")) !== null && _searchParams$get !== void 0 ? _searchParams$get : null;
|
|
763
775
|
var pathname = (0, _navigation.usePathname)();
|
|
@@ -783,13 +795,14 @@ function AuthScapeApp(_ref10) {
|
|
|
783
795
|
setIsSigningIn(true);
|
|
784
796
|
codeVerifier = window.localStorage.getItem("verifier");
|
|
785
797
|
if (!(!codeFromQuery || !codeVerifier)) {
|
|
786
|
-
_context8.next =
|
|
798
|
+
_context8.next = 12;
|
|
787
799
|
break;
|
|
788
800
|
}
|
|
789
801
|
window.localStorage.clear();
|
|
790
|
-
|
|
802
|
+
setIsSigningIn(false);
|
|
803
|
+
setFrontEndLoadedState(true);
|
|
791
804
|
return _context8.abrupt("return");
|
|
792
|
-
case
|
|
805
|
+
case 12:
|
|
793
806
|
headers = {
|
|
794
807
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
795
808
|
};
|
|
@@ -801,56 +814,51 @@ function AuthScapeApp(_ref10) {
|
|
|
801
814
|
client_secret: process.env.client_secret,
|
|
802
815
|
code_verifier: codeVerifier
|
|
803
816
|
});
|
|
804
|
-
_context8.prev =
|
|
805
|
-
_context8.next =
|
|
817
|
+
_context8.prev = 14;
|
|
818
|
+
_context8.next = 17;
|
|
806
819
|
return _axios["default"].post(process.env.authorityUri + "/connect/token", body, {
|
|
807
820
|
headers: headers
|
|
808
821
|
});
|
|
809
|
-
case
|
|
822
|
+
case 17:
|
|
810
823
|
response = _context8.sent;
|
|
811
824
|
domainHost = window.location.hostname.split(".").slice(-2).join(".");
|
|
812
825
|
window.localStorage.removeItem("verifier");
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
826
|
+
_jsCookie["default"].set("access_token", response.data.access_token, {
|
|
827
|
+
expires: 365,
|
|
816
828
|
path: "/",
|
|
817
829
|
domain: domainHost,
|
|
818
830
|
secure: true
|
|
819
831
|
});
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
return setCookie("expires_in", response.data.expires_in, {
|
|
823
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
832
|
+
_jsCookie["default"].set("expires_in", String(response.data.expires_in), {
|
|
833
|
+
expires: 365,
|
|
824
834
|
path: "/",
|
|
825
835
|
domain: domainHost,
|
|
826
836
|
secure: true
|
|
827
837
|
});
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
return setCookie("refresh_token", response.data.refresh_token, {
|
|
831
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
838
|
+
_jsCookie["default"].set("refresh_token", response.data.refresh_token, {
|
|
839
|
+
expires: 365,
|
|
832
840
|
path: "/",
|
|
833
841
|
domain: domainHost,
|
|
834
842
|
secure: true
|
|
835
843
|
});
|
|
836
|
-
|
|
844
|
+
resetRedirectCounter();
|
|
837
845
|
redirectUri = window.localStorage.getItem("redirectUri") || "/";
|
|
838
846
|
window.localStorage.clear();
|
|
839
847
|
window.location.href = redirectUri;
|
|
840
|
-
_context8.next =
|
|
848
|
+
_context8.next = 35;
|
|
841
849
|
break;
|
|
842
|
-
case
|
|
843
|
-
_context8.prev =
|
|
844
|
-
_context8.t0 = _context8["catch"](
|
|
850
|
+
case 29:
|
|
851
|
+
_context8.prev = 29;
|
|
852
|
+
_context8.t0 = _context8["catch"](14);
|
|
845
853
|
console.error("PKCE sign-in failed", _context8.t0);
|
|
846
854
|
window.localStorage.clear();
|
|
847
855
|
setIsSigningIn(false);
|
|
848
|
-
|
|
849
|
-
case
|
|
856
|
+
setFrontEndLoadedState(true);
|
|
857
|
+
case 35:
|
|
850
858
|
case "end":
|
|
851
859
|
return _context8.stop();
|
|
852
860
|
}
|
|
853
|
-
}, _callee8, null, [[
|
|
861
|
+
}, _callee8, null, [[14, 29]]);
|
|
854
862
|
}));
|
|
855
863
|
return function signInValidator(_x4) {
|
|
856
864
|
return _ref11.apply(this, arguments);
|
|
@@ -961,7 +969,12 @@ function AuthScapeApp(_ref10) {
|
|
|
961
969
|
};
|
|
962
970
|
}, [frontEndLoadedState, pageProps.googleAnalytics4Code, pageProps.microsoftClarityCode]);
|
|
963
971
|
(0, _react.useEffect)(function () {
|
|
964
|
-
if (enforceLoggedIn && pathname !== "/signin-oidc" && frontEndLoadedState && !signedInUserState) {
|
|
972
|
+
if (enforceLoggedIn && pathname !== "/signin-oidc" && frontEndLoadedState && !signedInUserState && !loginRedirectPending.current) {
|
|
973
|
+
if (!checkAndIncrementRedirect()) {
|
|
974
|
+
console.warn('[AuthScape] Auth redirect loop detected — halting redirects.');
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
loginRedirectPending.current = true;
|
|
965
978
|
module.exports.authService().login();
|
|
966
979
|
}
|
|
967
980
|
}, [signedInUserState, enforceLoggedIn, frontEndLoadedState, pathname]);
|
|
@@ -9599,19 +9612,6 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
9599
9612
|
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, "catch": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
9600
9613
|
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
9601
9614
|
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
9602
|
-
// Cookie utility function
|
|
9603
|
-
var setCookie = function setCookie(name, value) {
|
|
9604
|
-
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
9605
|
-
return new Promise(function (resolve) {
|
|
9606
|
-
var cookieString = "".concat(name, "=").concat(value, ";");
|
|
9607
|
-
if (options.maxAge) cookieString += "max-age=".concat(options.maxAge, ";");
|
|
9608
|
-
if (options.path) cookieString += "path=".concat(options.path, ";");
|
|
9609
|
-
if (options.domain) cookieString += "domain=".concat(options.domain, ";");
|
|
9610
|
-
if (options.secure) cookieString += "secure;";
|
|
9611
|
-
document.cookie = cookieString;
|
|
9612
|
-
resolve();
|
|
9613
|
-
});
|
|
9614
|
-
};
|
|
9615
9615
|
var setupDefaultOptions = /*#__PURE__*/function () {
|
|
9616
9616
|
var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
|
9617
9617
|
var ctx,
|
|
@@ -9658,9 +9658,16 @@ var RefreshToken = /*#__PURE__*/function () {
|
|
|
9658
9658
|
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
9659
9659
|
while (1) switch (_context2.prev = _context2.next) {
|
|
9660
9660
|
case 0:
|
|
9661
|
+
_context2.prev = 0;
|
|
9661
9662
|
accessToken = _jsCookie["default"].get('access_token') || '';
|
|
9662
9663
|
refreshToken = _jsCookie["default"].get('refresh_token') || '';
|
|
9663
|
-
|
|
9664
|
+
if (refreshToken) {
|
|
9665
|
+
_context2.next = 5;
|
|
9666
|
+
break;
|
|
9667
|
+
}
|
|
9668
|
+
return _context2.abrupt("return", false);
|
|
9669
|
+
case 5:
|
|
9670
|
+
_context2.next = 7;
|
|
9664
9671
|
return instance.post(process.env.authorityUri + "/connect/token", _queryString["default"].stringify({
|
|
9665
9672
|
grant_type: 'refresh_token',
|
|
9666
9673
|
client_id: process.env.client_id,
|
|
@@ -9672,42 +9679,44 @@ var RefreshToken = /*#__PURE__*/function () {
|
|
|
9672
9679
|
"Authorization": "Bearer " + accessToken
|
|
9673
9680
|
}
|
|
9674
9681
|
});
|
|
9675
|
-
case
|
|
9682
|
+
case 7:
|
|
9676
9683
|
response = _context2.sent;
|
|
9677
9684
|
if (!(response != null && response.status == 200)) {
|
|
9678
|
-
_context2.next =
|
|
9685
|
+
_context2.next = 15;
|
|
9679
9686
|
break;
|
|
9680
9687
|
}
|
|
9681
9688
|
domainHost = window.location.hostname.split('.').slice(-2).join('.');
|
|
9682
9689
|
originalRequest.headers['Authorization'] = 'Bearer ' + response.data.access_token;
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
9690
|
+
_jsCookie["default"].set('access_token', response.data.access_token, {
|
|
9691
|
+
expires: 365,
|
|
9686
9692
|
path: '/',
|
|
9687
9693
|
domain: domainHost,
|
|
9688
9694
|
secure: true
|
|
9689
9695
|
});
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
return setCookie('expires_in', response.data.expires_in, {
|
|
9693
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
9696
|
+
_jsCookie["default"].set('expires_in', String(response.data.expires_in), {
|
|
9697
|
+
expires: 365,
|
|
9694
9698
|
path: '/',
|
|
9695
9699
|
domain: domainHost,
|
|
9696
9700
|
secure: true
|
|
9697
9701
|
});
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
return setCookie('refresh_token', response.data.refresh_token, {
|
|
9701
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
9702
|
+
_jsCookie["default"].set('refresh_token', response.data.refresh_token, {
|
|
9703
|
+
expires: 365,
|
|
9702
9704
|
path: '/',
|
|
9703
9705
|
domain: domainHost,
|
|
9704
9706
|
secure: true
|
|
9705
9707
|
});
|
|
9706
|
-
|
|
9708
|
+
return _context2.abrupt("return", true);
|
|
9709
|
+
case 15:
|
|
9710
|
+
return _context2.abrupt("return", false);
|
|
9711
|
+
case 18:
|
|
9712
|
+
_context2.prev = 18;
|
|
9713
|
+
_context2.t0 = _context2["catch"](0);
|
|
9714
|
+
return _context2.abrupt("return", false);
|
|
9715
|
+
case 21:
|
|
9707
9716
|
case "end":
|
|
9708
9717
|
return _context2.stop();
|
|
9709
9718
|
}
|
|
9710
|
-
}, _callee2);
|
|
9719
|
+
}, _callee2, null, [[0, 18]]);
|
|
9711
9720
|
}));
|
|
9712
9721
|
return function RefreshToken(_x, _x2) {
|
|
9713
9722
|
return _ref2.apply(this, arguments);
|
|
@@ -9728,48 +9737,58 @@ var apiService = exports.apiService = function apiService() {
|
|
|
9728
9737
|
return response;
|
|
9729
9738
|
}, /*#__PURE__*/function () {
|
|
9730
9739
|
var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(error) {
|
|
9731
|
-
var originalConfig, domainHost;
|
|
9740
|
+
var originalConfig, refreshed, domainHost;
|
|
9732
9741
|
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
9733
9742
|
while (1) switch (_context3.prev = _context3.next) {
|
|
9734
9743
|
case 0:
|
|
9735
9744
|
originalConfig = error.config;
|
|
9736
9745
|
if (!error.response) {
|
|
9737
|
-
_context3.next =
|
|
9746
|
+
_context3.next = 13;
|
|
9738
9747
|
break;
|
|
9739
9748
|
}
|
|
9740
9749
|
if (!(error.response.status === 401 && !originalConfig._retry)) {
|
|
9741
|
-
_context3.next =
|
|
9750
|
+
_context3.next = 10;
|
|
9742
9751
|
break;
|
|
9743
9752
|
}
|
|
9744
9753
|
originalConfig._retry = true;
|
|
9745
9754
|
_context3.next = 6;
|
|
9746
9755
|
return RefreshToken(originalConfig, instance);
|
|
9747
9756
|
case 6:
|
|
9757
|
+
refreshed = _context3.sent;
|
|
9758
|
+
if (!refreshed) {
|
|
9759
|
+
_context3.next = 9;
|
|
9760
|
+
break;
|
|
9761
|
+
}
|
|
9748
9762
|
return _context3.abrupt("return", instance.request(originalConfig));
|
|
9749
|
-
case
|
|
9763
|
+
case 9:
|
|
9764
|
+
return _context3.abrupt("return", Promise.reject(error));
|
|
9765
|
+
case 10:
|
|
9750
9766
|
if (!(error.response.status === 400)) {
|
|
9751
|
-
_context3.next =
|
|
9767
|
+
_context3.next = 13;
|
|
9752
9768
|
break;
|
|
9753
9769
|
}
|
|
9754
9770
|
if (error.response.config.url.includes("/connect/token")) {
|
|
9755
9771
|
domainHost = window.location.hostname.split('.').slice(-2).join('.');
|
|
9756
9772
|
_jsCookie["default"].remove('access_token', {
|
|
9757
9773
|
path: '/',
|
|
9758
|
-
domain: domainHost
|
|
9774
|
+
domain: domainHost,
|
|
9775
|
+
secure: true
|
|
9759
9776
|
});
|
|
9760
9777
|
_jsCookie["default"].remove('refresh_token', {
|
|
9761
9778
|
path: '/',
|
|
9762
|
-
domain: domainHost
|
|
9779
|
+
domain: domainHost,
|
|
9780
|
+
secure: true
|
|
9763
9781
|
});
|
|
9764
9782
|
_jsCookie["default"].remove('expires_in', {
|
|
9765
9783
|
path: '/',
|
|
9766
|
-
domain: domainHost
|
|
9784
|
+
domain: domainHost,
|
|
9785
|
+
secure: true
|
|
9767
9786
|
});
|
|
9768
9787
|
}
|
|
9769
9788
|
return _context3.abrupt("return", Promise.reject(error));
|
|
9770
|
-
case
|
|
9789
|
+
case 13:
|
|
9771
9790
|
return _context3.abrupt("return", Promise.reject(error));
|
|
9772
|
-
case
|
|
9791
|
+
case 14:
|
|
9773
9792
|
case "end":
|
|
9774
9793
|
return _context3.stop();
|
|
9775
9794
|
}
|
|
@@ -10318,15 +10337,18 @@ var _authService = exports.authService = function authService() {
|
|
|
10318
10337
|
AuthUri = process.env.authorityUri;
|
|
10319
10338
|
_jsCookie["default"].remove('access_token', {
|
|
10320
10339
|
path: '/',
|
|
10321
|
-
domain: domainHost
|
|
10340
|
+
domain: domainHost,
|
|
10341
|
+
secure: true
|
|
10322
10342
|
});
|
|
10323
10343
|
_jsCookie["default"].remove('refresh_token', {
|
|
10324
10344
|
path: '/',
|
|
10325
|
-
domain: domainHost
|
|
10345
|
+
domain: domainHost,
|
|
10346
|
+
secure: true
|
|
10326
10347
|
});
|
|
10327
10348
|
_jsCookie["default"].remove('expires_in', {
|
|
10328
10349
|
path: '/',
|
|
10329
|
-
domain: domainHost
|
|
10350
|
+
domain: domainHost,
|
|
10351
|
+
secure: true
|
|
10330
10352
|
});
|
|
10331
10353
|
|
|
10332
10354
|
// destroyCookie({}, "access_token", {
|
package/package.json
CHANGED
|
@@ -17,18 +17,33 @@ import { HubConnectionBuilder, LogLevel, HttpTransportType } from '@microsoft/si
|
|
|
17
17
|
import Cookies from 'js-cookie';
|
|
18
18
|
|
|
19
19
|
// ============================================================================
|
|
20
|
-
//
|
|
20
|
+
// Auth Redirect Circuit Breaker
|
|
21
21
|
// ============================================================================
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
const AUTH_REDIRECT_KEY = 'authscape_redirect_count';
|
|
23
|
+
const AUTH_REDIRECT_TS_KEY = 'authscape_redirect_ts';
|
|
24
|
+
const AUTH_MAX_REDIRECTS = 3;
|
|
25
|
+
const AUTH_REDIRECT_WINDOW_MS = 30000; // 30 seconds
|
|
26
|
+
|
|
27
|
+
const checkAndIncrementRedirect = () => {
|
|
28
|
+
if (typeof window === 'undefined') return false;
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
const storedTs = parseInt(sessionStorage.getItem(AUTH_REDIRECT_TS_KEY) || '0', 10);
|
|
31
|
+
let count = parseInt(sessionStorage.getItem(AUTH_REDIRECT_KEY) || '0', 10);
|
|
32
|
+
|
|
33
|
+
if (now - storedTs > AUTH_REDIRECT_WINDOW_MS) {
|
|
34
|
+
count = 0;
|
|
35
|
+
sessionStorage.setItem(AUTH_REDIRECT_TS_KEY, String(now));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
count += 1;
|
|
39
|
+
sessionStorage.setItem(AUTH_REDIRECT_KEY, String(count));
|
|
40
|
+
return count <= AUTH_MAX_REDIRECTS;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const resetRedirectCounter = () => {
|
|
44
|
+
if (typeof window === 'undefined') return;
|
|
45
|
+
sessionStorage.removeItem(AUTH_REDIRECT_KEY);
|
|
46
|
+
sessionStorage.removeItem(AUTH_REDIRECT_TS_KEY);
|
|
32
47
|
};
|
|
33
48
|
|
|
34
49
|
// ============================================================================
|
|
@@ -484,6 +499,7 @@ export function AuthScapeApp({
|
|
|
484
499
|
const queryCodeUsed = useRef(null);
|
|
485
500
|
const ga4React = useRef(null);
|
|
486
501
|
const errorTrackingInitializedRef = useRef(false);
|
|
502
|
+
const loginRedirectPending = useRef(false);
|
|
487
503
|
|
|
488
504
|
const searchParams = useSearchParams();
|
|
489
505
|
const queryCode = searchParams?.get("code") ?? null;
|
|
@@ -500,7 +516,8 @@ export function AuthScapeApp({
|
|
|
500
516
|
const codeVerifier = window.localStorage.getItem("verifier");
|
|
501
517
|
if (!codeFromQuery || !codeVerifier) {
|
|
502
518
|
window.localStorage.clear();
|
|
503
|
-
|
|
519
|
+
setIsSigningIn(false);
|
|
520
|
+
setFrontEndLoadedState(true);
|
|
504
521
|
return;
|
|
505
522
|
}
|
|
506
523
|
|
|
@@ -526,25 +543,27 @@ export function AuthScapeApp({
|
|
|
526
543
|
|
|
527
544
|
window.localStorage.removeItem("verifier");
|
|
528
545
|
|
|
529
|
-
|
|
530
|
-
|
|
546
|
+
Cookies.set("access_token", response.data.access_token, {
|
|
547
|
+
expires: 365,
|
|
531
548
|
path: "/",
|
|
532
549
|
domain: domainHost,
|
|
533
550
|
secure: true,
|
|
534
551
|
});
|
|
535
|
-
|
|
536
|
-
|
|
552
|
+
Cookies.set("expires_in", String(response.data.expires_in), {
|
|
553
|
+
expires: 365,
|
|
537
554
|
path: "/",
|
|
538
555
|
domain: domainHost,
|
|
539
556
|
secure: true,
|
|
540
557
|
});
|
|
541
|
-
|
|
542
|
-
|
|
558
|
+
Cookies.set("refresh_token", response.data.refresh_token, {
|
|
559
|
+
expires: 365,
|
|
543
560
|
path: "/",
|
|
544
561
|
domain: domainHost,
|
|
545
562
|
secure: true,
|
|
546
563
|
});
|
|
547
564
|
|
|
565
|
+
resetRedirectCounter();
|
|
566
|
+
|
|
548
567
|
const redirectUri = window.localStorage.getItem("redirectUri") || "/";
|
|
549
568
|
window.localStorage.clear();
|
|
550
569
|
|
|
@@ -553,7 +572,7 @@ export function AuthScapeApp({
|
|
|
553
572
|
console.error("PKCE sign-in failed", exp);
|
|
554
573
|
window.localStorage.clear();
|
|
555
574
|
setIsSigningIn(false);
|
|
556
|
-
|
|
575
|
+
setFrontEndLoadedState(true);
|
|
557
576
|
}
|
|
558
577
|
};
|
|
559
578
|
|
|
@@ -653,8 +672,14 @@ export function AuthScapeApp({
|
|
|
653
672
|
enforceLoggedIn &&
|
|
654
673
|
pathname !== "/signin-oidc" &&
|
|
655
674
|
frontEndLoadedState &&
|
|
656
|
-
!signedInUserState
|
|
675
|
+
!signedInUserState &&
|
|
676
|
+
!loginRedirectPending.current
|
|
657
677
|
) {
|
|
678
|
+
if (!checkAndIncrementRedirect()) {
|
|
679
|
+
console.warn('[AuthScape] Auth redirect loop detected — halting redirects.');
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
loginRedirectPending.current = true;
|
|
658
683
|
module.exports.authService().login();
|
|
659
684
|
}
|
|
660
685
|
}, [signedInUserState, enforceLoggedIn, frontEndLoadedState, pathname]);
|
|
@@ -3,19 +3,6 @@ import querystring from 'query-string';
|
|
|
3
3
|
import fileDownload from 'js-file-download';
|
|
4
4
|
import Cookies from 'js-cookie';
|
|
5
5
|
|
|
6
|
-
// Cookie utility function
|
|
7
|
-
const setCookie = (name, value, options = {}) => {
|
|
8
|
-
return new Promise((resolve) => {
|
|
9
|
-
let cookieString = `${name}=${value};`;
|
|
10
|
-
if (options.maxAge) cookieString += `max-age=${options.maxAge};`;
|
|
11
|
-
if (options.path) cookieString += `path=${options.path};`;
|
|
12
|
-
if (options.domain) cookieString += `domain=${options.domain};`;
|
|
13
|
-
if (options.secure) cookieString += `secure;`;
|
|
14
|
-
document.cookie = cookieString;
|
|
15
|
-
resolve();
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
|
|
19
6
|
const setupDefaultOptions = async (ctx = null) => {
|
|
20
7
|
let defaultOptions = {};
|
|
21
8
|
if (ctx == null) {
|
|
@@ -42,46 +29,58 @@ const setupDefaultOptions = async (ctx = null) => {
|
|
|
42
29
|
}
|
|
43
30
|
|
|
44
31
|
const RefreshToken = async (originalRequest, instance) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
let response = await instance.post(process.env.authorityUri + "/connect/token",
|
|
49
|
-
querystring.stringify({
|
|
50
|
-
grant_type: 'refresh_token',
|
|
51
|
-
client_id: process.env.client_id,
|
|
52
|
-
client_secret: process.env.client_secret,
|
|
53
|
-
refresh_token: refreshToken
|
|
54
|
-
}), {
|
|
55
|
-
headers: {
|
|
56
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
57
|
-
"Authorization": "Bearer " + accessToken
|
|
58
|
-
}
|
|
59
|
-
});
|
|
32
|
+
try {
|
|
33
|
+
let accessToken = Cookies.get('access_token') || '';
|
|
34
|
+
let refreshToken = Cookies.get('refresh_token') || '';
|
|
60
35
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
36
|
+
if (!refreshToken) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
64
39
|
|
|
65
|
-
await
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
40
|
+
let response = await instance.post(process.env.authorityUri + "/connect/token",
|
|
41
|
+
querystring.stringify({
|
|
42
|
+
grant_type: 'refresh_token',
|
|
43
|
+
client_id: process.env.client_id,
|
|
44
|
+
client_secret: process.env.client_secret,
|
|
45
|
+
refresh_token: refreshToken
|
|
46
|
+
}), {
|
|
47
|
+
headers: {
|
|
48
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
49
|
+
"Authorization": "Bearer " + accessToken
|
|
50
|
+
}
|
|
70
51
|
});
|
|
71
52
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
53
|
+
if (response != null && response.status == 200) {
|
|
54
|
+
let domainHost = window.location.hostname.split('.').slice(-2).join('.');
|
|
55
|
+
originalRequest.headers['Authorization'] = 'Bearer ' + response.data.access_token;
|
|
56
|
+
|
|
57
|
+
Cookies.set('access_token', response.data.access_token, {
|
|
58
|
+
expires: 365,
|
|
59
|
+
path: '/',
|
|
60
|
+
domain: domainHost,
|
|
61
|
+
secure: true
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
Cookies.set('expires_in', String(response.data.expires_in), {
|
|
65
|
+
expires: 365,
|
|
66
|
+
path: '/',
|
|
67
|
+
domain: domainHost,
|
|
68
|
+
secure: true
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
Cookies.set('refresh_token', response.data.refresh_token, {
|
|
72
|
+
expires: 365,
|
|
73
|
+
path: '/',
|
|
74
|
+
domain: domainHost,
|
|
75
|
+
secure: true
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
domain: domainHost,
|
|
83
|
-
secure: true
|
|
84
|
-
});
|
|
81
|
+
return false;
|
|
82
|
+
} catch (err) {
|
|
83
|
+
return false;
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
86
|
|
|
@@ -107,16 +106,19 @@ export const apiService = (ctx = null) => {
|
|
|
107
106
|
if (error.response) {
|
|
108
107
|
if (error.response.status === 401 && !originalConfig._retry) {
|
|
109
108
|
originalConfig._retry = true;
|
|
110
|
-
await RefreshToken(originalConfig, instance);
|
|
111
|
-
|
|
109
|
+
const refreshed = await RefreshToken(originalConfig, instance);
|
|
110
|
+
if (refreshed) {
|
|
111
|
+
return instance.request(originalConfig);
|
|
112
|
+
}
|
|
113
|
+
return Promise.reject(error);
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
if (error.response.status === 400) {
|
|
115
117
|
if (error.response.config.url.includes("/connect/token")) {
|
|
116
118
|
let domainHost = window.location.hostname.split('.').slice(-2).join('.');
|
|
117
|
-
Cookies.remove('access_token', { path: '/', domain: domainHost });
|
|
118
|
-
Cookies.remove('refresh_token', { path: '/', domain: domainHost });
|
|
119
|
-
Cookies.remove('expires_in', { path: '/', domain: domainHost });
|
|
119
|
+
Cookies.remove('access_token', { path: '/', domain: domainHost, secure: true });
|
|
120
|
+
Cookies.remove('refresh_token', { path: '/', domain: domainHost, secure: true });
|
|
121
|
+
Cookies.remove('expires_in', { path: '/', domain: domainHost, secure: true });
|
|
120
122
|
}
|
|
121
123
|
return Promise.reject(error);
|
|
122
124
|
}
|
|
@@ -127,9 +127,9 @@ export const authService = () => {
|
|
|
127
127
|
let AuthUri = process.env.authorityUri;
|
|
128
128
|
|
|
129
129
|
|
|
130
|
-
Cookies.remove('access_token', { path: '/', domain: domainHost });
|
|
131
|
-
Cookies.remove('refresh_token', { path: '/', domain: domainHost });
|
|
132
|
-
Cookies.remove('expires_in', { path: '/', domain: domainHost });
|
|
130
|
+
Cookies.remove('access_token', { path: '/', domain: domainHost, secure: true });
|
|
131
|
+
Cookies.remove('refresh_token', { path: '/', domain: domainHost, secure: true });
|
|
132
|
+
Cookies.remove('expires_in', { path: '/', domain: domainHost, secure: true });
|
|
133
133
|
|
|
134
134
|
|
|
135
135
|
// destroyCookie({}, "access_token", {
|