diff --git a/packages/keychain/src/components/disconnect.tsx b/packages/keychain/src/components/disconnect.tsx index 89ca9ba1e..1b687a957 100644 --- a/packages/keychain/src/components/disconnect.tsx +++ b/packages/keychain/src/components/disconnect.tsx @@ -13,6 +13,11 @@ export const Disconnect = () => { (async () => { if (!controller || isDone) return; await controller.disconnect(); + try { + localStorage.clear(); + } catch { + // Ignore if localStorage is unavailable + } setIsDone(true); if (urlSearchParams) { const redirectUrl = urlSearchParams.get("redirect_url"); diff --git a/packages/keychain/src/hooks/connection.ts b/packages/keychain/src/hooks/connection.ts index f2bd0ab42..b93701696 100644 --- a/packages/keychain/src/hooks/connection.ts +++ b/packages/keychain/src/hooks/connection.ts @@ -402,6 +402,11 @@ export function useConnectionValue() { (async () => { await controller.disconnect(); + try { + localStorage.clear(); + } catch { + // Ignore if localStorage is unavailable + } setController(undefined); })(); }, [controller, urlRpcUrl, setController, setRpcUrl]); @@ -854,6 +859,13 @@ export function useConnectionValue() { const logout = useCallback(async () => { await window.controller?.disconnect(); + // Clear localStorage directly to handle storage partition mismatches + // caused by requestStorageAccess() switching contexts + try { + localStorage.clear(); + } catch { + // Ignore if localStorage is unavailable + } window.location.reload(); if (parent) { parent.close(); diff --git a/packages/keychain/src/utils/connection/index.ts b/packages/keychain/src/utils/connection/index.ts index 0f452f973..122583663 100644 --- a/packages/keychain/src/utils/connection/index.ts +++ b/packages/keychain/src/utils/connection/index.ts @@ -102,14 +102,28 @@ export function connectToController< disconnect: () => async () => { // First clear the React state setController(undefined); - // Then cleanup the controller + // Then cleanup the controller (WASM clears its storage backend) await window.controller?.disconnect(); + // Also clear localStorage directly from JS to handle storage partition + // mismatches caused by requestStorageAccess() switching between + // partitioned and unpartitioned storage contexts. + try { + localStorage.clear(); + } catch { + // Ignore if localStorage is unavailable + } }, logout: () => async () => { // First clear the React state setController(undefined); - // Then cleanup the controller + // Then cleanup the controller (WASM clears its storage backend) await window.controller?.disconnect(); + // Also clear localStorage directly from JS (see disconnect above) + try { + localStorage.clear(); + } catch { + // Ignore if localStorage is unavailable + } }, username: () => () => window.controller?.username(), delegateAccount: () => () => window.controller?.delegateAccount(),