Skip to content

fix(shell-ui): persist login session in localStorage across tabs and restarts#1555

Merged
kgarg2468 merged 4 commits into
fix/305-network-vs-auth-errorsfrom
fix/303-persistent-session
Jul 18, 2026
Merged

fix(shell-ui): persist login session in localStorage across tabs and restarts#1555
kgarg2468 merged 4 commits into
fix/305-network-vs-auth-errorsfrom
fix/303-persistent-session

Conversation

@kgarg2468

@kgarg2468 kgarg2468 commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Login session dies with the tab: token lives in sessionStorage

rr:user_token was stored in sessionStorage, 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_key re-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:

  • Token persistence moves to localStorage (with a one-time sessionStoragelocalStorage migration so live sessions survive the deploy), in CloudAuthProvider, the ConnectionManager helpers, and ApiKeyAuthProvider for consistency.
  • Cross-tab sync via the storage event: 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_keys table), 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 to develop when it merges — the diff here is one commit).

Testing

  • Tested locally — Playwright on the local Zitadel stack: token present in localStorage with sessionStorage empty 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 --noEmit clean.
  • Commit messages follow conventional commits
  • No secrets or credentials included

Linked Issue

Fixes rocketride-ai/rocketride-saas#303

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Authentication sessions now persist across browser tabs, windows, refreshes, and restarts.
    • Sign-in state synchronizes automatically across open tabs.
    • Existing session data is migrated automatically to the new persistence behavior.
  • Bug Fixes

    • Signing out in one tab now reliably clears the session and disconnects other tabs.

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>
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • develop
  • release/.*

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ff24ad64-8b90-4520-8069-08a26a1bc7a4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Authentication tokens now persist in localStorage across providers and connection management. ConnectionManager migrates legacy session tokens and synchronizes authentication state across tabs through LS_TOKEN storage events.

Changes

Authentication persistence and synchronization

Layer / File(s) Summary
Auth provider localStorage persistence
apps/shell-ui/src/auth/ApiKeyAuthProvider.ts, apps/shell-ui/src/auth/CloudAuthProvider.ts, apps/shell-ui/src/constants.ts
API key and OAuth tokens are stored, retrieved, and removed through localStorage; related documentation reflects the new persistence behavior.
Connection token migration and cross-tab synchronization
apps/shell-ui/src/connection/connection.ts
ConnectionManager migrates legacy sessionStorage tokens, uses localStorage for token lifecycle operations, and reloads or resets connection state when LS_TOKEN changes across tabs.

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
Loading

Suggested reviewers: jmaionchi, rod-christensen, stepmikhaylov

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: moving shell-ui session persistence to localStorage across tabs and restarts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/303-persistent-session

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor
🤖 Internal: Discord sync marker

Auto-managed by the Discord notification workflow. Stores the linked Discord message ID and forum thread ID. Do not edit or delete.

@kgarg2468

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 98e3c64 and 6bb1d84.

📒 Files selected for processing (4)
  • apps/shell-ui/src/auth/ApiKeyAuthProvider.ts
  • apps/shell-ui/src/auth/CloudAuthProvider.ts
  • apps/shell-ui/src/connection/connection.ts
  • apps/shell-ui/src/constants.ts

Comment thread apps/shell-ui/src/connection/connection.ts
@kgarg2468

Copy link
Copy Markdown
Collaborator Author

@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.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

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 -100

Length of output: 1532


@kgarg2468 Confirmed — I checked commit 4c3b732 and the new block correctly handles the token-replacement case:

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 (oldValue === null) and remove (newValue === null) paths untouched. Thanks for closing the gap.

Krish Garg added 2 commits July 12, 2026 15:12
…into fix/303-persistent-session

# Conflicts:
#	apps/shell-ui/src/connection/connection.ts
@kgarg2468
kgarg2468 merged commit 6e314b3 into fix/305-network-vs-auth-errors Jul 18, 2026
5 checks passed
@kgarg2468
kgarg2468 deleted the fix/303-persistent-session branch July 18, 2026 01:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants