From 511d1bd7ab2f2fc97aee4318231c60734076e59a Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Wed, 25 Mar 2026 18:35:54 +0100 Subject: [PATCH] Fix SSE event stream errors when impersonating users with limited permissions (#18966) Clear the SSE client before swapping auth tokens during impersonation, preventing a userWorkspaceId mismatch between the existing event stream (created under the admin's identity) and the new impersonation token. Treat NOT_AUTHORIZED event stream errors as recoverable (destroy + recreate), matching the existing behavior for EVENT_STREAM_DOES_NOT_EXIST and EVENT_STREAM_ALREADY_EXISTS. --- .../modules/settings/admin-panel/hooks/useImpersonationAuth.ts | 3 +++ .../sse-db-event/components/SSEQuerySubscribeEffect.tsx | 1 + 2 files changed, 4 insertions(+) diff --git a/packages/twenty-front/src/modules/settings/admin-panel/hooks/useImpersonationAuth.ts b/packages/twenty-front/src/modules/settings/admin-panel/hooks/useImpersonationAuth.ts index 2584f60408..e8e7755a08 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/hooks/useImpersonationAuth.ts +++ b/packages/twenty-front/src/modules/settings/admin-panel/hooks/useImpersonationAuth.ts @@ -1,15 +1,18 @@ import { isAppEffectRedirectEnabledState } from '@/app/states/isAppEffectRedirectEnabledState'; import { useAuth } from '@/auth/hooks/useAuth'; +import { useClearSseClient } from '@/sse-db-event/hooks/useClearSseClient'; import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState'; export const useImpersonationAuth = () => { const { getAuthTokensFromLoginToken } = useAuth(); + const { clearSseClient } = useClearSseClient(); const setIsAppEffectRedirectEnabled = useSetAtomState( isAppEffectRedirectEnabledState, ); const executeImpersonationAuth = async (loginToken: string) => { setIsAppEffectRedirectEnabled(false); + clearSseClient(); await getAuthTokensFromLoginToken(loginToken); setIsAppEffectRedirectEnabled(true); }; diff --git a/packages/twenty-front/src/modules/sse-db-event/components/SSEQuerySubscribeEffect.tsx b/packages/twenty-front/src/modules/sse-db-event/components/SSEQuerySubscribeEffect.tsx index 2ce68bf759..802ca8b205 100644 --- a/packages/twenty-front/src/modules/sse-db-event/components/SSEQuerySubscribeEffect.tsx +++ b/packages/twenty-front/src/modules/sse-db-event/components/SSEQuerySubscribeEffect.tsx @@ -93,6 +93,7 @@ export const SSEQuerySubscribeEffect = () => { const isRecoverable = subCode === 'EVENT_STREAM_DOES_NOT_EXIST' || subCode === 'EVENT_STREAM_ALREADY_EXISTS' || + subCode === 'NOT_AUTHORIZED' || code === 'UNAUTHENTICATED' || code === 'FORBIDDEN';