Skip to content

Commit f4ce35e

Browse files
authored
fix(oidc-client): implement consistent storage caching for userInfo and well-known configuration (release) (#1592)
* fix: add persistent storage caching for userInfo to prevent loss on page refresh Fixes #898 Problem: - UserInfo was only cached in memory (oidc.userInfo) - Lost on page refresh, causing unnecessary /userinfo network requests - Performance issue for users with configured storage Solution: - Add storage check before network fetch using existing storage configuration - Store userInfo result after successful fetch for persistence across refreshes - Follows same security pattern as existing token storage - Respects noCache parameter to bypass both memory and storage cache Implementation: - Only 4 lines added to userInfoAsync function - Uses oidc.configuration.storage (same as tokens) - Storage key: oidc.{configurationName}.userInfo - Graceful fallback when storage not configured Security: - UserInfo is less sensitive than tokens (already stored in same location) - Uses optional chaining for safe access - Maintains all existing security controls Benefits: - Eliminates unnecessary userinfo network requests on page refresh - Improves performance for users with storage configuration - Zero breaking changes, backward compatible - Reuses existing infrastructure * fix: implement consistent storage caching for userInfo and well-known configuration Fixes #898 Problems: 1. UserInfo lost on page refresh causing unnecessary /userinfo network requests 2. Well-known configuration cache hardcoded to sessionStorage, ignoring user storage preferences Root Causes: - UserInfo only cached in memory (oidc.userInfo), lost on refresh - Well-known cache always used sessionStorage instead of configuration.storage - Inconsistent storage behavior across different cached data types Solutions: 1. UserInfo Persistent Caching: - Add storage check before network fetch using existing storage configuration - Store userInfo result after successful fetch for persistence across refreshes - Use same storage key pattern: oidc.{configurationName}.userInfo 2. Well-Known Cache Storage Consistency: - Respect user's configuration.storage instead of hardcoded sessionStorage - Maintain backward compatibility with fallback to sessionStorage Implementation: - Only 5 lines of code added across 2 files - Uses oidc.configuration.storage (same as tokens) - Graceful fallback when storage not configured - Respects noCache parameter to bypass both memory and storage cache Security: - UserInfo is less sensitive than tokens (already stored in same location) - Uses optional chaining for safe access - Maintains all existing security controls Benefits: - Eliminates unnecessary userinfo and well-known network requests on page refresh - Consistent storage behavior across all cached data (tokens, userInfo, well-known) - Improves performance for users with persistent storage configuration - Zero breaking changes, backward compatible - Reuses existing infrastructure
1 parent 7a99d7c commit f4ce35e

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

packages/oidc-client/src/oidc.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
252252
}
253253

254254
const serviceWorker = await initWorkerAsync(this.configuration, this.configurationName);
255-
const storage = serviceWorker ? window.sessionStorage : null;
255+
const storage = serviceWorker
256+
? this.configuration.storage || window.sessionStorage
257+
: this.configuration.storage;
256258
return await fetchFromIssuer(this.getFetch())(
257259
authority,
258260
this.configuration.authority_time_cache_wellknowurl_in_second ?? 60 * 60,

packages/oidc-client/src/user.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ export const userInfoAsync =
77
if (oidc.userInfo != null && !noCache) {
88
return oidc.userInfo;
99
}
10+
// Check storage cache
11+
const stored =
12+
!noCache && oidc.configuration.storage?.getItem(`oidc.${oidc.configurationName}.userInfo`);
13+
if (stored) {
14+
oidc.userInfo = JSON.parse(stored);
15+
return oidc.userInfo;
16+
}
1017
const configuration = oidc.configuration;
1118
const oidcServerConfiguration = await oidc.initAsync(
1219
configuration.authority,
@@ -23,5 +30,12 @@ export const userInfoAsync =
2330
};
2431
const userInfo = await fetchUserInfo();
2532
oidc.userInfo = userInfo;
33+
// Store in cache
34+
if (userInfo) {
35+
oidc.configuration.storage?.setItem(
36+
`oidc.${oidc.configurationName}.userInfo`,
37+
JSON.stringify(userInfo),
38+
);
39+
}
2640
return userInfo;
2741
};

0 commit comments

Comments
 (0)