Hi maliming
Thanks for the workaround. We'll use it for now.
For our pen-test finding (CWE-922), the cleanest fix is a cookie-based session, where no tokens are held in the browser at all. Could you tell us:
This would also solve the multi-tab refresh problem, since only the server would redeem refresh tokens, and we could keep SetRefreshTokenReuseLeeway(0).
Thanks
ABP version: 10.1.1 (@abp/ng.core, @abp/ng.oauth), Angular 21.2, angular-oauth2-oidc 20.0.2. Commercial license, microservice solution, Angular SPA, OpenIddict 7.2 auth server.
Background
Issue #23930 / PR #24050 moved the access and ID tokens to memory (MemoryTokenStorageService with a SharedWorker). A penetration test of our product found that OAuth tokens kept in browser storage can be stolen through XSS. With 10.1.1 the access token is protected, but refresh_token is not in keysShouldStoreInMemory, so it is still written to localStorage through AbpLocalStorageService. The refresh token is the long-lived credential: with it an attacker can mint new access tokens until it expires. So the original issue is only partly solved.
Problem 1: refresh token in localStorage
provideAbpOAuth() with the code flow and the offline_access scope. Sign in, then open DevTools → Application → Local Storage.refresh_token is present in localStorage.Problem 2: tabs refreshing at the same time break rotation
SetRefreshTokenReuseLeeway(0));Requests
refresh_token in memory as well (shared through the SharedWorker), accepting that the session ends when the last tab closes and is restored by a silent authorization-code redirect using the auth server's cookie.OAuthStorage with localStorage lose the protection;data: URL SharedWorker (worker-src data:), since a strict worker-src silently turns the shared storage off.Impact This blocks closing a penetration-test finding (tokens in browser storage, CWE-922) for a government client without replacing ABP's OAuth storage and refresh code.
Want me to remove the two override lines on a front-end branch and test reload, several tabs and the two-tab refresh against dev?
Type: Bug / Security
Environment
ABP Framework: 10.x Frontend: Angular 21 (OAuth2/OIDC via the ABP Angular packages) Authentication server: OpenIddict Token type: JWT access token Access token lifetime: 15 min
Description When a user logs out of the Angular application, the access token should be revoked so it can no longer be used. In our tests, a token copied before logout still works against the APIs after logout.
Steps to reproduce
Log in to the Angular application. Open the browser dev tools (Application → Local Storage) and copy the access_token value. Save the token somewhere outside the browser. Log out from the application. Call a protected API endpoint from Postman with the header Authorization: Bearer .
Expected result The API rejects the token with 401 Unauthorized, because logout revoked it.
Actual result The API accepts the token and returns data as if the user were still logged in.
Impact A token that is leaked or copied (through XSS, a shared machine, or a compromised device) stays usable until it expires, even after the user has explicitly logged out. This defeats the purpose of logout.
Questions for the ABP team
Is this the expected default behavior, for example because access tokens are self-contained JWTs validated locally by the API?
What is the recommended way to make logout invalidate the access token immediately? Options we are considering: Reference access tokens with token entry validation enabled in OpenIddict Calling the revocation endpoint from the Angular client on logout Another approach you recommend
Attachments (available on request): OpenIddict configuration, API logs, minimal reproduction project.