antaeus.keycloak.react 2.2.2 → 2.3.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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
1
+ import { createContext, useState, useRef, useCallback, useEffect, useMemo, useContext } from 'react';
2
2
  import { useAuth as useAuth$1, AuthProvider } from 'react-oidc-context';
3
3
  import { WebStorageStateStore, User } from 'oidc-client-ts';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -27,7 +27,8 @@ var defaultConfig = {
27
27
  maxRefreshTokenLifetime: 2592e3,
28
28
  // 30 days in seconds
29
29
  showLoadingIndicator: false,
30
- loadingMessage: "Refreshing session..."
30
+ loadingMessage: "Refreshing session...",
31
+ useRefreshToken: true
31
32
  },
32
33
  advanced: {
33
34
  responseType: "code",
@@ -53,6 +54,7 @@ var KeycloakConfigBuilder = class {
53
54
  const config = this.mergeWithDefaults(userConfig);
54
55
  const storageType = config.advanced.storageType || "session";
55
56
  const storage = storageType === "local" ? window.localStorage : window.sessionStorage;
57
+ const { useRefreshToken } = config.silentRenew;
56
58
  const oidcSettings = {
57
59
  authority: config.authority,
58
60
  client_id: config.clientId,
@@ -70,6 +72,9 @@ var KeycloakConfigBuilder = class {
70
72
  response_mode: "query"
71
73
  }
72
74
  };
75
+ if (useRefreshToken !== void 0) {
76
+ oidcSettings.useRefreshToken = useRefreshToken;
77
+ }
73
78
  return oidcSettings;
74
79
  }
75
80
  /**
@@ -157,6 +162,7 @@ function useTokenLifecycle(options) {
157
162
  const [isRefreshing, setIsRefreshing] = useState(false);
158
163
  const [isRefreshTokenExpired, setIsRefreshTokenExpired] = useState(false);
159
164
  const hasCheckedOnStartup = useRef(false);
165
+ const supportsRefreshTokens = config.silentRenew?.useRefreshToken !== false;
160
166
  const log = useCallback(
161
167
  (message, ...args) => {
162
168
  if (debug) {
@@ -293,24 +299,49 @@ function useTokenLifecycle(options) {
293
299
  useEffect(() => {
294
300
  const strategy = config.silentRenew?.refreshStrategy || "both";
295
301
  const shouldCheckOnStartup = strategy === "startup" || strategy === "both";
302
+ const hasRefreshToken = Boolean(auth.user?.refresh_token);
296
303
  if (!shouldCheckOnStartup || hasCheckedOnStartup.current) {
297
304
  return;
298
305
  }
299
- if (!auth.isAuthenticated || auth.isLoading) {
306
+ if (auth.isLoading) {
300
307
  return;
301
308
  }
309
+ if (!auth.isAuthenticated) {
310
+ if (!supportsRefreshTokens) {
311
+ return;
312
+ }
313
+ if (!auth.user || !hasRefreshToken) {
314
+ return;
315
+ }
316
+ }
302
317
  hasCheckedOnStartup.current = true;
303
- log("Running startup token check with strategy:", strategy);
318
+ log(
319
+ "Running startup token check with strategy:",
320
+ strategy,
321
+ "using refresh token:",
322
+ !auth.isAuthenticated && supportsRefreshTokens
323
+ );
304
324
  checkAndRefreshTokens().catch((error) => {
305
325
  log("Startup token check failed:", error);
306
326
  });
307
327
  }, [
308
328
  auth.isAuthenticated,
309
329
  auth.isLoading,
330
+ auth.user,
310
331
  config.silentRenew?.refreshStrategy,
332
+ supportsRefreshTokens,
311
333
  checkAndRefreshTokens,
312
334
  log
313
335
  ]);
336
+ useEffect(() => {
337
+ if (hasCheckedOnStartup.current) {
338
+ const hasUser = Boolean(auth.user);
339
+ const hasRefreshToken = Boolean(auth.user?.refresh_token);
340
+ if (auth.isLoading || !auth.isAuthenticated && (!supportsRefreshTokens || !hasUser || !hasRefreshToken)) {
341
+ hasCheckedOnStartup.current = false;
342
+ }
343
+ }
344
+ }, [auth.isAuthenticated, auth.isLoading, auth.user, supportsRefreshTokens]);
314
345
  useEffect(() => {
315
346
  if (auth.user && !auth.isLoading) {
316
347
  storeFirstLoginTime();
@@ -834,6 +865,15 @@ function mergeWithPreset(preset, customConfig) {
834
865
  }
835
866
  };
836
867
  }
868
+ var StorageConfigContext = createContext({
869
+ storageType: "session",
870
+ storage: typeof window !== "undefined" ? window.sessionStorage : {}
871
+ });
872
+ var StorageConfigProvider = ({ storageType, children }) => {
873
+ const storage = storageType === "local" ? window.localStorage : window.sessionStorage;
874
+ return /* @__PURE__ */ jsx(StorageConfigContext.Provider, { value: { storageType, storage }, children });
875
+ };
876
+ var useStorageConfig = () => useContext(StorageConfigContext);
837
877
  function isZeroConfig(props) {
838
878
  return "authority" in props && "clientId" in props;
839
879
  }
