fix(auth): re-check auth status after logout; clear NextAuth session after sync

1) Sidebar logout flow:
   - After AuthReset, also dispatch AuthStatusCheckSubmitted so the auth
     machine re-verifies storage (not just resets to initialState). This
     makes sure the redirect to /chat reflects the actual storage state,
     not just the forcibly-cleared context.

2) OAuthSessionSync:
   - After dispatching AuthGoogleSyncSubmitted / AuthFacebookSyncSubmitted,
     call signOut({ redirect: false }) to drop the NextAuth session.
     The OAuth idToken / accessToken has already been handed to the
     backend; clearing the browser-side session prevents lingering OAuth
     credential exposure. Fire-and-forget — once status flips to
     "unauthenticated", the useEffect early-returns so no re-entry.

Note: auth-machine.ts lost a 3-line stale comment block about XState v5
type inference for inline assign; bundled with this commit.
This commit is contained in:
2026-06-16 18:24:23 +08:00
parent a44463b3ee
commit 39e7d61c8a
3 changed files with 15 additions and 6 deletions
@@ -52,7 +52,12 @@ export function SidebarScreen() {
const isNowLoggedOut = user.currentUser == null;
prevUserRef.current = user.currentUser;
if (wasLoggedIn && isNowLoggedOut) {
// 1) AuthReset:清场(清 email/password/username 等敏感字段)
authDispatch({ type: "AuthReset" });
// 2) AuthStatusCheckSubmitted:通过 storage 重新验证实际 auth 状态
// userLogoutActor 已清空 userStoragecheckAuthStatusActor 会返 "notLoggedIn"
// 这一步确保 redirect 到 /chat 后,chat-screen 看到的是真实 storage 状态而非 AuthReset 直接置的 initialState
authDispatch({ type: "AuthStatusCheckSubmitted" });
router.replace(ROUTES.chat);
}
}, [user.currentUser, authDispatch, router]);