antaeus.keycloak.react 2.6.2 → 2.7.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/README.md +52 -0
- package/dist/index.d.mts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +138 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +134 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
package/dist/index.mjs
CHANGED
|
@@ -33,7 +33,8 @@ var defaultConfig = {
|
|
|
33
33
|
// 30 days in seconds
|
|
34
34
|
showLoadingIndicator: false,
|
|
35
35
|
loadingMessage: "Refreshing session...",
|
|
36
|
-
useRefreshToken: true
|
|
36
|
+
useRefreshToken: true,
|
|
37
|
+
refreshOnResume: true
|
|
37
38
|
},
|
|
38
39
|
advanced: {
|
|
39
40
|
responseType: "code",
|
|
@@ -188,6 +189,7 @@ function useTokenLifecycle(options) {
|
|
|
188
189
|
const auth = useAuth();
|
|
189
190
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
|
190
191
|
const [isRefreshTokenExpired, setIsRefreshTokenExpired] = useState(false);
|
|
192
|
+
const isRefreshingRef = useRef(false);
|
|
191
193
|
const hasCheckedOnStartup = useRef(false);
|
|
192
194
|
const supportsRefreshTokens = config.silentRenew?.useRefreshToken !== false;
|
|
193
195
|
const [pendingRetry, setPendingRetry] = useState(null);
|
|
@@ -240,10 +242,11 @@ function useTokenLifecycle(options) {
|
|
|
240
242
|
return elapsedSeconds >= maxLifetime;
|
|
241
243
|
}, [config.silentRenew?.maxRefreshTokenLifetime, getStorageKey, log, storeFirstLoginTime]);
|
|
242
244
|
const refreshToken = useCallback(async () => {
|
|
243
|
-
if (
|
|
245
|
+
if (isRefreshingRef.current) {
|
|
244
246
|
log("Refresh already in progress, skipping");
|
|
245
247
|
return;
|
|
246
248
|
}
|
|
249
|
+
isRefreshingRef.current = true;
|
|
247
250
|
setIsRefreshing(true);
|
|
248
251
|
deferredRefreshReasonRef.current = null;
|
|
249
252
|
try {
|
|
@@ -299,10 +302,10 @@ function useTokenLifecycle(options) {
|
|
|
299
302
|
onRefreshError?.(err);
|
|
300
303
|
throw err;
|
|
301
304
|
} finally {
|
|
305
|
+
isRefreshingRef.current = false;
|
|
302
306
|
setIsRefreshing(false);
|
|
303
307
|
}
|
|
304
308
|
}, [
|
|
305
|
-
isRefreshing,
|
|
306
309
|
auth,
|
|
307
310
|
checkRefreshTokenLifetime,
|
|
308
311
|
onRefreshStart,
|
|
@@ -313,6 +316,38 @@ function useTokenLifecycle(options) {
|
|
|
313
316
|
getStorageKey,
|
|
314
317
|
log
|
|
315
318
|
]);
|
|
319
|
+
const shouldRefreshOnResume = useCallback((reason) => {
|
|
320
|
+
const silentRenewEnabled = config.silentRenew?.enabled !== false;
|
|
321
|
+
const refreshOnResume = config.silentRenew?.refreshOnResume !== false;
|
|
322
|
+
const strategy = config.silentRenew?.refreshStrategy || "both";
|
|
323
|
+
const strategyAllowsResume = strategy === "startup" || strategy === "both";
|
|
324
|
+
const hasRefreshToken = Boolean(auth.user?.refresh_token);
|
|
325
|
+
if (!silentRenewEnabled || !refreshOnResume || !strategyAllowsResume) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
if (auth.isLoading) {
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
if (!auth.user) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
if (supportsRefreshTokens && !hasRefreshToken) {
|
|
335
|
+
log("Skipping resume token check because no refresh token is available:", reason);
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
if (reason !== "online" && typeof document !== "undefined" && document.visibilityState === "hidden") {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
return true;
|
|
342
|
+
}, [
|
|
343
|
+
auth.isLoading,
|
|
344
|
+
auth.user,
|
|
345
|
+
config.silentRenew?.enabled,
|
|
346
|
+
config.silentRenew?.refreshOnResume,
|
|
347
|
+
config.silentRenew?.refreshStrategy,
|
|
348
|
+
supportsRefreshTokens,
|
|
349
|
+
log
|
|
350
|
+
]);
|
|
316
351
|
const checkAndRefreshTokens = useCallback(async () => {
|
|
317
352
|
if (!auth.user) {
|
|
318
353
|
log("No user session, skipping token check");
|
|
@@ -460,6 +495,38 @@ function useTokenLifecycle(options) {
|
|
|
460
495
|
checkAndRefreshTokens,
|
|
461
496
|
log
|
|
462
497
|
]);
|
|
498
|
+
useEffect(() => {
|
|
499
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
const runResumeCheck = (reason) => {
|
|
503
|
+
if (!shouldRefreshOnResume(reason)) {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
log("Running resume token check after:", reason);
|
|
507
|
+
checkAndRefreshTokens().catch((error) => {
|
|
508
|
+
log("Resume token check failed:", error);
|
|
509
|
+
});
|
|
510
|
+
};
|
|
511
|
+
const handleVisibilityChange = () => {
|
|
512
|
+
if (document.visibilityState === "visible") {
|
|
513
|
+
runResumeCheck("visibilitychange");
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
const handlePageShow = () => runResumeCheck("pageshow");
|
|
517
|
+
const handleFocus = () => runResumeCheck("focus");
|
|
518
|
+
const handleOnline = () => runResumeCheck("online");
|
|
519
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
520
|
+
window.addEventListener("pageshow", handlePageShow);
|
|
521
|
+
window.addEventListener("focus", handleFocus);
|
|
522
|
+
window.addEventListener("online", handleOnline);
|
|
523
|
+
return () => {
|
|
524
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
525
|
+
window.removeEventListener("pageshow", handlePageShow);
|
|
526
|
+
window.removeEventListener("focus", handleFocus);
|
|
527
|
+
window.removeEventListener("online", handleOnline);
|
|
528
|
+
};
|
|
529
|
+
}, [checkAndRefreshTokens, log, shouldRefreshOnResume]);
|
|
463
530
|
useEffect(() => {
|
|
464
531
|
if (hasCheckedOnStartup.current) {
|
|
465
532
|
const hasUser = Boolean(auth.user);
|
|
@@ -882,7 +949,8 @@ var CONFIG_PRESETS = {
|
|
|
882
949
|
maxRefreshTokenLifetime: 2592e3,
|
|
883
950
|
// 30 days
|
|
884
951
|
showLoadingIndicator: false,
|
|
885
|
-
loadingMessage: "Refreshing session..."
|
|
952
|
+
loadingMessage: "Refreshing session...",
|
|
953
|
+
refreshOnResume: true
|
|
886
954
|
},
|
|
887
955
|
advanced: {
|
|
888
956
|
responseType: "code",
|
|
@@ -918,7 +986,8 @@ var CONFIG_PRESETS = {
|
|
|
918
986
|
// 30 days
|
|
919
987
|
showLoadingIndicator: true,
|
|
920
988
|
// Show loading for better UX
|
|
921
|
-
loadingMessage: "Restoring your session..."
|
|
989
|
+
loadingMessage: "Restoring your session...",
|
|
990
|
+
refreshOnResume: true
|
|
922
991
|
},
|
|
923
992
|
advanced: {
|
|
924
993
|
responseType: "code",
|
|
@@ -955,7 +1024,8 @@ var CONFIG_PRESETS = {
|
|
|
955
1024
|
// 24 hours only
|
|
956
1025
|
showLoadingIndicator: false,
|
|
957
1026
|
// Silent for security
|
|
958
|
-
loadingMessage: "Validating session..."
|
|
1027
|
+
loadingMessage: "Validating session...",
|
|
1028
|
+
refreshOnResume: true
|
|
959
1029
|
},
|
|
960
1030
|
advanced: {
|
|
961
1031
|
responseType: "code",
|
|
@@ -989,7 +1059,8 @@ var CONFIG_PRESETS = {
|
|
|
989
1059
|
maxRefreshTokenLifetime: 604800,
|
|
990
1060
|
// 7 days
|
|
991
1061
|
showLoadingIndicator: false,
|
|
992
|
-
loadingMessage: "Refreshing session..."
|
|
1062
|
+
loadingMessage: "Refreshing session...",
|
|
1063
|
+
refreshOnResume: true
|
|
993
1064
|
},
|
|
994
1065
|
advanced: {
|
|
995
1066
|
responseType: "code",
|
|
@@ -1026,7 +1097,8 @@ var CONFIG_PRESETS = {
|
|
|
1026
1097
|
// No limit (for convenience)
|
|
1027
1098
|
showLoadingIndicator: true,
|
|
1028
1099
|
// Show for debugging
|
|
1029
|
-
loadingMessage: "[DEV] Refreshing tokens..."
|
|
1100
|
+
loadingMessage: "[DEV] Refreshing tokens...",
|
|
1101
|
+
refreshOnResume: true
|
|
1030
1102
|
},
|
|
1031
1103
|
advanced: {
|
|
1032
1104
|
responseType: "code",
|
|
@@ -1920,6 +1992,59 @@ function useProtectedFetch(options = {}) {
|
|
|
1920
1992
|
};
|
|
1921
1993
|
}
|
|
1922
1994
|
|
|
1995
|
+
// src/utils/storedOidcSession.ts
|
|
1996
|
+
var getOidcUserStorageKey = (authority, clientId) => {
|
|
1997
|
+
if (!authority || !clientId) {
|
|
1998
|
+
return null;
|
|
1999
|
+
}
|
|
2000
|
+
return `oidc.user:${authority}:${clientId}`;
|
|
2001
|
+
};
|
|
2002
|
+
var getStoredOidcUser = ({
|
|
2003
|
+
authority,
|
|
2004
|
+
clientId,
|
|
2005
|
+
storage
|
|
2006
|
+
}) => {
|
|
2007
|
+
const storageKey = getOidcUserStorageKey(authority, clientId);
|
|
2008
|
+
if (!storageKey || !storage) {
|
|
2009
|
+
return null;
|
|
2010
|
+
}
|
|
2011
|
+
try {
|
|
2012
|
+
const storedUser = storage.getItem(storageKey);
|
|
2013
|
+
if (!storedUser) {
|
|
2014
|
+
return null;
|
|
2015
|
+
}
|
|
2016
|
+
return JSON.parse(storedUser);
|
|
2017
|
+
} catch {
|
|
2018
|
+
return null;
|
|
2019
|
+
}
|
|
2020
|
+
};
|
|
2021
|
+
var hasStoredOidcRefreshToken = (args) => {
|
|
2022
|
+
const storedUser = getStoredOidcUser(args);
|
|
2023
|
+
return typeof storedUser?.refresh_token === "string" && storedUser.refresh_token.length > 0;
|
|
2024
|
+
};
|
|
2025
|
+
var getStoredOidcSession = (args) => {
|
|
2026
|
+
const storageKey = getOidcUserStorageKey(args.authority, args.clientId);
|
|
2027
|
+
const storedUser = getStoredOidcUser(args);
|
|
2028
|
+
return {
|
|
2029
|
+
storageKey,
|
|
2030
|
+
storedUser,
|
|
2031
|
+
hasStoredUser: storedUser !== null,
|
|
2032
|
+
hasRefreshToken: typeof storedUser?.refresh_token === "string" && storedUser.refresh_token.length > 0
|
|
2033
|
+
};
|
|
2034
|
+
};
|
|
2035
|
+
|
|
2036
|
+
// src/hooks/useStoredOidcSession.ts
|
|
2037
|
+
var useStoredOidcSession = () => {
|
|
2038
|
+
const auth = useAuth();
|
|
2039
|
+
const { storage } = useStorageConfig();
|
|
2040
|
+
const authority = auth.settings.authority;
|
|
2041
|
+
const clientId = auth.settings.client_id;
|
|
2042
|
+
return useMemo(
|
|
2043
|
+
() => getStoredOidcSession({ authority, clientId, storage }),
|
|
2044
|
+
[authority, clientId, storage]
|
|
2045
|
+
);
|
|
2046
|
+
};
|
|
2047
|
+
|
|
1923
2048
|
// node_modules/@microsoft/signalr/dist/esm/Errors.js
|
|
1924
2049
|
var HttpError = class extends Error {
|
|
1925
2050
|
/** Constructs a new instance of {@link @microsoft/signalr.HttpError}.
|
|
@@ -4958,6 +5083,6 @@ function useSignalRConnection(hubUrl, options = {}) {
|
|
|
4958
5083
|
};
|
|
4959
5084
|
}
|
|
4960
5085
|
|
|
4961
|
-
export { CONFIG_PRESETS, DeviceLogin, KeycloakConfigBuilder, KeycloakProvider, KeycloakStatusProvider, LoginButton, LogoutButton, ProtectedRoute, SessionMonitor, TokenBridge, TokenBridgeSync, TokenLifecycleManager, UserProfile, createTokenBridge, defaultConfig, defaultTokenBridge, fetchUserInfo, getConfigFromEnv, getConfigPreset, mergeWithPreset, pollForToken, requestDeviceCode, useAuth, useKeycloakStatus, useProtectedFetch, useRoles, useScopes, useSignalRConnection, useTokenLifecycle };
|
|
5086
|
+
export { CONFIG_PRESETS, DeviceLogin, KeycloakConfigBuilder, KeycloakProvider, KeycloakStatusProvider, LoginButton, LogoutButton, ProtectedRoute, SessionMonitor, TokenBridge, TokenBridgeSync, TokenLifecycleManager, UserProfile, createTokenBridge, defaultConfig, defaultTokenBridge, fetchUserInfo, getConfigFromEnv, getConfigPreset, getOidcUserStorageKey, getStoredOidcSession, getStoredOidcUser, hasStoredOidcRefreshToken, mergeWithPreset, pollForToken, requestDeviceCode, useAuth, useKeycloakStatus, useProtectedFetch, useRoles, useScopes, useSignalRConnection, useStoredOidcSession, useTokenLifecycle };
|
|
4962
5087
|
//# sourceMappingURL=index.mjs.map
|
|
4963
5088
|
//# sourceMappingURL=index.mjs.map
|