STCOR-1012 💉 botox for the botched RTR implementation#1696
Open
STCOR-1012 💉 botox for the botched RTR implementation#1696
Conversation
* FFetch is a lot less spaghetti-y * Include `handleFetch` and FLS timers on Stripes so they can be used on login/logout, just as they are during rotation
Jest Unit Test Results 1 files ± 0 85 suites ±0 1m 5s ⏱️ -38s Results for commit a4f1623. ± Comparison against base commit 5ab64db. This pull request removes 55 and adds 33 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
JohnC-80
approved these changes
Feb 13, 2026
Contributor
JohnC-80
left a comment
There was a problem hiding this comment.
Tiny cleanup is all I've got so far... this really cleaned a lot of house. 👏 👏 👏
Previously, XHR.send() requests would blow up because they called `rotateAndReplay()` with only two args but three were required.
shouldRotate alternative to status code inspection when a response is present: deal with Okapi's non-standard 400 response for missing/invalid tokens by cloning the response and inspecting the body text. optional; defaults to a function that resolves to false, i.e. do not force rotation
Start timers when reloading a window. DUH! Hard to believe I completely missed this the first time around. h/t @Dmytro-Melnyshyn Prop-drilling > stripes. Only a few components need these RTR functions, so only a few components should receive them. When XHR notices the AT has expired, force rotation.
…hat return promises ... should return promises. Your hed asplode now, huh, Sonar?
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



RTR, boy oh boy, where to start?
RTR_IS_ROTATINGfrom local storage before dispatching theRTR_SUCCESS_EVENTto correctly determine theRTR_IS_ROTATINGstate in therotationHandlerfunction. #1643, STCOR-978 Use BroadcastChannel to isolate token to last-focused window. #1647, and STCOR-1029: Remove the/users-keycloak/_self(and/bl-users/_self) requests. They were included inisAuthenticationRequest, which caused them to bypass the RTR queue (getPromise). #1688).The implementations thus far all worked by setting a timer that pinged shortly before the AT expired, executing a callback that paused API requests while executing the rotation request. Of course, it was never that simple; starting rotation after authenticating was subtly different than starting rotation for an existing session because the login-response includes token-expiration data but the
/bl-users/_selfdoesn't. All those extra tweaks made the code even messier, and while they each made the UX a little better, none of them made it actually make it good. And then STCOR-1012 showed up, telling us things were not only not good; they were, in fact, pretty bad. It was a mess. It was just a mess. 💩And that brings us here, to the fourth full-blown rewrite of RTR. Hopefully, the logic here is simpler, better isolated, and easier to reason about. At the highest level, things are still the same: we're replacing native-fetch with FFetch, which transparently handles rotation. The FFetch algorithm now works like this:
ok, callrotateAndReplay()to rotate the tokens and replay the original requestrotateAndReplayworks like this:Checking, while inside the lock, whether the tokens have already been rotated is a crucial step that handles the situation of many requests firing simultaneously after the tokens have expired. The Web Locks API elects one request, allowing rotation, storage, and replay to proceed for that request only while all others wait for the lock's promise to resolve. After that first request releases its lock, the next request in the queue proceeds through
rotateAndReplay(), but this time it will return early since the token-expiration data in storage will be valid. Note: this means requests that are queued together proceed single-threaded through the lock. This sounds worse than it is sincerotateAndReplay()short-circuits after the first request, jumping immediately to "replay" since valid tokens are now available.But wait! There's more! The original implementation stored the end-of-session timer-IDs in redux. It's important to keep track of those IDs so they can be cleared if the user logs out early or session expiration is configured as a window that slides on rotation, as non-keycloak sessions are. Anybody remember UICHKOUT-869? Using redux was problematic for two reasons:
The self-contained, self-clearing timer ResetTimer (maybe I should've called it SelfClearingTimer? 🤔) resolves both: redux actions are once again pure, and Root no longer re-renders with each rotation.
Refs STCOR-1012, UITEN-333, STCOR-1025