@@ -879,6 +919,7 @@ var KeycloakProvider = (props) => {
879
919
  log("warn", "User removed from storage - token validation likely failed");
880
920
  }, [log]);
881
921
  const showSessionMonitor = config.features?.sessionMonitor !== false;
922
+ const storageType = config.advanced?.storageType || "session";
882
923
  return /* @__PURE__ */ jsx(
883
924
  AuthProvider,
884
925
  {
@@ -886,10 +927,10 @@ var KeycloakProvider = (props) => {
886
927
  onSigninCallback,
887
928
  onSignoutCallback,
888
929
  onRemoveUser,
889
- children: /* @__PURE__ */ jsxs(TokenLifecycleManager, { config, debug, children: [
930
+ children: /* @__PURE__ */ jsx(StorageConfigProvider, { storageType, children: /* @__PURE__ */ jsxs(TokenLifecycleManager, { config, debug, children: [
890
931
  showSessionMonitor && /* @__PURE__ */ jsx(SessionMonitor, {}),
891
932
  children
892
- ] })
933
+ ] }) })
893
934
  }
894
935
  );
895
936
  };
@@ -1346,6 +1387,7 @@ var DeviceLogin = ({
1346
1387
  style
1347
1388
  }) => {
1348
1389
  const auth = useAuth();
1390
+ const { storage, storageType } = useStorageConfig();
1349
1391
  const [deviceData, setDeviceData] = useState(null);
1350
1392
  const [error, setError] = useState(null);
1351
1393
  const [loading, setLoading] = useState(true);
@@ -1412,10 +1454,10 @@ var DeviceLogin = ({
1412
1454
  });
1413
1455
  const storageKey = `oidc.user:${auth.settings.authority}:${auth.settings.client_id}`;
1414
1456
  const userJson = user.toStorageString();
1415
- const storage = auth.settings.userStore?.store || window.sessionStorage;
1416
1457
  console.log("[DeviceLogin] Storing user in storage...", {
1417
1458
  storageKey,
1418
- storageType: storage === window.localStorage ? "localStorage" : "sessionStorage"
1459
+ storageType,
1460
+ storage: storageType === "local" ? "localStorage" : "sessionStorage"
1419
1461
  });
1420
1462
  storage.setItem(storageKey, userJson);
1421
1463
  const stored = storage.getItem(storageKey);
@@ -1423,7 +1465,7 @@ var DeviceLogin = ({
1423
1465
  console.error("[DeviceLogin] Failed to store user in storage!");
1424
1466
  throw new Error("Failed to store user session. Please try again.");
1425
1467
  }
1426
- console.log("[DeviceLogin] User stored successfully in", storage === window.localStorage ? "localStorage" : "sessionStorage");
1468
+ console.log("[DeviceLogin] User stored successfully in", storageType === "local" ? "localStorage" : "sessionStorage");
1427
1469
  if (onSuccess) {
1428
1470
  await new Promise((resolve) => setTimeout(resolve, 100));
1429
1471
  onSuccess(user);