Skip to content

Sign-out sweep: serial retry-armed instance logouts stall the CM logout, a failed logout leaves basic-auth on disk, and a re-added entity is skipped #1679

Description

@dawsontoth

Summary

authStore.signOutFromPotentiallyAuthenticatedInstances (src/features/auth/store/authStore.ts) is the per-entity sweep that Studio's Sign out runs before the central-manager /Logout/. Three defects in it were surfaced by the cross-model review of the #1672 fix and are pre-existing, so they were left out of that PR. None is introduced by the fix; all three are still present after it.

1. Instance logouts are serial, retry-armed, and ahead of the central-manager logout

The loop awaits onInstanceLogoutSubmit once per entity, in order, and only then does useLogout post /Logout/ to the central manager and run logoutOnSuccess (which is what clears localStorage). Every client it uses comes from getInstanceClient, which installs curryRetryGatewayErrors: on a 502/503/504 that interceptor sleeps 5s + 10s + 20s before giving up (src/integrations/api/retryGatewayErrors.ts), and a hung connection burns the client's 60s timeout.

Two signed-in instances, the first answering 503 on operation: 'logout': the second instance's session, the central-manager logout, and the storage wipe all wait ~35s. A user who clicks Sign out and walks away is still fully signed in for that window.

Suggested shape: run the local clears for every entity up front (they already precede each network call), then dispatch the instance logouts with Promise.allSettled and don't make the central-manager logout wait on them — or at least build the logout client without the gateway-retry interceptor.

2. A failed instance logout leaves stored basic-auth credentials on disk

flagForBasicAuth(id, null) and flagForFabricConnect(id, false) run only after a successful POST, inside onInstanceLogoutSubmit (src/integrations/api/instance/auth/onInstanceLogoutSubmit.ts). The sweep's own clears don't touch them — unlike signOutLocally, which does. Normally logoutOnSuccessclearLocalStorage wipes them anyway, so this only bites when the instance logout fails and the central-manager /Logout/ rejects (offline, 401): then Studio:BasicAuth:<id> (base64 username/password) survives a user-requested sign-out until the next successful logout.

Suggested shape: clear the basic-auth entry and the Fabric Connect flag in the sweep's local-clear block, the way signOutLocally already does, so a failed POST cannot leave them behind.

3. An entity re-added during an await is skipped

The loop is a for…in over potentiallyAuthenticated with an await between iterations, and signOutAllLocally snapshots Object.keys first for exactly this reason. A loadUser in flight when the sweep starts captured its key before the clear, and its flagKeyAsSignedIn on resolve re-adds potentiallyAuthenticated[id]; keys added after a for…in starts are not visited, so the sweep never revisits it, and logoutOnSuccess's localStorage.clear() does not touch the in-memory entry. A same-tab re-login then inherits the prior user's connection — the leak signOutAllLocally was written to close. (Deleting the current key mid-loop is spec-safe; the re-add is the defect.)

Suggested shape: iterate a snapshot of the keys, and drop any entry re-added during the sweep at the end.

Notes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    P2

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions