antaeus.keycloak.react 2.0.0 → 2.1.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/index.js +65 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ var defaultConfig = {
|
|
|
14
14
|
scope: "openid profile email offline_access",
|
|
15
15
|
features: {
|
|
16
16
|
deviceFlow: false,
|
|
17
|
-
sessionMonitor:
|
|
17
|
+
sessionMonitor: true,
|
|
18
18
|
autoRefresh: true
|
|
19
19
|
},
|
|
20
20
|
silentRenew: {
|
|
@@ -59,7 +59,11 @@ var KeycloakConfigBuilder = class {
|
|
|
59
59
|
scope: config.scope,
|
|
60
60
|
automaticSilentRenew: config.silentRenew.enabled,
|
|
61
61
|
loadUserInfo: config.advanced.loadUserInfo,
|
|
62
|
-
silent_redirect_uri: config.silentRenew.silentRedirectUri
|
|
62
|
+
silent_redirect_uri: config.silentRenew.silentRedirectUri,
|
|
63
|
+
// Add PKCE support (required for public clients)
|
|
64
|
+
...config.advanced.codeChallengeMethod && {
|
|
65
|
+
response_mode: "query"
|
|
66
|
+
}
|
|
63
67
|
};
|
|
64
68
|
return oidcSettings;
|
|
65
69
|
}
|
|
@@ -239,7 +243,11 @@ function useTokenLifecycle(options) {
|
|
|
239
243
|
onRefreshTokenExpired?.();
|
|
240
244
|
const key = getStorageKey();
|
|
241
245
|
localStorage.removeItem(key);
|
|
242
|
-
|
|
246
|
+
try {
|
|
247
|
+
await auth.removeUser();
|
|
248
|
+
} catch (error) {
|
|
249
|
+
log("Error removing user after max lifetime:", error);
|
|
250
|
+
}
|
|
243
251
|
return false;
|
|
244
252
|
}
|
|
245
253
|
const expiresAt = auth.user.expires_at;
|
|
@@ -318,7 +326,9 @@ function useTokenLifecycle(options) {
|
|
|
318
326
|
onRefreshTokenExpired?.();
|
|
319
327
|
const key = getStorageKey();
|
|
320
328
|
localStorage.removeItem(key);
|
|
321
|
-
auth.removeUser()
|
|
329
|
+
auth.removeUser().catch((error) => {
|
|
330
|
+
log("Error removing user during periodic check:", error);
|
|
331
|
+
});
|
|
322
332
|
}
|
|
323
333
|
}, 5 * 60 * 1e3);
|
|
324
334
|
return () => clearInterval(intervalId);
|
|
@@ -495,22 +505,28 @@ var SessionMonitor = ({
|
|
|
495
505
|
}) => {
|
|
496
506
|
const auth = useAuth();
|
|
497
507
|
const [timeRemaining, setTimeRemaining] = useState(null);
|
|
508
|
+
const [initialTimeRemaining, setInitialTimeRemaining] = useState(null);
|
|
498
509
|
const [minimized, setMinimized] = useState(startMinimized);
|
|
499
510
|
const [warningTriggered, setWarningTriggered] = useState(false);
|
|
500
511
|
const [criticalTriggered, setCriticalTriggered] = useState(false);
|
|
501
512
|
useEffect(() => {
|
|
502
513
|
if (!auth.isAuthenticated || !auth.user?.expires_at) {
|
|
503
514
|
setTimeRemaining(null);
|
|
515
|
+
setInitialTimeRemaining(null);
|
|
504
516
|
return;
|
|
505
517
|
}
|
|
518
|
+
let logoutTimeoutId = null;
|
|
506
519
|
const updateTimeRemaining = () => {
|
|
507
520
|
const expiresAt = auth.user.expires_at;
|
|
508
521
|
const now = Math.floor(Date.now() / 1e3);
|
|
509
522
|
const remaining = expiresAt - now;
|
|
523
|
+
if (initialTimeRemaining === null && remaining > 0) {
|
|
524
|
+
setInitialTimeRemaining(remaining);
|
|
525
|
+
}
|
|
510
526
|
if (remaining <= 0) {
|
|
511
527
|
setTimeRemaining(0);
|
|
512
528
|
onExpired?.();
|
|
513
|
-
setTimeout(() => {
|
|
529
|
+
logoutTimeoutId = setTimeout(() => {
|
|
514
530
|
auth.signoutRedirect();
|
|
515
531
|
}, 2e3);
|
|
516
532
|
} else {
|
|
@@ -526,13 +542,19 @@ var SessionMonitor = ({
|
|
|
526
542
|
};
|
|
527
543
|
updateTimeRemaining();
|
|
528
544
|
const interval = setInterval(updateTimeRemaining, 1e3);
|
|
529
|
-
return () =>
|
|
545
|
+
return () => {
|
|
546
|
+
clearInterval(interval);
|
|
547
|
+
if (logoutTimeoutId) {
|
|
548
|
+
clearTimeout(logoutTimeoutId);
|
|
549
|
+
}
|
|
550
|
+
};
|
|
530
551
|
}, [
|
|
531
552
|
auth,
|
|
532
553
|
warningThreshold,
|
|
533
554
|
criticalThreshold,
|
|
534
555
|
warningTriggered,
|
|
535
556
|
criticalTriggered,
|
|
557
|
+
initialTimeRemaining,
|
|
536
558
|
onWarning,
|
|
537
559
|
onCritical,
|
|
538
560
|
onExpired
|
|
@@ -555,9 +577,9 @@ var SessionMonitor = ({
|
|
|
555
577
|
return "normal";
|
|
556
578
|
}, [timeRemaining, warningThreshold, criticalThreshold]);
|
|
557
579
|
const getProgress = useCallback(() => {
|
|
558
|
-
if (!timeRemaining || !
|
|
559
|
-
return timeRemaining /
|
|
560
|
-
}, [timeRemaining,
|
|
580
|
+
if (!timeRemaining || !initialTimeRemaining) return 100;
|
|
581
|
+
return Math.max(0, Math.min(100, timeRemaining / initialTimeRemaining * 100));
|
|
582
|
+
}, [timeRemaining, initialTimeRemaining]);
|
|
561
583
|
if (!auth.isAuthenticated || timeRemaining === null) {
|
|
562
584
|
return null;
|
|
563
585
|
}
|
|
@@ -870,12 +892,27 @@ function buildZeroConfig(props) {
|
|
|
870
892
|
const { authority, clientId, preset = "default", config: overrides = {} } = props;
|
|
871
893
|
const presetConfig = mergeWithPreset(preset, overrides);
|
|
872
894
|
const fullConfig = {
|
|
873
|
-
...defaultConfig,
|
|
874
|
-
...presetConfig,
|
|
875
895
|
authority,
|
|
876
896
|
clientId,
|
|
877
|
-
redirectUri: presetConfig.redirectUri || (typeof window !== "undefined" ? window.location.origin + "/" : "/"),
|
|
878
|
-
postLogoutRedirectUri: presetConfig.postLogoutRedirectUri || (typeof window !== "undefined" ? window.location.origin + "/" : "/")
|
|
897
|
+
redirectUri: presetConfig.redirectUri || defaultConfig.redirectUri || (typeof window !== "undefined" ? window.location.origin + "/" : "/"),
|
|
898
|
+
postLogoutRedirectUri: presetConfig.postLogoutRedirectUri || defaultConfig.postLogoutRedirectUri || (typeof window !== "undefined" ? window.location.origin + "/" : "/"),
|
|
899
|
+
scope: presetConfig.scope || defaultConfig.scope,
|
|
900
|
+
features: {
|
|
901
|
+
...defaultConfig.features,
|
|
902
|
+
...presetConfig.features
|
|
903
|
+
},
|
|
904
|
+
silentRenew: {
|
|
905
|
+
...defaultConfig.silentRenew,
|
|
906
|
+
...presetConfig.silentRenew
|
|
907
|
+
},
|
|
908
|
+
advanced: {
|
|
909
|
+
...defaultConfig.advanced,
|
|
910
|
+
...presetConfig.advanced
|
|
911
|
+
},
|
|
912
|
+
events: {
|
|
913
|
+
...defaultConfig.events,
|
|
914
|
+
...presetConfig.events
|
|
915
|
+
}
|
|
879
916
|
};
|
|
880
917
|
return fullConfig;
|
|
881
918
|
}
|
|
@@ -970,6 +1007,7 @@ var ProtectedRoute = ({
|
|
|
970
1007
|
const { hasAnyRole, hasAllRoles } = useRoles();
|
|
971
1008
|
const { hasAnyScope, hasAllScopes } = useScopes();
|
|
972
1009
|
const location = useLocation();
|
|
1010
|
+
const hasRedirected = useRef(false);
|
|
973
1011
|
const isAuthenticated = !auth.isLoading && auth.isAuthenticated;
|
|
974
1012
|
const policyAccess = policy && auth.user ? policy(auth.user, { location }) : null;
|
|
975
1013
|
const roleAccess = requiredRoles.length > 0 ? requireAllRoles ? hasAllRoles(requiredRoles) : hasAnyRole(requiredRoles) : null;
|
|
@@ -981,12 +1019,21 @@ var ProtectedRoute = ({
|
|
|
981
1019
|
}
|
|
982
1020
|
}, [unauthorizedReason, onUnauthorized]);
|
|
983
1021
|
useEffect(() => {
|
|
984
|
-
if (!auth.isLoading && !auth.isAuthenticated) {
|
|
1022
|
+
if (!auth.isLoading && !auth.isAuthenticated && !hasRedirected.current) {
|
|
1023
|
+
hasRedirected.current = true;
|
|
985
1024
|
auth.signinRedirect({
|
|
986
1025
|
redirect_uri: window.location.origin + location.pathname + location.search
|
|
1026
|
+
}).catch((error) => {
|
|
1027
|
+
hasRedirected.current = false;
|
|
1028
|
+
console.error("[ProtectedRoute] Signin redirect failed:", error);
|
|
987
1029
|
});
|
|
988
1030
|
}
|
|
989
|
-
}, [auth.isLoading, auth.isAuthenticated,
|
|
1031
|
+
}, [auth.isLoading, auth.isAuthenticated, location.pathname, location.search]);
|
|
1032
|
+
useEffect(() => {
|
|
1033
|
+
if (auth.isAuthenticated) {
|
|
1034
|
+
hasRedirected.current = false;
|
|
1035
|
+
}
|
|
1036
|
+
}, [auth.isAuthenticated]);
|
|
990
1037
|
if (auth.isLoading) {
|
|
991
1038
|
return /* @__PURE__ */ jsx(Fragment, { children: loadingComponent || /* @__PURE__ */ jsx(DefaultLoadingComponent, {}) });
|
|
992
1039
|
}
|
|
@@ -1442,14 +1489,14 @@ function useProtectedFetch(options = {}) {
|
|
|
1442
1489
|
},
|
|
1443
1490
|
[baseUrl]
|
|
1444
1491
|
);
|
|
1445
|
-
const getAuthHeader =
|
|
1492
|
+
const getAuthHeader = () => {
|
|
1446
1493
|
if (!auth.user?.access_token) {
|
|
1447
1494
|
return {};
|
|
1448
1495
|
}
|
|
1449
1496
|
return {
|
|
1450
1497
|
Authorization: `Bearer ${auth.user.access_token}`
|
|
1451
1498
|
};
|
|
1452
|
-
}
|
|
1499
|
+
};
|
|
1453
1500
|
const buildHeaders = useCallback(
|
|
1454
1501
|
(requestHeaders) => {
|
|
1455
1502
|
const headers = new Headers(requestHeaders);
|
|
@@ -1462,7 +1509,7 @@ function useProtectedFetch(options = {}) {
|
|
|
1462
1509
|
});
|
|
1463
1510
|
return headers;
|
|
1464
1511
|
},
|
|
1465
|
-
[
|
|
1512
|
+
[customHeaders]
|
|
1466
1513
|
);
|
|
1467
1514
|
const protectedFetch = useCallback(
|
|
1468
1515
|
async (url, init) => {
|