Single-flight session restore so startup no longer clears the session - #717
Merged
Merged
Conversation
gjwgit
requested review from
anushkavidanage,
cdawei,
jesscmoore and
tonypioneer
September 11, 2026 05:49
Contributor
Author
|
Tested extensively with todopod, notepod, diarypod, innerpod, billipod, ++ |
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.
Fixes the login page being shown on every start even while the session
was still valid.
Problem
Two callers reach
AuthDataManager.loadAuthData()on the first frame —solidui's auto-login (
solid_login.dart:274) and its login-statusnotifier (
solid_login_status_notifier.dart:68, viaisUserLoggedIn()→getAccessToken()). The slow path had no in-flight guard, and theawait secureStorage.readyields, so neither caller blocked the other:both built their own
SolidAuthManagerand both POSTed arefresh_tokengrant with the same stored token.The server issues single-use refresh tokens, so the second grant came
back
invalid_grant, andtryRestoreSession()responds to a failedrefresh by clearing the stored session — discarding the session the
first caller had just successfully refreshed. Deterministic rather than
intermittent, because both calls start in the same frame.
No solidpod code change caused this:
lib/is byte-identical between1.0.19 and 1.0.20. The trigger was the dependency bump in 1.0.20, where
solid_auth 1.0.7 sets
initMode: OidcInitMode.blockingValidateand somakes
init()reach the token endpoint during restore — turning aredundant-but-harmless double restore into a double spend.
Fix
Concurrent callers now share one restore, and one refresh once a manager
is live, since that path double-spends the token the same way. The slow
path moved verbatim into
_restoreFromStorage();loadAuthData()is nolonger
asyncso the??=assignment happens before any await point,which is what closes the window.
A completing future cannot null out a newer in-flight future, because a
new one is only created once the field is already null.
Testing
Verified with todopod on Linux desktop via a path override. Before, the
whole startup block appeared twice and ended in two
Clearing stored session. After:The app goes straight to its data instead of the login page, and the
session held for the whole run — no clearing or forced login afterwards.
Worth noting
grant_type=refresh_tokenwas ×0 on the successful run:the cached access token was still valid, so no refresh was needed. That
is the behaviour originally lost, and it confirms the mechanism — the old
code's two racing restores each forced a token-endpoint round trip and
destroyed a session that never needed refreshing.
Not covered
Restore across an actually-expired access token, where a single refresh
does fire. That path is unexercised, so the rotating-token behaviour is
still unverified in practice.
Closes #716