Skip to content

Drop redundant localStorage.setItem in TokenHandler (already done by setBearerToken) #1365

@MODSetter

Description

@MODSetter

Problem

surfsense_web/components/TokenHandler.tsx writes the bearer token to localStorage twice in a row:

// surfsense_web/components/TokenHandler.tsx, lines 47–49
localStorage.setItem(storageKey, token);   // <-- redundant
setBearerToken(token);                     // already does the same write + Electron sync

Looking at setBearerToken in surfsense_web/lib/auth-utils.ts:94:

export function setBearerToken(token: string): void {
    if (typeof window === "undefined") return;
    localStorage.setItem(BEARER_TOKEN_KEY, token); // BEARER_TOKEN_KEY === "surfsense_bearer_token"
    syncTokensToElectron();
}
  • BEARER_TOKEN_KEY (auth-utils) and TokenHandler's default storageKey are both "surfsense_bearer_token".
  • The only caller of <TokenHandler> (surfsense_web/app/auth/callback/page.tsx:14) explicitly passes storageKey="surfsense_bearer_token" — same value.
  • The first localStorage.setItem(storageKey, token) writes to the same key setBearerToken writes to immediately after, but without triggering syncTokensToElectron.

Result: a redundant write that creates a brief inconsistent state and tempts "simplification" in the wrong direction. The token-write adapter is split across two lines.

Files

  • surfsense_web/components/TokenHandler.tsx (lines 47–49, props at 24–28)
  • surfsense_web/app/auth/callback/page.tsx (the only caller)

What to do

  1. In TokenHandler.tsx, delete line 48 (localStorage.setItem(storageKey, token);). Keep setBearerToken(token) — it owns the write + Electron sync.
  2. Since the only caller passes the default value for storageKey, also remove the storageKey prop entirely (it's no longer used). Update auth/callback/page.tsx to drop the prop.
  3. (Optional) Update the JSDoc on TokenHandler to remove the now-stale storageKey reference.
  4. Test the OAuth callback flow end-to-end: Google sign-in → confirm bearer + refresh tokens land in localStorage and (on desktop) propagate to Electron.

Why this matters

  • Single token-write adapter: nobody has to wonder "which write wins?" or "why are we writing twice?"
  • Removes a regression trap: a future contributor could remove setBearerToken(...) thinking the raw setItem covers it — silently breaking Electron Quick Ask + Autocomplete windows.
  • Smaller, deeper interface for TokenHandler.

Acceptance criteria

  • TokenHandler.tsx calls setBearerToken only (no raw localStorage.setItem for the bearer)
  • storageKey prop removed (or, if you'd rather keep it for backward compat, document why)
  • auth/callback/page.tsx updated
  • Google OAuth login still works on web and (if you can test) desktop

Difficulty

Good first issue — single-file deletion with one prop cleanup.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions