Repository navigation
Conversation
EmbeddedChatApi.logout() only cleared the auth token via auth.logout(). The DDP connection and its active subscriptions were left running, so the client kept receiving live messages and events for a session that was no longer authenticated. logout() now tears the connection down via the existing close() method. The teardown runs in a finally block so the socket is also closed when the logout request itself fails, and close() errors are logged rather than propagated so they cannot mask the logout result. Fixes RocketChat#1158
| // keeps receiving messages for a session that is no longer | ||
| // authenticated. | ||
| try { | ||
| await this.close(); |
There was a problem hiding this comment.
this does not cancel an in-flight _doConnect(). If logout happens while connect() is awaiting joinRoom(), _doConnect() can resume afterward and add new stream subscriptions. The DDP client retains and replays those on the next connection.
Please cancel/invalidate pending connects
|
Thanks for picking this up :) |
close() now invalidates a connect() which is still awaiting, so that subscriptions are not registered after the socket has been torn down. Previously, if logout happened while _doConnect() was awaiting joinRoom() (or the connection/login steps), the connect would resume afterwards and register the stream subscriptions on the closed connection, which the DDP client replays on the next connection. Addresses review feedback on RocketChat#1394.
|
Thanks for the review @Aryan-Verma-999 — you're right, and the window was wider than just
Fixed in
I also pulled the teardown out into Verification
Before: After: I ran the harness against the previous commit first to confirm it actually reproduces the bug rather than passing vacuously. Also run: One thing still outside this PR's reach: CI hasn't run on any of my PRs yet — the workflow runs are sitting at |
…ocketChat#1158) (#4) * fix: close realtime connection on logout to prevent ghost sessions EmbeddedChatApi.logout() only cleared the auth token via auth.logout(). The DDP connection and its active subscriptions were left running, so the client kept receiving live messages and events for a session that was no longer authenticated. logout() now tears the connection down via the existing close() method. The teardown runs in a finally block so the socket is also closed when the logout request itself fails, and close() errors are logged rather than propagated so they cannot mask the logout result. Fixes RocketChat#1158 * [DOCS] Align Node.js requirement in docs README with package.json engines * feat: keep emoji picker open for multiple selections * chore: format code * fix: cancel in-flight connect on logout to prevent ghost subscriptions close() now invalidates a connect() which is still awaiting, so that subscriptions are not registered after the socket has been torn down. Previously, if logout happened while _doConnect() was awaiting joinRoom() (or the connection/login steps), the connect would resume afterwards and register the stream subscriptions on the closed connection, which the DDP client replays on the next connection. Addresses review feedback on RocketChat#1394. --------- Co-authored-by: swarnendusahu10-dotcom <swarnendusahu10@gmail.com> Co-authored-by: Aryan Verma <121835781+Aryan-Verma-999@users.noreply.github.com> Co-authored-by: iRahul360 <rahulburman669@gmail.com>
Fixes #1158
Problem
EmbeddedChatApi.logout()only awaitedthis.auth.logout(), which clears the auth token. The DDP connection and its_activeSubscriptionswere left running, so after a "logout" the client kept receiving live messages and events for a session that was no longer authenticated — a privacy leak, and inconsistent state if another user logged in without a full page refresh.The class already has a
close()method that stops_activeSubscriptionsand callssdk.connection.close().logout()simply never called it.Fix
logout()now tears the connection down via the existingclose(), with two deliberate details:finallyblock, so the socket is also closed when the logout request itself fails (a failed logout previously left a fully live session behind);close()errors are logged rather than propagated, so they cannot mask the logout result. Other call sites already treatclose()as rejectable (EmbeddedChat.jswraps it in.catch()).Verification
packages/apihas no test runner ("test": "echo \"Error: no test specified\""), so I verified behaviourally with a harness that bundles the realEmbeddedChatApi.ts(deps stubbed) and asserts the teardown contract. It is reproducible and included below.Run against this branch — all pass:
Run against unpatched
develop— the same harness fails, confirming it genuinely exercises the bug:Also run:
tsc --noEmitonpackages/api(clean),prettier --check(clean),yarn lint(0 errors; warning count unchanged fromdevelop), andyarn workspace @embeddedchat/api build(succeeds).If you'd prefer this as a committed test, I'm happy to add a runner to
packages/apiin a follow-up — I kept it out of this PR to hold the diff to the one-file fix.Prior art
@Aryan-Verma-999's earlier #1171 identified the same root cause and was closed unmerged. This PR keeps that insight and adds the
finallyhandling so a failed logout cannot leave a live socket behind.