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/README.md
CHANGED
|
@@ -30,6 +30,7 @@ That's it! You now have full authentication with automatic token refresh.
|
|
|
30
30
|
- Zero-config setup
|
|
31
31
|
- Automatic token lifecycle management
|
|
32
32
|
- Token refresh on app startup
|
|
33
|
+
- Token refresh when suspended mobile/PWA sessions resume
|
|
33
34
|
- Silent token renewal
|
|
34
35
|
- Session monitoring UI
|
|
35
36
|
- Protected routes
|
|
@@ -152,6 +153,8 @@ const { isEnabled, isConfigured, reason } = useKeycloakStatus();
|
|
|
152
153
|
- **on-demand**: Only when API returns 401
|
|
153
154
|
- **both** (recommended): Startup + 401 retry
|
|
154
155
|
|
|
156
|
+
For mobile browsers and installed PWAs, token freshness is also checked when the app resumes from the background by default. Set `silentRenew.refreshOnResume` to `false` to disable this behavior.
|
|
157
|
+
|
|
155
158
|
## React Hooks
|
|
156
159
|
|
|
157
160
|
### useAuth()
|
|
@@ -166,6 +169,55 @@ auth.signinRedirect()
|
|
|
166
169
|
auth.signoutRedirect()
|
|
167
170
|
```
|
|
168
171
|
|
|
172
|
+
### useStoredOidcSession()
|
|
173
|
+
|
|
174
|
+
Inspect the OIDC user record stored by `oidc-client-ts` without duplicating the
|
|
175
|
+
library's storage-key format in an application. This is useful when an app wants
|
|
176
|
+
to decide whether to attempt a silent session restore or show a login prompt
|
|
177
|
+
immediately.
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
import { useAuth, useStoredOidcSession } from 'antaeus.keycloak.react';
|
|
181
|
+
|
|
182
|
+
function AuthGate() {
|
|
183
|
+
const auth = useAuth();
|
|
184
|
+
const storedSession = useStoredOidcSession();
|
|
185
|
+
|
|
186
|
+
if (!auth.isAuthenticated && !storedSession.hasRefreshToken) {
|
|
187
|
+
return <button onClick={() => auth.signinRedirect()}>Sign in</button>;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return <App />;
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The hook reads from the same storage configured on `KeycloakProvider` via
|
|
195
|
+
`advanced.storageType`. It does not trigger network calls or change provider
|
|
196
|
+
state.
|
|
197
|
+
|
|
198
|
+
For non-React code or tests, use the exported helpers directly:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
import {
|
|
202
|
+
getOidcUserStorageKey,
|
|
203
|
+
getStoredOidcSession,
|
|
204
|
+
getStoredOidcUser,
|
|
205
|
+
hasStoredOidcRefreshToken,
|
|
206
|
+
} from 'antaeus.keycloak.react';
|
|
207
|
+
|
|
208
|
+
const storageKey = getOidcUserStorageKey(authority, clientId);
|
|
209
|
+
const storedUser = getStoredOidcUser({ authority, clientId, storage: localStorage });
|
|
210
|
+
const session = getStoredOidcSession({ authority, clientId, storage: localStorage });
|
|
211
|
+
const canTrySilentRestore = hasStoredOidcRefreshToken({
|
|
212
|
+
authority,
|
|
213
|
+
clientId,
|
|
214
|
+
storage: localStorage,
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
These helpers are additive APIs. They do not alter default provider behavior,
|
|
219
|
+
token refresh, silent renew, or session monitoring.
|
|
220
|
+
|
|
169
221
|
## Token Bridge (Non-React Consumers)
|
|
170
222
|
|
|
171
223
|
Expose tokens to plain TypeScript modules (SignalR, fetch helpers, etc.):
|
package/dist/index.d.mts
CHANGED
|
@@ -121,6 +121,12 @@ interface SilentRenewConfig {
|
|
|
121
121
|
* @default true
|
|
122
122
|
*/
|
|
123
123
|
useRefreshToken?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Re-check token freshness when a suspended tab/PWA resumes.
|
|
126
|
+
* Useful for mobile browsers and installed PWAs where timers pause in the background.
|
|
127
|
+
* @default true
|
|
128
|
+
*/
|
|
129
|
+
refreshOnResume?: boolean;
|
|
124
130
|
}
|
|
125
131
|
/**
|
|
126
132
|
* Event callbacks for authentication lifecycle
|
|
@@ -1435,6 +1441,31 @@ interface UseTokenLifecycleReturn {
|
|
|
1435
1441
|
*/
|
|
1436
1442
|
declare function useTokenLifecycle(options: UseTokenLifecycleOptions): UseTokenLifecycleReturn;
|
|
1437
1443
|
|
|
1444
|
+
interface StoredOidcSessionUser {
|
|
1445
|
+
access_token?: string;
|
|
1446
|
+
refresh_token?: string;
|
|
1447
|
+
expires_at?: number;
|
|
1448
|
+
[key: string]: unknown;
|
|
1449
|
+
}
|
|
1450
|
+
interface StoredOidcSessionInfo {
|
|
1451
|
+
storageKey: string | null;
|
|
1452
|
+
storedUser: StoredOidcSessionUser | null;
|
|
1453
|
+
hasStoredUser: boolean;
|
|
1454
|
+
hasRefreshToken: boolean;
|
|
1455
|
+
}
|
|
1456
|
+
interface StoredOidcSessionArgs {
|
|
1457
|
+
authority?: string;
|
|
1458
|
+
clientId?: string;
|
|
1459
|
+
storage?: Pick<Storage, 'getItem'>;
|
|
1460
|
+
}
|
|
1461
|
+
declare const getOidcUserStorageKey: (authority?: string, clientId?: string) => string | null;
|
|
1462
|
+
declare const getStoredOidcUser: ({ authority, clientId, storage, }: StoredOidcSessionArgs) => StoredOidcSessionUser | null;
|
|
1463
|
+
declare const hasStoredOidcRefreshToken: (args: StoredOidcSessionArgs) => boolean;
|
|
1464
|
+
declare const getStoredOidcSession: (args: StoredOidcSessionArgs) => StoredOidcSessionInfo;
|
|
1465
|
+
|
|
1466
|
+
type UseStoredOidcSessionReturn = StoredOidcSessionInfo;
|
|
1467
|
+
declare const useStoredOidcSession: () => UseStoredOidcSessionReturn;
|
|
1468
|
+
|
|
1438
1469
|
/**
|
|
1439
1470
|
* Options for configuring the SignalR connection
|
|
1440
1471
|
*/
|
|
@@ -1715,4 +1746,4 @@ declare function pollForToken(apiBaseUrl: string, deviceCode: string): Promise<T
|
|
|
1715
1746
|
*/
|
|
1716
1747
|
declare function fetchUserInfo(apiBaseUrl: string, accessToken: string): Promise<any>;
|
|
1717
1748
|
|
|
1718
|
-
export { type AdvancedOidcOptions, CONFIG_PRESETS, type ConfigPreset, type DeviceAuthorizationResponse, type DeviceFlowError, DeviceLogin, type DeviceLoginProps, type EventCallbacks, type FeatureFlags, type KeycloakConfig, KeycloakConfigBuilder, type KeycloakDisabledReason, KeycloakProvider, type KeycloakProviderFullConfigProps, type KeycloakProviderProps, type KeycloakProviderZeroConfigProps, type KeycloakStatus, KeycloakStatusProvider, LoginButton, type LoginButtonProps, LogoutButton, type LogoutButtonProps, type PolicyContext, type PolicyFunction, ProtectedRoute, type ProtectedRouteProps, SessionMonitor, type SessionMonitorProps, type SilentRenewConfig, TokenBridge, type TokenBridgeProps, TokenBridgeSync, TokenLifecycleManager, type TokenLifecycleManagerProps, type TokenListener, type TokenResponse, type UseProtectedFetchOptions, type UseProtectedFetchReturn, type UseRolesReturn, type UseScopesReturn, type UseSignalRConnectionOptions, type UseSignalRConnectionReturn, type UseTokenLifecycleOptions, type UseTokenLifecycleReturn, UserProfile, type UserProfileProps, createTokenBridge, defaultConfig, defaultTokenBridge, fetchUserInfo, getConfigFromEnv, getConfigPreset, mergeWithPreset, pollForToken, requestDeviceCode, useAuth, useKeycloakStatus, useProtectedFetch, useRoles, useScopes, useSignalRConnection, useTokenLifecycle };
|
|
1749
|
+
export { type AdvancedOidcOptions, CONFIG_PRESETS, type ConfigPreset, type DeviceAuthorizationResponse, type DeviceFlowError, DeviceLogin, type DeviceLoginProps, type EventCallbacks, type FeatureFlags, type KeycloakConfig, KeycloakConfigBuilder, type KeycloakDisabledReason, KeycloakProvider, type KeycloakProviderFullConfigProps, type KeycloakProviderProps, type KeycloakProviderZeroConfigProps, type KeycloakStatus, KeycloakStatusProvider, LoginButton, type LoginButtonProps, LogoutButton, type LogoutButtonProps, type PolicyContext, type PolicyFunction, ProtectedRoute, type ProtectedRouteProps, SessionMonitor, type SessionMonitorProps, type SilentRenewConfig, type StoredOidcSessionArgs, type StoredOidcSessionInfo, type StoredOidcSessionUser, TokenBridge, type TokenBridgeProps, TokenBridgeSync, TokenLifecycleManager, type TokenLifecycleManagerProps, type TokenListener, type TokenResponse, type UseProtectedFetchOptions, type UseProtectedFetchReturn, type UseRolesReturn, type UseScopesReturn, type UseSignalRConnectionOptions, type UseSignalRConnectionReturn, type UseStoredOidcSessionReturn, type UseTokenLifecycleOptions, type UseTokenLifecycleReturn, UserProfile, type UserProfileProps, createTokenBridge, defaultConfig, defaultTokenBridge, fetchUserInfo, getConfigFromEnv, getConfigPreset, getOidcUserStorageKey, getStoredOidcSession, getStoredOidcUser, hasStoredOidcRefreshToken, mergeWithPreset, pollForToken, requestDeviceCode, useAuth, useKeycloakStatus, useProtectedFetch, useRoles, useScopes, useSignalRConnection, useStoredOidcSession, useTokenLifecycle };
|
package/dist/index.d.ts
CHANGED
|
@@ -121,6 +121,12 @@ interface SilentRenewConfig {
|
|
|
121
121
|
* @default true
|
|
122
122
|
*/
|
|
123
123
|
useRefreshToken?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Re-check token freshness when a suspended tab/PWA resumes.
|
|
126
|
+
* Useful for mobile browsers and installed PWAs where timers pause in the background.
|
|
127
|
+
* @default true
|
|
128
|
+
*/
|
|
129
|
+
refreshOnResume?: boolean;
|
|
124
130
|
}
|
|
125
131
|
/**
|
|
126
132
|
* Event callbacks for authentication lifecycle
|
|
@@ -1435,6 +1441,31 @@ interface UseTokenLifecycleReturn {
|
|
|
1435
1441
|
*/
|
|
1436
1442
|
declare function useTokenLifecycle(options: UseTokenLifecycleOptions): UseTokenLifecycleReturn;
|
|
1437
1443
|
|
|
1444
|
+
interface StoredOidcSessionUser {
|
|
1445
|
+
access_token?: string;
|
|
1446
|
+
refresh_token?: string;
|
|
1447
|
+
expires_at?: number;
|
|
1448
|
+
[key: string]: unknown;
|
|
1449
|
+
}
|
|
1450
|
+
interface StoredOidcSessionInfo {
|
|
1451
|
+
storageKey: string | null;
|
|
1452
|
+
storedUser: StoredOidcSessionUser | null;
|
|
1453
|
+
hasStoredUser: boolean;
|
|
1454
|
+
hasRefreshToken: boolean;
|
|
1455
|
+
}
|
|
1456
|
+
interface StoredOidcSessionArgs {
|
|
1457
|
+
authority?: string;
|
|
1458
|
+
clientId?: string;
|
|
1459
|
+
storage?: Pick<Storage, 'getItem'>;
|
|
1460
|
+
}
|
|
1461
|
+
declare const getOidcUserStorageKey: (authority?: string, clientId?: string) => string | null;
|
|
1462
|
+
declare const getStoredOidcUser: ({ authority, clientId, storage, }: StoredOidcSessionArgs) => StoredOidcSessionUser | null;
|
|
1463
|
+
declare const hasStoredOidcRefreshToken: (args: StoredOidcSessionArgs) => boolean;
|
|
1464
|
+
declare const getStoredOidcSession: (args: StoredOidcSessionArgs) => StoredOidcSessionInfo;
|
|
1465
|
+
|
|
1466
|
+
type UseStoredOidcSessionReturn = StoredOidcSessionInfo;
|
|
1467
|
+
declare const useStoredOidcSession: () => UseStoredOidcSessionReturn;
|
|
1468
|
+
|
|
1438
1469
|
/**
|
|
1439
1470
|
* Options for configuring the SignalR connection
|
|
1440
1471
|
*/
|
|
@@ -1715,4 +1746,4 @@ declare function pollForToken(apiBaseUrl: string, deviceCode: string): Promise<T
|
|
|
1715
1746
|
*/
|
|
1716
1747
|
declare function fetchUserInfo(apiBaseUrl: string, accessToken: string): Promise<any>;
|
|
1717
1748
|
|
|
1718
|
-
export { type AdvancedOidcOptions, CONFIG_PRESETS, type ConfigPreset, type DeviceAuthorizationResponse, type DeviceFlowError, DeviceLogin, type DeviceLoginProps, type EventCallbacks, type FeatureFlags, type KeycloakConfig, KeycloakConfigBuilder, type KeycloakDisabledReason, KeycloakProvider, type KeycloakProviderFullConfigProps, type KeycloakProviderProps, type KeycloakProviderZeroConfigProps, type KeycloakStatus, KeycloakStatusProvider, LoginButton, type LoginButtonProps, LogoutButton, type LogoutButtonProps, type PolicyContext, type PolicyFunction, ProtectedRoute, type ProtectedRouteProps, SessionMonitor, type SessionMonitorProps, type SilentRenewConfig, TokenBridge, type TokenBridgeProps, TokenBridgeSync, TokenLifecycleManager, type TokenLifecycleManagerProps, type TokenListener, type TokenResponse, type UseProtectedFetchOptions, type UseProtectedFetchReturn, type UseRolesReturn, type UseScopesReturn, type UseSignalRConnectionOptions, type UseSignalRConnectionReturn, type UseTokenLifecycleOptions, type UseTokenLifecycleReturn, UserProfile, type UserProfileProps, createTokenBridge, defaultConfig, defaultTokenBridge, fetchUserInfo, getConfigFromEnv, getConfigPreset, mergeWithPreset, pollForToken, requestDeviceCode, useAuth, useKeycloakStatus, useProtectedFetch, useRoles, useScopes, useSignalRConnection, useTokenLifecycle };
|
|
1749
|
+
export { type AdvancedOidcOptions, CONFIG_PRESETS, type ConfigPreset, type DeviceAuthorizationResponse, type DeviceFlowError, DeviceLogin, type DeviceLoginProps, type EventCallbacks, type FeatureFlags, type KeycloakConfig, KeycloakConfigBuilder, type KeycloakDisabledReason, KeycloakProvider, type KeycloakProviderFullConfigProps, type KeycloakProviderProps, type KeycloakProviderZeroConfigProps, type KeycloakStatus, KeycloakStatusProvider, LoginButton, type LoginButtonProps, LogoutButton, type LogoutButtonProps, type PolicyContext, type PolicyFunction, ProtectedRoute, type ProtectedRouteProps, SessionMonitor, type SessionMonitorProps, type SilentRenewConfig, type StoredOidcSessionArgs, type StoredOidcSessionInfo, type StoredOidcSessionUser, TokenBridge, type TokenBridgeProps, TokenBridgeSync, TokenLifecycleManager, type TokenLifecycleManagerProps, type TokenListener, type TokenResponse, type UseProtectedFetchOptions, type UseProtectedFetchReturn, type UseRolesReturn, type UseScopesReturn, type UseSignalRConnectionOptions, type UseSignalRConnectionReturn, type UseStoredOidcSessionReturn, type UseTokenLifecycleOptions, type UseTokenLifecycleReturn, UserProfile, type UserProfileProps, createTokenBridge, defaultConfig, defaultTokenBridge, fetchUserInfo, getConfigFromEnv, getConfigPreset, getOidcUserStorageKey, getStoredOidcSession, getStoredOidcUser, hasStoredOidcRefreshToken, mergeWithPreset, pollForToken, requestDeviceCode, useAuth, useKeycloakStatus, useProtectedFetch, useRoles, useScopes, useSignalRConnection, useStoredOidcSession, useTokenLifecycle };
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,8 @@ var defaultConfig = {
|
|
|
36
36
|
// 30 days in seconds
|
|
37
37
|
showLoadingIndicator: false,
|
|
38
38
|
loadingMessage: "Refreshing session...",
|
|
39
|
-
useRefreshToken: true
|
|
39
|
+
useRefreshToken: true,
|
|
40
|
+
refreshOnResume: true
|
|
40
41
|
},
|
|
41
42
|
advanced: {
|
|
42
43
|
responseType: "code",
|
|
@@ -191,6 +192,7 @@ function useTokenLifecycle(options) {
|
|
|
191
192
|
const auth = useAuth();
|
|
192
193
|
const [isRefreshing, setIsRefreshing] = react.useState(false);
|
|
193
194
|
const [isRefreshTokenExpired, setIsRefreshTokenExpired] = react.useState(false);
|
|
195
|
+
const isRefreshingRef = react.useRef(false);
|
|
194
196
|
const hasCheckedOnStartup = react.useRef(false);
|
|
195
197
|
const supportsRefreshTokens = config.silentRenew?.useRefreshToken !== false;
|
|
196
198
|
const [pendingRetry, setPendingRetry] = react.useState(null);
|
|
@@ -243,10 +245,11 @@ function useTokenLifecycle(options) {
|
|
|
243
245
|
return elapsedSeconds >= maxLifetime;
|
|
244
246
|
}, [config.silentRenew?.maxRefreshTokenLifetime, getStorageKey, log, storeFirstLoginTime]);
|
|
245
247
|
const refreshToken = react.useCallback(async () => {
|
|
246
|
-
if (
|
|
248
|
+
if (isRefreshingRef.current) {
|
|
247
249
|
log("Refresh already in progress, skipping");
|
|
248
250
|
return;
|
|
249
251
|
}
|
|
252
|
+
isRefreshingRef.current = true;
|
|
250
253
|
setIsRefreshing(true);
|
|
251
254
|
deferredRefreshReasonRef.current = null;
|
|
252
255
|
try {
|
|
@@ -302,10 +305,10 @@ function useTokenLifecycle(options) {
|
|
|
302
305
|
onRefreshError?.(err);
|
|
303
306
|
throw err;
|
|
304
307
|
} finally {
|
|
308
|
+
isRefreshingRef.current = false;
|
|
305
309
|
setIsRefreshing(false);
|
|
306
310
|
}
|
|
307
311
|
}, [
|
|
308
|
-
isRefreshing,
|
|
309
312
|
auth,
|
|
310
313
|
checkRefreshTokenLifetime,
|
|
311
314
|
onRefreshStart,
|
|
@@ -316,6 +319,38 @@ function useTokenLifecycle(options) {
|
|
|
316
319
|
getStorageKey,
|
|
317
320
|
log
|
|
318
321
|
]);
|
|
322
|
+
const shouldRefreshOnResume = react.useCallback((reason) => {
|
|
323
|
+
const silentRenewEnabled = config.silentRenew?.enabled !== false;
|
|
324
|
+
const refreshOnResume = config.silentRenew?.refreshOnResume !== false;
|
|
325
|
+
const strategy = config.silentRenew?.refreshStrategy || "both";
|
|
326
|
+
const strategyAllowsResume = strategy === "startup" || strategy === "both";
|
|
327
|
+
const hasRefreshToken = Boolean(auth.user?.refresh_token);
|
|
328
|
+
if (!silentRenewEnabled || !refreshOnResume || !strategyAllowsResume) {
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
if (auth.isLoading) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
if (!auth.user) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
if (supportsRefreshTokens && !hasRefreshToken) {
|
|
338
|
+
log("Skipping resume token check because no refresh token is available:", reason);
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
if (reason !== "online" && typeof document !== "undefined" && document.visibilityState === "hidden") {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
return true;
|
|
345
|
+
}, [
|
|
346
|
+
auth.isLoading,
|
|
347
|
+
auth.user,
|
|
348
|
+
config.silentRenew?.enabled,
|
|
349
|
+
config.silentRenew?.refreshOnResume,
|
|
350
|
+
config.silentRenew?.refreshStrategy,
|
|
351
|
+
supportsRefreshTokens,
|
|
352
|
+
log
|
|
353
|
+
]);
|
|
319
354
|
const checkAndRefreshTokens = react.useCallback(async () => {
|
|
320
355
|
if (!auth.user) {
|
|
321
356
|
log("No user session, skipping token check");
|
|
@@ -463,6 +498,38 @@ function useTokenLifecycle(options) {
|
|
|
463
498
|
checkAndRefreshTokens,
|
|
464
499
|
log
|
|
465
500
|
]);
|
|
501
|
+
react.useEffect(() => {
|
|
502
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
const runResumeCheck = (reason) => {
|
|
506
|
+
if (!shouldRefreshOnResume(reason)) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
log("Running resume token check after:", reason);
|
|
510
|
+
checkAndRefreshTokens().catch((error) => {
|
|
511
|
+
log("Resume token check failed:", error);
|
|
512
|
+
});
|
|
513
|
+
};
|
|
514
|
+
const handleVisibilityChange = () => {
|
|
515
|
+
if (document.visibilityState === "visible") {
|
|
516
|
+
runResumeCheck("visibilitychange");
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
const handlePageShow = () => runResumeCheck("pageshow");
|
|
520
|
+
const handleFocus = () => runResumeCheck("focus");
|
|
521
|
+
const handleOnline = () => runResumeCheck("online");
|
|
522
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
523
|
+
window.addEventListener("pageshow", handlePageShow);
|
|
524
|
+
window.addEventListener("focus", handleFocus);
|
|
525
|
+
window.addEventListener("online", handleOnline);
|
|
526
|
+
return () => {
|
|
527
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
528
|
+
window.removeEventListener("pageshow", handlePageShow);
|
|
529
|
+
window.removeEventListener("focus", handleFocus);
|
|
530
|
+
window.removeEventListener("online", handleOnline);
|
|
531
|
+
};
|
|
532
|
+
}, [checkAndRefreshTokens, log, shouldRefreshOnResume]);
|
|
466
533
|
react.useEffect(() => {
|
|
467
534
|
if (hasCheckedOnStartup.current) {
|
|
468
535
|
const hasUser = Boolean(auth.user);
|
|
@@ -885,7 +952,8 @@ var CONFIG_PRESETS = {
|
|
|
885
952
|
maxRefreshTokenLifetime: 2592e3,
|
|
886
953
|
// 30 days
|
|
887
954
|
showLoadingIndicator: false,
|
|
888
|
-
loadingMessage: "Refreshing session..."
|
|
955
|
+
loadingMessage: "Refreshing session...",
|
|
956
|
+
refreshOnResume: true
|
|
889
957
|
},
|
|
890
958
|
advanced: {
|
|
891
959
|
responseType: "code",
|
|
@@ -921,7 +989,8 @@ var CONFIG_PRESETS = {
|
|
|
921
989
|
// 30 days
|
|
922
990
|
showLoadingIndicator: true,
|
|
923
991
|
// Show loading for better UX
|
|
924
|
-
loadingMessage: "Restoring your session..."
|
|
992
|
+
loadingMessage: "Restoring your session...",
|
|
993
|
+
refreshOnResume: true
|
|
925
994
|
},
|
|
926
995
|
advanced: {
|
|
927
996
|
responseType: "code",
|
|
@@ -958,7 +1027,8 @@ var CONFIG_PRESETS = {
|
|
|
958
1027
|
// 24 hours only
|
|
959
1028
|
showLoadingIndicator: false,
|
|
960
1029
|
// Silent for security
|
|
961
|
-
loadingMessage: "Validating session..."
|
|
1030
|
+
loadingMessage: "Validating session...",
|
|
1031
|
+
refreshOnResume: true
|
|
962
1032
|
},
|
|
963
1033
|
advanced: {
|
|
964
1034
|
responseType: "code",
|
|
@@ -992,7 +1062,8 @@ var CONFIG_PRESETS = {
|
|
|
992
1062
|
maxRefreshTokenLifetime: 604800,
|
|
993
1063
|
// 7 days
|
|
994
1064
|
showLoadingIndicator: false,
|
|
995
|
-
loadingMessage: "Refreshing session..."
|
|
1065
|
+
loadingMessage: "Refreshing session...",
|
|
1066
|
+
refreshOnResume: true
|
|
996
1067
|
},
|
|
997
1068
|
advanced: {
|
|
998
1069
|
responseType: "code",
|
|
@@ -1029,7 +1100,8 @@ var CONFIG_PRESETS = {
|
|
|
1029
1100
|
// No limit (for convenience)
|
|
1030
1101
|
showLoadingIndicator: true,
|
|
1031
1102
|
// Show for debugging
|
|
1032
|
-
loadingMessage: "[DEV] Refreshing tokens..."
|
|
1103
|
+
loadingMessage: "[DEV] Refreshing tokens...",
|
|
1104
|
+
refreshOnResume: true
|
|
1033
1105
|
},
|
|
1034
1106
|
advanced: {
|
|
1035
1107
|
responseType: "code",
|
|
@@ -1923,6 +1995,59 @@ function useProtectedFetch(options = {}) {
|
|
|
1923
1995
|
};
|
|
1924
1996
|
}
|
|
1925
1997
|
|
|
1998
|
+
// src/utils/storedOidcSession.ts
|
|
1999
|
+
var getOidcUserStorageKey = (authority, clientId) => {
|
|
2000
|
+
if (!authority || !clientId) {
|
|
2001
|
+
return null;
|
|
2002
|
+
}
|
|
2003
|
+
return `oidc.user:${authority}:${clientId}`;
|
|
2004
|
+
};
|
|
2005
|
+
var getStoredOidcUser = ({
|
|
2006
|
+
authority,
|
|
2007
|
+
clientId,
|
|
2008
|
+
storage
|
|
2009
|
+
}) => {
|
|
2010
|
+
const storageKey = getOidcUserStorageKey(authority, clientId);
|
|
2011
|
+
if (!storageKey || !storage) {
|
|
2012
|
+
return null;
|
|
2013
|
+
}
|
|
2014
|
+
try {
|
|
2015
|
+
const storedUser = storage.getItem(storageKey);
|
|
2016
|
+
if (!storedUser) {
|
|
2017
|
+
return null;
|
|
2018
|
+
}
|
|
2019
|
+
return JSON.parse(storedUser);
|
|
2020
|
+
} catch {
|
|
2021
|
+
return null;
|
|
2022
|
+
}
|
|
2023
|
+
};
|
|
2024
|
+
var hasStoredOidcRefreshToken = (args) => {
|
|
2025
|
+
const storedUser = getStoredOidcUser(args);
|
|
2026
|
+
return typeof storedUser?.refresh_token === "string" && storedUser.refresh_token.length > 0;
|
|
2027
|
+
};
|
|
2028
|
+
var getStoredOidcSession = (args) => {
|
|
2029
|
+
const storageKey = getOidcUserStorageKey(args.authority, args.clientId);
|
|
2030
|
+
const storedUser = getStoredOidcUser(args);
|
|
2031
|
+
return {
|
|
2032
|
+
storageKey,
|
|
2033
|
+
storedUser,
|
|
2034
|
+
hasStoredUser: storedUser !== null,
|
|
2035
|
+
hasRefreshToken: typeof storedUser?.refresh_token === "string" && storedUser.refresh_token.length > 0
|
|
2036
|
+
};
|
|
2037
|
+
};
|
|
2038
|
+
|
|
2039
|
+
// src/hooks/useStoredOidcSession.ts
|
|
2040
|
+
var useStoredOidcSession = () => {
|
|
2041
|
+
const auth = useAuth();
|
|
2042
|
+
const { storage } = useStorageConfig();
|
|
2043
|
+
const authority = auth.settings.authority;
|
|
2044
|
+
const clientId = auth.settings.client_id;
|
|
2045
|
+
return react.useMemo(
|
|
2046
|
+
() => getStoredOidcSession({ authority, clientId, storage }),
|
|
2047
|
+
[authority, clientId, storage]
|
|
2048
|
+
);
|
|
2049
|
+
};
|
|
2050
|
+
|
|
1926
2051
|
// node_modules/@microsoft/signalr/dist/esm/Errors.js
|
|
1927
2052
|
var HttpError = class extends Error {
|
|
1928
2053
|
/** Constructs a new instance of {@link @microsoft/signalr.HttpError}.
|
|
@@ -4980,6 +5105,10 @@ exports.defaultTokenBridge = defaultTokenBridge;
|
|
|
4980
5105
|
exports.fetchUserInfo = fetchUserInfo;
|
|
4981
5106
|
exports.getConfigFromEnv = getConfigFromEnv;
|
|
4982
5107
|
exports.getConfigPreset = getConfigPreset;
|
|
5108
|
+
exports.getOidcUserStorageKey = getOidcUserStorageKey;
|
|
5109
|
+
exports.getStoredOidcSession = getStoredOidcSession;
|
|
5110
|
+
exports.getStoredOidcUser = getStoredOidcUser;
|
|
5111
|
+
exports.hasStoredOidcRefreshToken = hasStoredOidcRefreshToken;
|
|
4983
5112
|
exports.mergeWithPreset = mergeWithPreset;
|
|
4984
5113
|
exports.pollForToken = pollForToken;
|
|
4985
5114
|
exports.requestDeviceCode = requestDeviceCode;
|
|
@@ -4989,6 +5118,7 @@ exports.useProtectedFetch = useProtectedFetch;
|
|
|
4989
5118
|
exports.useRoles = useRoles;
|
|
4990
5119
|
exports.useScopes = useScopes;
|
|
4991
5120
|
exports.useSignalRConnection = useSignalRConnection;
|
|
5121
|
+
exports.useStoredOidcSession = useStoredOidcSession;
|
|
4992
5122
|
exports.useTokenLifecycle = useTokenLifecycle;
|
|
4993
5123
|
//# sourceMappingURL=index.js.map
|
|
4994
5124
|
//# sourceMappingURL=index.js.map
|