Tweak browser extension logout flow to suppress session errors (#1325)

This commit is contained in:
Leendert de Borst
2025-10-31 12:10:40 +01:00
committed by Leendert de Borst
parent c134c2642a
commit 3664f5bc20
7 changed files with 13 additions and 42 deletions

View File

@@ -12,7 +12,6 @@ import { useLoading } from '@/entrypoints/popup/context/LoadingContext';
import { NavigationProvider } from '@/entrypoints/popup/context/NavigationContext';
import AuthSettings from '@/entrypoints/popup/pages/auth/AuthSettings';
import Login from '@/entrypoints/popup/pages/auth/Login';
import Logout from '@/entrypoints/popup/pages/auth/Logout';
import Unlock from '@/entrypoints/popup/pages/auth/Unlock';
import UnlockSuccess from '@/entrypoints/popup/pages/auth/UnlockSuccess';
import Upgrade from '@/entrypoints/popup/pages/auth/Upgrade';
@@ -168,7 +167,6 @@ const App: React.FC = () => {
{ path: '/settings/language', element: <LanguageSettings />, showBackButton: true, title: t('settings.language') },
{ path: '/settings/auto-lock', element: <AutoLockSettings />, showBackButton: true, title: t('settings.autoLockTimeout') },
{ path: '/settings/passkeys', element: <PasskeySettings />, showBackButton: true, title: t('settings.passkeySettings') },
{ path: '/logout', element: <Logout />, showBackButton: false },
], [t]);
useEffect(() => {

View File

@@ -1,4 +1,4 @@
import React, { createContext, useContext, useMemo, useCallback, useEffect, useState } from 'react';
import React, { createContext, useContext, useMemo, useCallback, useEffect, useState, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useAuth } from '@/entrypoints/popup/context/AuthContext';
@@ -15,7 +15,6 @@ type AppContextType = {
setAuthTokens: (username: string, accessToken: string, refreshToken: string) => Promise<void>;
globalMessage: string | null;
clearGlobalMessage: () => void;
isLoggingOut: boolean;
}
const AppContext = createContext<AppContextType | undefined>(undefined);
@@ -27,7 +26,7 @@ export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children
const auth = useAuth();
const webApi = useWebApi();
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [isLoggingOut, setIsLoggingOut] = useState(false);
const isLoggingOutRef = useRef(false);
const { t } = useTranslation();
/**
@@ -35,23 +34,21 @@ export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children
* Prevents recursive logout calls by tracking logout state.
*/
const logout = useCallback(async (errorMessage?: string): Promise<void> => {
// Prevent recursive logout calls
if (isLoggingOut) {
console.debug('Logout already in progress, ignoring duplicate call');
if (isLoggingOutRef.current) {
return;
}
try {
setIsLoggingOut(true);
webApi.revokeTokens();
auth.clearAuth(errorMessage);
setIsLoggedIn(false);
isLoggingOutRef.current = true;
await webApi.revokeTokens();
await auth.clearAuth(errorMessage);
} catch (error) {
console.error('Error during logout:', error);
} finally {
setIsLoggingOut(false);
isLoggingOutRef.current = false;
setIsLoggedIn(false);
}
}, [auth, webApi, isLoggingOut]);
}, [auth, webApi]);
/**
* Initialize the authentication state.
@@ -93,7 +90,6 @@ export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children
setAuthTokens: auth.setAuthTokens,
clearGlobalMessage: auth.clearGlobalMessage,
isLoggedIn: isLoggedIn,
isLoggingOut: isLoggingOut,
}), [
auth.isInitialized,
auth.username,
@@ -103,7 +99,6 @@ export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children
logout,
initializeAuth,
isLoggedIn,
isLoggingOut,
]);
return (

View File

@@ -52,7 +52,6 @@ export const NavigationProvider: React.FC<{ children: React.ReactNode }> = ({ ch
'/unlock-success',
'/auth-settings',
'/upgrade',
'/logout',
'/passkeys/create',
'/passkeys/authenticate'
];

View File

@@ -1,21 +0,0 @@
import React, { useEffect } from 'react';
import { useApp } from '@/entrypoints/popup/context/AppContext';
/**
* Logout page.
*/
const Logout: React.FC = () => {
const app = useApp();
/**
* Logout and navigate to home page.
*/
useEffect(() => {
app.logout();
}, [app]);
// Return null since this is just a functional component that handles logout.
return null;
};
export default Logout;

View File

@@ -152,7 +152,7 @@ const Unlock: React.FC = () => {
* Handle logout
*/
const handleLogout = () : void => {
navigate('/logout', { replace: true });
app.logout();
};
return (

View File

@@ -24,7 +24,7 @@ import { VaultSqlGenerator } from '@/utils/dist/shared/vault-sql';
*/
const Upgrade: React.FC = () => {
const { t } = useTranslation();
const { username } = useApp();
const { username, logout } = useApp();
const dbContext = useDb();
const { sqliteClient } = dbContext;
const { setHeaderButtons } = useHeaderButtons();
@@ -206,7 +206,7 @@ const Upgrade: React.FC = () => {
* Handle the logout.
*/
const handleLogout = async (): Promise<void> => {
navigate('/logout');
logout();
};
/**

View File

@@ -109,7 +109,7 @@ const Settings: React.FC = () => {
* Handle logout.
*/
const handleLogout = async () : Promise<void> => {
navigate('/logout', { replace: true });
app.logout();
};
/**