fix: add timeout to CAS popup login to prevent infinite hang#40161
fix: add timeout to CAS popup login to prevent infinite hang#40161Kgupta62 wants to merge 2 commits into
Conversation
|
Looks like this PR is not ready to merge, because of the following issues:
Please fix the issues and try again If you have any trouble, please check the PR guidelines |
🦋 Changeset detectedLatest commit: dbe6ed9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 41 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
WalkthroughAdded a 120s timeout to the CAS popup login flow: Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client (main window)
participant Popup as Popup (CAS window)
participant CAS as CAS Server
Client->>Popup: open popup to CAS auth URL
Popup->>CAS: request / authenticate user
CAS-->>Popup: redirect to callback page
Note right of Popup: callback may or may not auto-close
alt Popup closes within 120s
Popup-->>Client: (window.closed detected)
Client->>Client: resolve login flow
else Popup doesn't close within 120s
Client->>Client: timeout elapsed
Client->>Popup: try to close() (try/catch)
Client->>Client: reject promise with timeout error
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/meteor/client/lib/openCASLoginPopup.ts`:
- Line 60: Remove the inline comment inside the catch block in
apps/meteor/client/lib/openCASLoginPopup.ts (the catch handling around the
popup/window check in function openCASLoginPopup), i.e., delete the comment text
"// popup may already be closed or cross-origin" so the catch block contains no
implementation comment and matches repository style; leave the catch body empty
or add a minimal TODO or proper error handling if required by project policy.
- Around line 46-67: The polling interval and timeout are not cleared in both
completion paths; update the logic in openCASLoginPopup (the pollClosed Promise
and timeout Promise using checkPopupOpen interval and the setTimeout with
CAS_POPUP_TIMEOUT_MS) so that when either path completes you clear the other
timer: store the interval id (checkPopupOpen) and timeout id, call
clearInterval(checkPopupOpen) and clearTimeout(timeoutId) inside the pollClosed
resolve branch and likewise clearInterval/checkPopupOpen before rejecting in the
timeout branch (ensure popup.close() remains wrapped in try/catch).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7719af75-046c-4d40-add0-14ce44381d94
📒 Files selected for processing (1)
apps/meteor/client/lib/openCASLoginPopup.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation
Files:
apps/meteor/client/lib/openCASLoginPopup.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `page.waitFor()` with specific conditions instead of hardcoded timeouts in Playwright tests
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `page.waitFor()` with specific conditions instead of hardcoded timeouts in Playwright tests
Applied to files:
apps/meteor/client/lib/openCASLoginPopup.ts
📚 Learning: 2026-02-10T16:32:42.586Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38528
File: apps/meteor/client/startup/roles.ts:14-14
Timestamp: 2026-02-10T16:32:42.586Z
Learning: In Rocket.Chat's Meteor client code, DDP streams use EJSON and Date fields arrive as Date objects; do not manually construct new Date() in stream handlers (for example, in sdk.stream()). Only REST API responses return plain JSON where dates are strings, so implement explicit conversion there if needed. Apply this guidance to all TypeScript files under apps/meteor/client to ensure consistent date handling in DDP streams and REST responses.
Applied to files:
apps/meteor/client/lib/openCASLoginPopup.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.
Applied to files:
apps/meteor/client/lib/openCASLoginPopup.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.
Applied to files:
apps/meteor/client/lib/openCASLoginPopup.ts
🔇 Additional comments (1)
apps/meteor/client/lib/openCASLoginPopup.ts (1)
43-44: Nice extraction of popup timeout constant.Good call centralizing the timeout value; this keeps the flow readable and easier to adjust later.
| const pollClosed = new Promise<void>((resolve) => { | ||
| const checkPopupOpen = setInterval(() => { | ||
| if (popup.closed || popup.closed === undefined) { | ||
| clearInterval(checkPopupOpen); | ||
| resolve(); | ||
| } | ||
| }, 100); | ||
| }); | ||
|
|
||
| const timeout = new Promise<never>((_, reject) => { | ||
| setTimeout(() => { | ||
| try { | ||
| popup.close(); | ||
| } catch { | ||
| // popup may already be closed or cross-origin | ||
| } | ||
| reject(new Error('CAS login timed out. Please try again.')); | ||
| }, CAS_POPUP_TIMEOUT_MS); | ||
| }); | ||
|
|
||
| return Promise.race([pollClosed, timeout]); | ||
| }; |
There was a problem hiding this comment.
Clear timer handles on both completion paths.
On Line 46 and Line 55, interval/timeout are created independently but never jointly cleaned up. If the timeout path hits Line 57 and popup.close() fails, polling may continue forever; if polling wins first, the timeout still executes later.
Proposed fix
const waitForPopupClose = (popup: Window) => {
- const pollClosed = new Promise<void>((resolve) => {
- const checkPopupOpen = setInterval(() => {
- if (popup.closed || popup.closed === undefined) {
- clearInterval(checkPopupOpen);
- resolve();
- }
- }, 100);
- });
-
- const timeout = new Promise<never>((_, reject) => {
- setTimeout(() => {
- try {
- popup.close();
- } catch {
- // popup may already be closed or cross-origin
- }
- reject(new Error('CAS login timed out. Please try again.'));
- }, CAS_POPUP_TIMEOUT_MS);
- });
-
- return Promise.race([pollClosed, timeout]);
+ return new Promise<void>((resolve, reject) => {
+ const checkPopupOpen = window.setInterval(() => {
+ if (popup.closed || popup.closed === undefined) {
+ cleanup();
+ resolve();
+ }
+ }, 100);
+
+ const timeoutId = window.setTimeout(() => {
+ cleanup();
+ try {
+ popup.close();
+ } catch {}
+ reject(new Error('CAS login timed out. Please try again.'));
+ }, CAS_POPUP_TIMEOUT_MS);
+
+ const cleanup = (): void => {
+ window.clearInterval(checkPopupOpen);
+ window.clearTimeout(timeoutId);
+ };
+ });
};🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/meteor/client/lib/openCASLoginPopup.ts` around lines 46 - 67, The
polling interval and timeout are not cleared in both completion paths; update
the logic in openCASLoginPopup (the pollClosed Promise and timeout Promise using
checkPopupOpen interval and the setTimeout with CAS_POPUP_TIMEOUT_MS) so that
when either path completes you clear the other timer: store the interval id
(checkPopupOpen) and timeout id, call clearInterval(checkPopupOpen) and
clearTimeout(timeoutId) inside the pollClosed resolve branch and likewise
clearInterval/checkPopupOpen before rejecting in the timeout branch (ensure
popup.close() remains wrapped in try/catch).
| try { | ||
| popup.close(); | ||
| } catch { | ||
| // popup may already be closed or cross-origin |
There was a problem hiding this comment.
Remove inline catch comment to match repository style.
Line 60 adds an implementation comment in production code; this should be removed to follow project conventions.
As per coding guidelines "Avoid code comments in the implementation".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/meteor/client/lib/openCASLoginPopup.ts` at line 60, Remove the inline
comment inside the catch block in apps/meteor/client/lib/openCASLoginPopup.ts
(the catch handling around the popup/window check in function
openCASLoginPopup), i.e., delete the comment text "// popup may already be
closed or cross-origin" so the catch block contains no implementation comment
and matches repository style; leave the catch body empty or add a minimal TODO
or proper error handling if required by project policy.
Summary
Closes #40153
openCASLoginPopup()pollspopup.closedevery 100ms with no timeout, causing the login flow to hang indefinitely if the popup never closesPromise.race()that rejects with a user-friendly error message and attempts to close the stale popupChanges
apps/meteor/client/lib/openCASLoginPopup.ts: Wrapped the polling promise inPromise.race()alongside a 120-second timeout promise that rejects with"CAS login timed out. Please try again."Test plan
Note
This PR was authored with assistance from an AI coding tool (Claude Code by Anthropic).
Summary by CodeRabbit