Skip to content

bug: OAuth login promise hangs forever if user closes popup without completing login #1274

@deepak0x

Description

@deepak0x

If a user opens the OAuth popup and closes it without finishing login, the promise in loginWithRocketChatOAuth never settles. No resolve, no reject.

The Promise constructor on line 45 only takes resolve. There's no reject. The only path to resolve() is inside the onMessage handler, which fires when the popup posts back an rc-oauth-callback message.

There IS code that detects when the popup closes (the setInterval on line 60). It cleans up the interval and the event listener, which is good. But then it just... stops. Nobody calls resolve() or reject(), so the promise sits there indefinitely:

const checkInterval = setInterval(() => {
  if (popup.closed) {
    clearInterval(checkInterval);
    window.removeEventListener("message", onMessage);
    // nothing here — promise hangs
  }
}, 1000);

What happens in practice:

The caller in ChatInput.js (line 241) does:

try {
  await RCInstance.auth.loginWithRocketChatOAuth();
} catch (e) {
  console.error(e);
  dispatchToastMessage({ type: 'error', message: e.message });
}

Since the promise never rejects, the catch block never runs. The user closes the popup and gets zero feedback — no error toast, no "login cancelled" message, nothing. The onJoin async function just silently stays stuck at the await forever.

Each time the user tries this (click JOIN, popup opens, close popup), another unresolved promise stacks up in memory. They're never garbage collected because the promise internals still hold references to the closure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions