6 Commits

Author SHA1 Message Date
d6b25dd78d Serialize authenticated requests to fix persistent login redirect loop
The last fix only deduplicated concurrent refresh calls, but the
underlying problem is broader: the backend's session nonce is
single-use and rotates on every authenticated request, so ANY two
concurrent authenticated calls race for it, not just refresh calls.
The dashboard fires ~5 authenticated requests in parallel (summary,
cashflow, merchants, accounts, transactions) plus the app shell's
own profile fetch, all reading the same nonce cookie before any
response updates it. Only the first to reach the server can win;
losers get a nonce-mismatch 401, and if that race happens to catch
the refresh call itself against another still-rotating request,
refresh legitimately fails and forces a hard logout. That's what
produced the "works for a while, then dumped back to login" pattern.

Fix: queue every apiFetch call so only one nonce-consuming request
is ever in flight per tab, refresh-and-retry included. This fully
removes the race within a tab (a second tab open to the same
account is a separate, much rarer case and not what was happening
here). Also redirect to login if a post-refresh retry still 401s,
since under serialization that means the session is genuinely
invalid rather than a timing collision.
2026-08-26 20:41:23 +05:30
136f41020f Deduplicate concurrent token refresh to fix login redirect loop
The dashboard fires several authenticated requests at once (summary,
cashflow, merchants, accounts, transactions, plus the app shell's own
profile fetch). Once the 60-second access-token cookie expires, all
of them 401 together, and apiFetch had each one independently call
/api/auth/refresh. Refresh tokens are single-use and rotate on the
backend, so only the first of these racing calls succeeded — the
rest sent an already-consumed refresh token, got rejected, cleared
auth cookies, and hard-redirected to /login. Symptom: land in the
app, then get bounced back to login almost immediately, repeatedly.

Fix: share one in-flight refresh promise across all callers so a
burst of concurrent 401s triggers exactly one refresh call.
2026-08-26 18:24:08 +05:30
99522a5544 Point frontend proxy to Aarthalabs API 2026-07-30 07:45:14 +05:30
edbcbea5b4 Proxy rotating session nonce cookies 2026-07-16 22:17:21 +05:30
2b17c36ed2 feat: implement LedgerOne frontend backlog features 2026-07-16 15:07:02 +05:30
sharada-gif
28cefdc7e7 Polish LedgerOne frontend signup, auth, and marketing UI
Made-with: Cursor
2026-03-18 13:02:58 -07:00