Repository navigation
Description
Summary
In @uvdsl/solid-oidc-client-browser 0.2.3 the sessionStateChange event fires only when
isActive flips. An identity change on its own — webId A → B while both states are active
— is silent. Applications that invalidate identity-derived state on this event keep answering
for the previous identity until something unrelated happens to notice.
The event payload already carries the WebID
(dist/esm/core/index.js ~2404):
dispatchStateChangeEvent () {
this.dispatchEvent(new CustomEvent(SessionEvents.STATE_CHANGE,
{ detail: { isActive: this.isActive, webId: this.webId } }))
}…so only the dispatch conditions need to consider it.
Where it is (and isn't) dispatched
| Path | Dispatch | Condition |
|---|---|---|
handleRedirectFromLogin() (~2151) |
yes | unconditional ("we logged in") |
restore() finally (~2188) |
yes | if (wasActive !== this.isActive) — activeness only |
logout() (~2218) |
yes | unconditional ("we logged out") |
setTokenDetails() (~2273) |
no | every token update goes through here |
WebWorkerSession.handleWorkerMessage, TOKEN_DETAILS (web ~2607) |
yes | if (wasActive !== this.isActive) — activeness only |
Why this happens in practice
A SharedWorker and a shared soidc IndexedDB per origin mean one tab can change the stored
session for all of them:
- Tab A is active as Alice.
- Bob logs in in another tab/window of the same origin (the database is cleared and rewritten).
- Tab A's next
restore()/worker refresh reads Bob's tokens:setTokenDetailsupdates
webIdto Bob,isActivestaystrue. - Both activeness-only checks are false — no
sessionStateChangereaches tab A's
listeners, and tab A continues to treat itself as Alice.
(Any in-place identity switch delivered through setTokenDetails has the same shape; the
shared-database case is the reproducible one.)
Impact
Consumers subscribing to sessionStateChange to invalidate per-identity state miss the
transition. Concrete example: SolidOS solid-logic caches which documents are writable —
editable() answers from response metadata that is not keyed by identity — and clears it
on each transition. With this gap, a tab whose WebID switched to Bob keeps showing Alice's
editability (and can act on the wrong assumption) until a refocus or a load happens to
refresh the document.
We currently work around it on the consumer side by wrapping setTokenDetails and comparing
(isActive, webId) before/after (SolidOS/solid-logic#328) — fragile, and it belongs here.
Suggested fix
Option A (smallest — keep the existing sites, add the identity term):
restore(): capturewasWebIdnext towasActiveand dispatch when
wasActive !== this.isActive || wasWebId !== this.webId.WebWorkerSession.handleWorkerMessageTOKEN_DETAILS: same comparison.
Option B (single source of truth): dispatch from setTokenDetails, since every update
(restore, redirect, worker) passes through it:
async setTokenDetails (tokenDetails) {
const wasActive = this.isActive
const wasWebId = this.webId
this.information.tokenDetails = tokenDetails
await this._updateSessionDetailsFromToken(tokenDetails.access_token)
if (wasActive !== this.isActive || wasWebId !== this.webId) {
this.dispatchStateChangeEvent()
}
}With B the site checks become redundant (and the explicit dispatches in
handleRedirectFromLogin/logout could stay for their other state changes, or be removed to
avoid duplicate events — consumers should be idempotent either way).
Worth stating in the event docs either way: listeners should treat sessionStateChange as
"the session's identity or activity may have changed".
Environment
@uvdsl/solid-oidc-client-browser0.2.3 (dist/esm/core/index.js,dist/esm/web/index.js)- Repo: https://github.com/uvdsl/solid-oidc-client-browser
- Consumer context: SolidOS
solid-logic(uvdsl session migration), PR #328
Activity
uvdsl commentedon Sep 16, 2026
Thanks @bourgeoa!
I did not consider the case where a session is active and then somebody logs in with a different account on top of that from a different tab (e.g., Bob).
I thought the new tab (Bob's tab) should automatically assume the already existing session (Alice's session).
If one wanted to switch accounts, one would need to logout, and then login with the other account.
What behavior are you desiring?
On the technical side, I think that your suggestion to add the WebID comparison (former vs. current) is a fine addition.
I recall removing that check at some point based on my understanding above... oh well.
bourgeoa commentedon Sep 17, 2026
I think yes it is simple and easy for the user and is considered a plus from your library.
exemple in SolidOS opening a same server link in a new tab
I personally think yes.
What is important is that the app can be aware of the change to be able to take action