fix(auth): prevent unwanted anonymous session after logout by tracking session state
Track previous session existence to avoid minting a new anonymous user when a session ends and the user is redirected to the sign-in page. This prevents clobbering account-scoped preferences by ensuring bootstrapping does not occur during the logout redirect flow.
This commit is contained in:
parent
b8621e64fb
commit
4bfd020125
1 changed files with 18 additions and 0 deletions
|
|
@ -102,6 +102,7 @@ export function AuthLoader({ children }: { children: ReactNode }) {
|
||||||
const [retryNonce, setRetryNonce] = useState(0);
|
const [retryNonce, setRetryNonce] = useState(0);
|
||||||
const attemptedForNullSessionRef = useRef(false);
|
const attemptedForNullSessionRef = useRef(false);
|
||||||
const clearingDisallowedAnonymousRef = useRef(false);
|
const clearingDisallowedAnonymousRef = useRef(false);
|
||||||
|
const hadSessionRef = useRef(false);
|
||||||
const isAuthPage = pathname === '/signin' || pathname === '/signup';
|
const isAuthPage = pathname === '/signin' || pathname === '/signup';
|
||||||
|
|
||||||
// If the auth base URL changes, re-run the bootstrap logic.
|
// If the auth base URL changes, re-run the bootstrap logic.
|
||||||
|
|
@ -116,6 +117,7 @@ export function AuthLoader({ children }: { children: ReactNode }) {
|
||||||
if (isPending) return;
|
if (isPending) return;
|
||||||
|
|
||||||
if (session) {
|
if (session) {
|
||||||
|
hadSessionRef.current = true;
|
||||||
if (!allowAnonymousAuthSessions && session.user.isAnonymous) {
|
if (!allowAnonymousAuthSessions && session.user.isAnonymous) {
|
||||||
if (clearingDisallowedAnonymousRef.current) return;
|
if (clearingDisallowedAnonymousRef.current) return;
|
||||||
clearingDisallowedAnonymousRef.current = true;
|
clearingDisallowedAnonymousRef.current = true;
|
||||||
|
|
@ -154,11 +156,27 @@ export function AuthLoader({ children }: { children: ReactNode }) {
|
||||||
// preferences such as the changelog "last seen version" and re-showing the
|
// preferences such as the changelog "last seen version" and re-showing the
|
||||||
// changelog on every fresh login.
|
// changelog on every fresh login.
|
||||||
if (isAuthPage) {
|
if (isAuthPage) {
|
||||||
|
hadSessionRef.current = false;
|
||||||
setIsAutoLoggingIn(false);
|
setIsAutoLoggingIn(false);
|
||||||
setBootstrapError(null);
|
setBootstrapError(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A session just ended in this tab (sign-out or expiry) and we're still
|
||||||
|
// on an app page while the redirect to /signin is in flight. The session
|
||||||
|
// hook delivers `null` before `router.push('/signin')` finishes its
|
||||||
|
// server roundtrip, so `isAuthPage` is still false here — bootstrapping
|
||||||
|
// now would mint a replacement anonymous user that onLinkAccount links
|
||||||
|
// into the next login, clobbering account-scoped preferences. Redirect
|
||||||
|
// instead of bootstrapping; the ref resets once an auth page mounts.
|
||||||
|
if (hadSessionRef.current) {
|
||||||
|
setIsAutoLoggingIn(false);
|
||||||
|
setBootstrapError(null);
|
||||||
|
setIsRedirecting(true);
|
||||||
|
router.replace('/signin');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid double-calling anonymous sign-in (e.g. React strict mode).
|
// Avoid double-calling anonymous sign-in (e.g. React strict mode).
|
||||||
if (attemptedForNullSessionRef.current) return;
|
if (attemptedForNullSessionRef.current) return;
|
||||||
attemptedForNullSessionRef.current = true;
|
attemptedForNullSessionRef.current = true;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue