Files
twenty/packages/twenty-front
Félix MalfaitandGitHub b6c62b3812 fix(auth): use dynamic SSE headers and add token renewal retry logic (#18706)
## Summary

- **Dynamic SSE headers**: The `graphql-sse` client was created with a
static `Authorization` header captured at creation time. When the access
token refreshed, the SSE client kept using the expired token on every
reconnection attempt, causing up to 10 wasted retries before the client
was disposed and recreated. Now `headers` is passed as a function that
reads the latest token from the Jotai store on each connection attempt.

- **Token renewal retry with error classification**:
`handleTokenRenewal` previously had zero retry tolerance — any failure
during `renewToken` (including transient network errors, server 500s, or
timeouts) triggered an immediate full logout via
`onUnauthenticatedError()`. Now the renewal retries up to 3 times with
linear backoff for transient errors. Only explicit server rejections
(`CombinedGraphQLErrors`, e.g. expired/revoked refresh token) skip
retries and proceed to logout immediately.

- **Preserved error types in `renewTokenMutation`**: The old code caught
all errors and re-threw them as a generic `new Error('Something went
wrong...')`, destroying the original error type. Callers couldn't
distinguish a GraphQL auth rejection from a network failure. Now errors
propagate with their original type.

- **Simplified SSE retry handler**: With dynamic headers handling token
freshness automatically, the retry handler no longer needs the
`initialTokenForSseClient` comparison to detect token mismatches. It now
only resets the SSE client when the user has logged out (no token) or
after 10+ consecutive failures.

## Test plan

- [ ] Log in, wait for access token to expire (~30 min or configure
shorter expiry), verify no unexpected logout occurs
- [ ] Simulate transient network failure during token renewal (e.g.
throttle network in devtools), verify the retry logic recovers without
logging out
- [ ] Verify SSE real-time updates continue working after a token
refresh
- [ ] Verify genuine logout still works when refresh token is actually
invalid/expired
- [ ] Open multiple browser tabs, verify token refresh works correctly
across all tabs without "suspicious activity" revocation


Made with [Cursor](https://cursor.com)
2026-03-18 15:08:30 +01:00
..
2026-02-17 11:24:33 +01:00

Run yarn dev while server running on port 3000