Skip to content

Commit 35ccd0b

Browse files
committed
fix(workspace): gate stale-session recovery on auth state and surface failed sign-out
1 parent 2ca9814 commit 35ccd0b

1 file changed

Lines changed: 23 additions & 7 deletions

File tree

apps/sim/app/workspace/page.tsx

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useEffect, useRef } from 'react'
3+
import { useEffect, useRef, useState } from 'react'
44
import { Chip } from '@sim/emcn'
55
import { CircleAlert } from '@sim/emcn/icons'
66
import { createLogger } from '@sim/logger'
@@ -27,13 +27,22 @@ function isStaleSessionError(error: unknown): boolean {
2727
return isApiClientError(error) && error.status === 401
2828
}
2929

30-
async function recoverFromStaleSession(): Promise<void> {
30+
/**
31+
* Signs out (clearing every auth cookie server-side), wipes per-user client
32+
* state, and navigates to login. Returns false without navigating when the
33+
* sign-out request fails — the cookies are still set, so going to /login
34+
* would only get bounced back to /workspace by the middleware.
35+
*/
36+
async function recoverFromStaleSession(): Promise<boolean> {
3137
try {
32-
await Promise.all([signOut(), clearUserData()])
38+
await signOut()
3339
} catch (error) {
3440
logger.error('Failed to sign out while recovering from a stale session:', error)
41+
return false
3542
}
43+
await clearUserData()
3644
window.location.assign('/login')
45+
return true
3746
}
3847

3948
export default function WorkspacePage() {
@@ -42,6 +51,7 @@ export default function WorkspacePage() {
4251
const isAuthenticated = !isSessionPending && !!session?.user
4352
const hasRedirectedRef = useRef(false)
4453
const isRecoveringRef = useRef(false)
54+
const [recoveryFailed, setRecoveryFailed] = useState(false)
4555

4656
const {
4757
data,
@@ -50,11 +60,15 @@ export default function WorkspacePage() {
5060
} = useWorkspacesWithMetadata(isAuthenticated)
5161

5262
useEffect(() => {
53-
if (!isStaleSessionError(workspacesError) || isRecoveringRef.current) return
63+
if (!isAuthenticated || !isStaleSessionError(workspacesError) || isRecoveringRef.current) return
5464
isRecoveringRef.current = true
5565
logger.warn('Session cookies are stale (authenticated session but 401 API); signing out')
56-
void recoverFromStaleSession()
57-
}, [workspacesError])
66+
void recoverFromStaleSession().then((recovered) => {
67+
if (recovered) return
68+
isRecoveringRef.current = false
69+
setRecoveryFailed(true)
70+
})
71+
}, [isAuthenticated, workspacesError])
5872

5973
useEffect(() => {
6074
if (isSessionPending || hasRedirectedRef.current) return
@@ -98,7 +112,9 @@ export default function WorkspacePage() {
98112
}, [session, isSessionPending, sessionError, isWorkspacesLoading, workspacesError, data, router])
99113

100114
const failedToLoad =
101-
Boolean(sessionError) || (Boolean(workspacesError) && !isStaleSessionError(workspacesError))
115+
recoveryFailed ||
116+
Boolean(sessionError) ||
117+
(isAuthenticated && Boolean(workspacesError) && !isStaleSessionError(workspacesError))
102118

103119
if (failedToLoad) {
104120
return (

0 commit comments

Comments
 (0)