fix(shell-ui): persist login session in localStorage across tabs and restarts#1555
Conversation
The rr_ session token is a 90-day sliding server-side session; keeping it
in sessionStorage was the only reason every tab/restart forced re-auth.
Move to localStorage with one-time migration and cross-tab storage sync.
Fixes rocketride-ai/rocketride-saas#303
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAuthentication tokens now persist in ChangesAuthentication persistence and synchronization
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant BrowserStorage
participant ConnectionManager
participant WindowReload
BrowserStorage->>ConnectionManager: LS_TOKEN storage event
ConnectionManager->>ConnectionManager: Reset auth state when token is removed
ConnectionManager->>WindowReload: Reload page after token removal or external addition
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🤖 Internal: Discord sync markerAuto-managed by the Discord notification workflow. Stores the linked Discord message ID and forum thread ID. Do not edit or delete. |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/shell-ui/src/connection/connection.ts`:
- Around line 314-335: Update the storage event handler for LS_TOKEN to handle
token replacement when both event.oldValue and event.newValue are non-null,
triggering the appropriate reload or reconnect so the tab adopts the newly
authenticated session while preserving the existing logout and initial-login
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5569b518-6c5d-4ecb-a5bf-8c059f84e06c
📒 Files selected for processing (4)
apps/shell-ui/src/auth/ApiKeyAuthProvider.tsapps/shell-ui/src/auth/CloudAuthProvider.tsapps/shell-ui/src/connection/connection.tsapps/shell-ui/src/constants.ts
|
@coderabbitai Addressed in 4c3b732 — a token replacement (both oldValue and newValue non-null) on a connected tab now reloads so the tab adopts the new session; add/remove behaviors unchanged. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
cd rocketride-server 2>/dev/null || true
git fetch origin 4c3b732a --depth=1 2>&1 | tail -5
git show 4c3b732a --stat 2>&1 | head -20
git show 4c3b732a -- apps/shell-ui/src/connection/connection.ts 2>&1 | head -100Length of output: 1532
if (
event.oldValue !== null &&
event.newValue !== null &&
this.isConnected() &&
this.accountInfo?.userToken === event.oldValue
) {
window.location.reload();
return;
}This reloads a connected tab when its current token is swapped for a new one (e.g., re-login in another tab), while leaving the add ( |
…into fix/303-persistent-session # Conflicts: # apps/shell-ui/src/connection/connection.ts
Login session dies with the tab: token lives in sessionStorage
rr:user_tokenwas stored insessionStorage, so every new tab, window, or browser restart forced a full OAuth round-trip (reported in rocketride-ai/rocketride-saas#303).Why not refresh tokens: tracing the token lifecycle showed the
rr_userToken is a 90-day sliding server-side session key (ensure_session_keyre-extends it on every login) — not a short-lived access token. Zitadel refresh tokens are received and discarded server-side and add nothing for session persistence. The entire bug is the storage location.Fix:
localStorage(with a one-timesessionStorage→localStoragemigration so live sessions survive the deploy), inCloudAuthProvider, theConnectionManagerhelpers, andApiKeyAuthProviderfor consistency.storageevent: signing out in one tab logs out the others; a sign-in is picked up by unauthenticated tabs.Security note for review: the
rr_token is DB-backed and individually revocable (api_keystable), which bounds the localStorage XSS-theft delta; the 90-day sliding session semantics are unchanged, only where the client keeps the key.Stacked on #1553 (base is
fix/305-network-vs-auth-errors; GitHub will retarget todevelopwhen it merges — the diff here is one commit).Testing
localStoragewithsessionStorageempty after login; second tab signed in without a redirect; fresh browser context restored from storage state ("restart") signed in; removing the token in tab A logs out tab B.tsc --noEmitclean.Linked Issue
Fixes rocketride-ai/rocketride-saas#303
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes