fix: session not being marked as logged out when logging out via REST /v1/logout

Merged
RO
3mo ago
+58-3

Proposed changes

When a user logs out via POST /v1/logout, the login token is removed from the user document but the session in the Sessions collection is never marked as logged out. The cleanup relies on an indirect chain (watch.users → in-memory callbacks → Accounts.onLogout → SAUMonitor → Sessions.logoutBySessionIdAndUserId) that breaks when the client closes its WebSocket upon receiving the logout response, the callbacks are destroyed before the broadcast arrives.

This adds a direct Sessions.logoutBySessionIdAndUserId() call in the logout handler, awaited before the response, so the session is always marked with logoutAt regardless of the WebSocket race.

Issue(s)

https://rocketchat.atlassian.net/browse/NATIVE-978

Steps to test or reproduce

  1. Log in on an Android/iOS client
  2. Verify the device appears in Device Manager
  3. Log out from the client
  4. Log back in
  5. Check Device Manager, should show only one active session not two

Further comments

The root cause is a race condition: POST /v1/logout broadcasts watch.users as fire-and-forget (void), but the mobile client closes its WebSocket on receiving the 200 response, removing the in-memory observer callbacks before the broadcast arrives. The SAUMonitor never receives the logout event, so logoutAt is never set on the session document. The direct Sessions.logoutBySessionIdAndUserId() call eliminates the dependency on this chain entirely.

Summary by CodeRabbit

  • Bug Fixes
    • Improved logout handling so POST /v1/logout explicitly marks the user’s session as logged out, preventing stale/orphaned sessions from persisting in Device Manager.
    • Reduced inconsistent session state by avoiding indirect, timing-sensitive cleanup during logout.
  • Tests
    • Added end-to-end coverage for POST /api/v1/logout to confirm session invalidation, logoutAt/logoutBy updates on the session record, and correct 401 responses for unauthenticated requests.