Skip to content

fix(auth): never persist refresh token to localStorage; rely on httpOnly cookie (Closes #898) - #926

Merged
Topmatrixmor2014 merged 1 commit into
FinChippay:mainfrom
waterWang:fix/remove-refresh-token-localstorage
Aug 26, 2026
Merged

fix(auth): never persist refresh token to localStorage; rely on httpOnly cookie (Closes #898)#926
Topmatrixmor2014 merged 1 commit into
FinChippay:mainfrom
waterWang:fix/remove-refresh-token-localstorage

Conversation

@waterWang

Copy link
Copy Markdown
Contributor

Closes #898

Problem

The backend already sets the refresh token as an httpOnly, SameSite=strict cookie, but the frontend still referenced a finchippay_refresh_token localStorage key in several auth/wallet code paths. Any XSS could exfiltrate a token stored in localStorage, undermining exactly what the httpOnly cookie was designed to prevent.

Fix

  • frontend/lib/auth.ts: getRefreshToken/setRefreshToken/clearJwtToken now only track a boolean finchippay_has_session session flag — the actual refresh token is never written to localStorage. Token refresh rides the backend httpOnly cookie via credentials: "include" on /api/auth/refresh.
  • frontend/lib/wallet.ts: removed the redundant finchippay_refresh_token localStorage cleanup in disconnectWallet (logout already clears via clearAuthToken).
  • Defence-in-depth: setRefreshToken/clearJwtToken still purge any legacy residual finchippay_refresh_token key left by earlier versions, so upgrading cleans old insecure data.

Tests

Added __tests__/auth.test.ts (8 tests) covering:

  • No refresh token is ever written to localStorage.
  • Session presence is tracked via a boolean flag, not the token value.
  • clearJwtToken removes the session flag and purges residual keys.
  • /api/auth/refresh is called with credentials: "include" and never sends the token as header/body.
  • withAuth preemptively refreshes via the cookie when only a session flag exists.

All 8 tests pass.

Note: the existing sdk-instance.ts has a pre-existing backslash-escape corruption on main (introduced in the SDK auth PR) that breaks unrelated test suites; it is out of scope for this issue.

@github-actions github-actions Bot added the needs-review PR ready for Greptile AI code review label Aug 26, 2026
@github-actions

Copy link
Copy Markdown

🤖 Greptile AI Code Review

Greptile will automatically review this PR (3 file(s) changed).

Review gates:

  • ✅ CodeQL Security Scan
  • ✅ Custom rules (.greptile/config.json)
  • ✅ Architecture guidelines (.greptile/rules.md)

To manually trigger a re-review, comment @greptileai on this PR.
To skip review, add the skip-review label.

});

describe("auth refresh flow via httpOnly cookie", () => {
const API_URL = "http://localhost:4000";
@Topmatrixmor2014
Topmatrixmor2014 merged commit 7da90a8 into FinChippay:main Aug 26, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review PR ready for Greptile AI code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

#120 — Persists the Refresh Token in While the Backend Sets an Cookie

3 participants