mirror of
https://github.com/twentyhq/twenty.git
synced 2026-09-16 07:56:04 -04:00
> **Scope changed.** #24983 was merged into this branch, so this PR now carries both changes: the e2e helper refactor **and** the token-pair clear. It is no longer the e2e-only PR its original description covered. Still stacked on #24981. ## 1. e2e: authenticate direct backend calls by session cookie `getAccessAuthToken` read the token pair out of `localStorage` to build a `Bearer` header. `login.setup.ts` saves storage state straight after sign-in with no reload, so the pair is there today — but `CookieSessionBootEffect` switches the client onto the session cookie on the first authenticated page load, and once part 2 clears the pair the helper throws `"No auth token pair found in local storage"`. `page.request` shares the browser context's cookie jar, so these calls now carry the session cookie the app itself uses. `CookieSessionCsrfMiddleware` fails closed on a missing `Origin` for a cookie-authenticated write and `page.request` sends none, so the shared helper sets it from `FRONTEND_BASE_URL`, which the server already resolves as an allowed credentialed origin. ## 2. front: clear the token pair once the client switches to cookie auth Closes core-team-issues#2756. #23755 kept the pair as a dormant fallback because a server with `AUTH_COOKIE_SESSIONS_ENABLED=false` ignores the session cookie. That flag no longer exists — #24257 removed it and every branch behind it, so no deployed configuration can turn cookie sessions off. The fallback's only remaining effect was keeping a 60-day refresh token in `localStorage`, which is the XSS-exfiltration surface cookie sessions exist to close. `switchToCookieAuth` clears the pair again, and the fallback it fed goes with it: `canFallBackFromCookieAuth`, the cookie-auth branch in `handleTokenRenewal`, and the `isMissingCredentialGraphQLError` branch from #24275 — which was gated on a retained refresh token and so could never fire once the pair is gone. `isMissingCredentialGraphQLError.ts` and `setIsCookieAuthActive.ts` lose their only consumers. Also fixes a race the review caught: `attemptTokenRenewal` published through `onTokenPairChange` unconditionally while `ensureTokenRenewed` guards the same write behind a refresh-token snapshot. A renewal in flight when the boot effect probes could resolve after the clear and put a fresh refresh token back for the rest of the session, since the boot effect only probes while cookie auth is inactive. It now takes the same snapshot. Regression test included. Two things deliberately kept: - **The auth link still suppresses `Bearer` while cookie auth is active.** A pair exists between sign-in and the boot effect's switch, and across the impersonation exchange; sending it would take precedence over the session cookie and bypass the CSRF origin check. - **`FORBIDDEN` stays in `AUTH_REFUSAL_CODES`.** A new bundle talking to a server predating #24981 still gets `FORBIDDEN` on the probe. ## Sequencing Recovery from a session cookie the server does not accept now rests entirely on the server reporting `UNAUTHENTICATED`. `WorkspaceAuthGuard` has done so since #24276; `UserAuthGuard` does as of #24981, which is this PR's base. **Without #24981 in place first, part 2 reopens the blank-app wedge for `UserAuthGuard` resolvers, `currentUser` among them.** The stacked base enforces the order. ## What this does not fix The pair is not removed for a freshly signed-in tab: sign-in still stores one and navigates client-side, and the boot effect has already spent its single probe on the sign-in page. That window closes only when the web token-pair machinery is deleted outright — core-team-issues#2747, gated on the 60-day refresh window. ## CI Both CI failures on this stack were confirmed transient by re-run on identical commits: `server-integration-test (9)` (one runner's database had not migrated; 15/16 shards green) and `front-sb-test (3, pages)` (lost iframe, zero tests run; 11/12 shards green). Both passed on attempt 2 with no code change.