Open Closed

Follow-up to #10937: MemoryTokenStorageService + refresh token in memory causes two regressions #10943


User avatar
0
wali-092 created

Follow-up to #10937: MemoryTokenStorageService + refresh token in memory causes two regressions the previous issue's link is : https://abp.io/support/questions/10937/Angular-MemoryTokenStorageService-still-persists-refreshtoken-in-localStorage-and-concurrent-tabs-break-refresh-token-rotation

Setup: We applied the workaround from this thread. RefreshTokenInMemoryStorageService extends MemoryTokenStorageService, pushes refresh_token into keysShouldStoreInMemory, posts a get for it to the SharedWorker, and removes the old refresh_token from localStorage. It's provided as { provide: MemoryTokenStorageService, useExisting: RefreshTokenInMemoryStorageService } after provideAbpOAuth().

Tokens are no longer in localStorage, as intended, but two problems appeared.

Issue 1: refreshing a page sends the user to the root (dashboard) instead of the page they were on

Steps:

Sign in and open a deep route, e.g. /my-tasks, in a single tab.

Press F5.

Expected: the page reloads on /my-tasks, still signed in.

Actual: the app signs in again through the auth server and lands on / (dashboard). Before the redirect, API calls made during startup return 401.

Our analysis: when the only tab unloads, the SharedWorker has no ports left and the browser ends it, so all in-memory tokens are lost, including the refresh token. The reloaded tab starts anonymous and has to sign in again. When that sign-in starts from a 401 rather than from the guard, no state/returnUrl is sent, so the auth server returns to the redirect URI (root).

Issue 2: duplicating a tab makes all open tabs reload repeatedly

Steps:

Sign in and open /my-tasks. Duplicate the tab (or open the app in a second tab). Expected: the new tab picks up the tokens from the SharedWorker, and the other tabs are not affected. Actual: all open tabs reload several times before they settle.

Network log of the duplicated tab (Fetch/XHR):

Boot 1: openid-configuration, jwks, token, application-configuration (9.2 kB, authenticated), API calls. Boot 2: openid-configuration, jwks, application-configuration (3.4 kB, anonymous). Then the page reloads. Boot 3: openid-configuration, jwks, application-configuration (authenticated), API calls. Our analysis, from the @abp/ng.oauth 10.1.1 sources:

MemoryTokenStorageService asks the SharedWorker for the tokens asynchronously (port.postMessage({ action: 'get' })). Nothing waits for the answers before AuthService.init() and configState.refreshAppState() in getInitialData(). A new tab can therefore load application-configuration without a token and get an anonymous currentUser. The tokens arrive right after that. checkAccessToken (CHECK_AUTHENTICATION_STATE_FN_KEY) then sees hasValidAccessToken() === true with no currentUser.id and calls clearOAuthStorage(). clearOAuthStorage() removes the in-memory keys through the worker. The worker broadcasts remove to every other port, and each tab runs refreshDocument(), which reloads it. The reloaded tabs start with no tokens and sign in again. Each new access_token is broadcast as set, and checkAuthStateChanges reloads any tab whose cache has no access_token yet. This produces the chain of reloads. Questions / requests

Can startup wait for the SharedWorker's answers (e.g. a ready promise in MemoryTokenStorageService awaited before AuthService.init()), so that a new tab never loads the configuration anonymously? Should checkAccessToken avoid clearOAuthStorage(), which signs out every tab, when the mismatch is only caused by the token arriving late in this tab? For example, it could reload the app configuration once with the token instead. Is official support for keeping refresh_token in memory planned? Our workaround relies on private members (keysShouldStoreInMemory, port). What is the recommended way to keep the user on the current page after F5 when the tokens exist only in memory (Issue 1)? Thanks.

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

No answer yet!
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on October 21, 2026, 11:09
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.