diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-17 17:38:00 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-17 17:38:00 +0200 |
| commit | 6562665c80f96f30fef95af83a0abcf71f41795f (patch) | |
| tree | d210f4c969b9b3881aba6d7d3573aa96b7831197 /packages/meshbay-node/src | |
| parent | af30a10b83366416c25eaacec0b4df77526d0924 (diff) | |
| download | meshbay-6562665c80f96f30fef95af83a0abcf71f41795f.tar.gz | |
fix(hub): a session that renews itself
Reported: after an hour of watching a film, every action answers "token expired
or invalid", with signing out and back in as the only way on. Reopening the tab
the next day did the same.
The access token lasts an hour and the refresh token thirty days, and nothing
used the second one. `hubFetch` reported a 401 like any other error, and
watching a film is precisely an hour in which the hub hears nothing at all,
because the video travels over WebRTC. So the token aged out with no request to
notice, and a tab reopened the next morning presented a stale token with a
perfectly good refresh token sitting beside it in localStorage.
Underneath was the reason it could not be recovered from. The hub *rotates*:
the refresh endpoint revokes the token presented, returns a replacement, and
treats a revoked one presented again as theft, revoking the whole family. The
client kept only the access token out of that response. So the refresh token was
spent on first use and the second attempt did not merely fail — it destroyed the
family. Which is exactly the reported symptom.
Renewal now happens on a margin, on returning to the tab, on mount, and on a 401
with the request replayed. Concurrent renewals share one request: two 401s
racing would otherwise present the same refresh token twice, and the hub cannot
tell that from theft, so the remedy would have been worse than the fault. A
refusal signs out cleanly rather than leaving a session that fails every call
while looking signed in.
The lifetime goes to four hours, which is not what makes long sessions work —
renewal is — but is what someone has to notice by if renewal itself breaks. An
hour was less than a feature film. Twelve was considered and declined: it widens
the window in which a leaked token cannot be turned off, and it lets the renewal
path go a whole day between uses, which is how it came to be broken here without
anyone noticing. Production sets this in its own hub.toml, so both moved.
The tests run the shipped code against a hub that enforces rotation, because a
stub that accepted the same refresh token twice would have passed against the
broken client. Checked that dropping the rotated token reproduces the revoked
family, so the guard is guarding something.
Also widens the orphan-setter rule to ignore `setX` functions declared in the
module: `setAuth` is not a hook setter, and a rule that cries wolf is one
somebody eventually silences. Verified it still catches a real orphan.
Diffstat (limited to 'packages/meshbay-node/src')
0 files changed, 0 insertions, 0 deletions