feat: Pexip video call auth credentials for persistent chat#3232
feat: Pexip video call auth credentials for persistent chat#3232jeanfbrito merged 7 commits intodevfrom
Conversation
…iBridge for non-Jitsi providers Auto-grab Meteor auth token and userId from localStorage when opening a Pexip video call, pipe them through IPC to the main process, and proactively postMessage credentials to Rocket.Chat iframes detected inside the Pexip webview via MutationObserver. Credentials are memory-only, provider-gated, and cleared on window close. Additionally, JitsiBridge now checks the provider name via synchronous IPC before initializing, skipping entirely for non-Jitsi providers like Pexip. This prevents false Jitsi URL detection, failed external_api.js loads, and CORS errors that were occurring on Pexip calls.
…l preload Pexip handles its own iframe — it just needs credentials available via the API. Removed MutationObserver, postMessage injection, and all iframe detection logic. Credentials are now only exposed through window.videoCallWindow.getAuthCredentials().
Remove internal implementation details (Jitsi, IPC, Electron architecture) and focus on the API surface that the Pexip team needs to integrate.
Keep only the API reference — Pexip team can refer to RC server docs for iframe authentication methods.
|
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 as they are similar to previous changes (1)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
WalkthroughAdds Pexip authentication credential capture, memory storage, and IPC retrieval for video call windows; exposes a new preload API Changes
Sequence DiagramsequenceDiagram
participant User
participant Desktop as Desktop App (Main)
participant Preload as Preload Script
participant VideoWin as Video Call Window (Webview)
participant RCIframe as RC Iframe
User->>Desktop: Request open Pexip call
Desktop->>Preload: getCredentialsForPexip(options)
Preload->>Preload: Read localStorage (loginToken, userId)
Preload-->>Desktop: Return options (with credentials)
Desktop->>VideoWin: IPC open-window(url, options with credentials)
activate VideoWin
VideoWin->>Desktop: invoke('video-call-window/get-credentials')
Desktop-->>VideoWin: { userId, authToken, serverUrl } | null
VideoWin->>RCIframe: Use credentials to authenticate RC iframe
deactivate VideoWin
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 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: 3
🧹 Nitpick comments (1)
src/ipc/channels.ts (1)
27-33: Extract shared credential IPC types to prevent type drift.The same credential shapes are duplicated across multiple files. Consider exporting shared types from this module and reusing them in preload/main to keep contracts in sync.
♻️ Suggested refactor
+export type VideoCallAuthCredentials = { + userId: string; + authToken: string; +}; + +export type VideoCallAuthCredentialsResponse = VideoCallAuthCredentials & { + serverUrl: string; +}; + +export type VideoCallWindowOpenOptions = { + providerName?: string; + credentials?: VideoCallAuthCredentials; +}; 'video-call-window/open-window': ( url: string, - options?: { - providerName?: string; - credentials?: { userId: string; authToken: string }; - } + options?: VideoCallWindowOpenOptions ) => void; 'video-call-window/get-credentials': () => { - userId: string; - authToken: string; - serverUrl: string; - } | null; + VideoCallAuthCredentialsResponse | null;Also applies to: 54-58
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ipc/channels.ts` around lines 27 - 33, The IPC channel type for 'video-call-window/open-window' duplicates credential shapes; extract a shared exported type (e.g., VideoCallCredentials or VideoCallOptions and a Credentials interface) from the module that currently declares the channel types and replace the inline shapes with those exported types, then import and reuse them in preload/main and any other places (also update the similar declarations around the other channel at lines 54-58) so all IPC contracts reference the single shared exported credential/type definitions to avoid drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/pexip-auth-credentials.md`:
- Around line 9-22: The fenced ASCII diagram block is missing a language tag,
causing markdownlint MD040; update the opening fence for the ASCII diagram (the
fenced code block containing the box/diagram) to include a language tag (for
example change ``` to ```text or ```nohighlight) so the diagram is treated as
plain text and the linter warning is resolved.
In `@src/videoCallWindow/ipc.ts`:
- Around line 557-569: Currently videoCallProviderName/videoCallCredentials are
set from renderer input before verifying the window destination, and new
URL(_wc.getURL()) is unguarded and may throw; change the flow so you first
verify the destination is trusted (using the existing destination-trust check
used elsewhere) before persisting any Pexip credentials for providerName ===
'pexip', and only then attempt to parse the WebContents URL inside a try/catch
to extract origin; if the destination is untrusted do not set
videoCallCredentials (keep null) and do not expose them via
getAuthCredentials(). Ensure the same fix is applied to the analogous block
around lines 604-620.
- Around line 1264-1266: The IPC handler video-call-window/get-credentials
currently returns videoCallCredentials to any caller; change the handler (the
handle function) to accept the IPC event parameter and verify the caller by
comparing event.sender (or event.senderFrame/webContents.id) against
videoCallWindow.webContents (or its hosted webview) before returning
credentials; if the sender does not match videoCallWindow.webContents, return
null or throw an authorization error instead of exposing videoCallCredentials.
Ensure you reference the existing symbols videoCallWindow.webContents and
videoCallCredentials when adding this access-control check.
---
Nitpick comments:
In `@src/ipc/channels.ts`:
- Around line 27-33: The IPC channel type for 'video-call-window/open-window'
duplicates credential shapes; extract a shared exported type (e.g.,
VideoCallCredentials or VideoCallOptions and a Credentials interface) from the
module that currently declares the channel types and replace the inline shapes
with those exported types, then import and reuse them in preload/main and any
other places (also update the similar declarations around the other channel at
lines 54-58) so all IPC contracts reference the single shared exported
credential/type definitions to avoid drift.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 03a4daa0-4685-445d-9f71-7039242e4fe7
📒 Files selected for processing (6)
docs/pexip-auth-credentials.mdsrc/ipc/channels.tssrc/servers/preload/internalVideoChatWindow.tssrc/videoCallWindow/ipc.tssrc/videoCallWindow/preload/index.tssrc/videoCallWindow/preload/jitsiBridge.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: check (windows-latest)
- GitHub Check: check (ubuntu-latest)
- GitHub Check: check (macos-latest)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript strict mode enabled in TypeScript configuration
Use React functional components with hooks instead of class components
Follow FSA (Flux Standard Action) pattern for Redux actions
Use camelCase for file names and PascalCase for component file names
All code must pass ESLint and TypeScript checks
Write self-documenting code with clear naming; avoid unnecessary comments except for complex business logic or non-obvious decisions
Use Fuselage components from@rocket.chat/fuselagefor all UI work and only create custom components when Fuselage doesn't provide what's needed
CheckTheme.d.tsfor valid color tokens when using Fuselage components
Use defensive coding with optional chaining and fallbacks for Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) to ensure cross-platform compatibility across Windows, macOS, and Linux
Files:
src/videoCallWindow/preload/index.tssrc/videoCallWindow/ipc.tssrc/ipc/channels.tssrc/servers/preload/internalVideoChatWindow.tssrc/videoCallWindow/preload/jitsiBridge.ts
🪛 LanguageTool
docs/pexip-auth-credentials.md
[style] ~56-~56: For conciseness, consider replacing this expression with an adverb.
Context: ...# Lifecycle - Credentials are captured at the moment the Pexip call is opened - They are hel...
(AT_THE_MOMENT)
🪛 markdownlint-cli2 (0.21.0)
docs/pexip-auth-credentials.md
[warning] 9-9: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (3)
src/videoCallWindow/preload/index.ts (1)
19-25: LGTM: preload API contract is clear and consistent.
getAuthCredentials()cleanly exposes the new IPC contract with an explicit nullable credential shape.src/servers/preload/internalVideoChatWindow.ts (1)
19-36: LGTM: provider-gated option enrichment is implemented cleanly.Credentials are only added for
pexip, and the enriched options are consistently passed through the IPC call path.Also applies to: 48-67
src/videoCallWindow/preload/jitsiBridge.ts (1)
541-562: LGTM: provider-gated Jitsi bridge initialization matches intent.Skipping bridge setup for non-Jitsi providers is correctly guarded while preserving fallback behavior.
- Wrap URL parsing of _wc.getURL() in try/catch to prevent unhandled throw - Scope get-credentials IPC handler to only respond to the video call window's webview, rejecting requests from other renderers - Add language tag to docs fenced code block
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/videoCallWindow/ipc.ts (1)
557-572:⚠️ Potential issue | 🔴 CriticalGate credential persistence behind trusted destination validation
Line 557 stores
videoCallProviderName/videoCallCredentialsbefore destination validation at Line 607. This still allows sensitive credentials to be bound prior to trust checks. Persist credentials only after validating a trusted Pexip destination.🔐 Suggested hardening
- // Store provider name and credentials - videoCallProviderName = options?.providerName ?? null; - videoCallCredentials = null; - if (options?.providerName === 'pexip' && options?.credentials) { - try { - const serverOrigin = new URL(_wc.getURL()).origin; - videoCallCredentials = { - userId: options.credentials.userId, - authToken: options.credentials.authToken, - serverUrl: serverOrigin, - }; - } catch { - // _wc.getURL() may not be a valid URL in edge cases - videoCallCredentials = null; - } - } + // Initialize as empty; assign only after destination validation + videoCallProviderName = null; + videoCallCredentials = null; ... const validUrl = new URL(url); const allowedProtocols = ['http:', 'https:']; ... if (allowedProtocols.includes(validUrl.protocol)) { + videoCallProviderName = options?.providerName ?? null; + + const isTrustedPexipDestination = + videoCallProviderName === 'pexip' && + validUrl.protocol === 'https:' && + /* apply existing trusted-origin check here */; + + if (isTrustedPexipDestination && options?.credentials) { + try { + const serverOrigin = new URL(_wc.getURL()).origin; + videoCallCredentials = { + userId: options.credentials.userId, + authToken: options.credentials.authToken, + serverUrl: serverOrigin, + }; + } catch { + videoCallCredentials = null; + } + }Also applies to: 607-623
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/videoCallWindow/ipc.ts` around lines 557 - 572, Do not assign videoCallProviderName or videoCallCredentials until after the trusted-Pexip-destination check succeeds: remove the early assignments (the block that sets videoCallProviderName = options?.providerName ?? null and computes videoCallCredentials from _wc.getURL() when options?.providerName === 'pexip') and instead set videoCallProviderName and compute videoCallCredentials only after the existing destination validation logic completes and confirms the destination is trusted; preserve the try/catch around new URL(_wc.getURL()) and ensure credentials are cleared (set to null) when validation fails or URL parsing throws.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/videoCallWindow/ipc.ts`:
- Around line 1273-1274: The wrapped equality comparison across lines with
callerWebContents.hostWebContents?.id === videoCallWindow.webContents.id is
causing Prettier/ESLint failures; collapse this into a single-line expression
(no manual line break) where the comparison occurs (look for the expression
referencing callerWebContents.hostWebContents?.id and
videoCallWindow.webContents.id in ipc.ts) to match Prettier formatting rules and
restore CI parity.
---
Duplicate comments:
In `@src/videoCallWindow/ipc.ts`:
- Around line 557-572: Do not assign videoCallProviderName or
videoCallCredentials until after the trusted-Pexip-destination check succeeds:
remove the early assignments (the block that sets videoCallProviderName =
options?.providerName ?? null and computes videoCallCredentials from
_wc.getURL() when options?.providerName === 'pexip') and instead set
videoCallProviderName and compute videoCallCredentials only after the existing
destination validation logic completes and confirms the destination is trusted;
preserve the try/catch around new URL(_wc.getURL()) and ensure credentials are
cleared (set to null) when validation fails or URL parsing throws.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 530f2f05-f0eb-4e59-9e29-f24866cabf83
📒 Files selected for processing (2)
docs/pexip-auth-credentials.mdsrc/videoCallWindow/ipc.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: check (macos-latest)
- GitHub Check: check (windows-latest)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript strict mode enabled in TypeScript configuration
Use React functional components with hooks instead of class components
Follow FSA (Flux Standard Action) pattern for Redux actions
Use camelCase for file names and PascalCase for component file names
All code must pass ESLint and TypeScript checks
Write self-documenting code with clear naming; avoid unnecessary comments except for complex business logic or non-obvious decisions
Use Fuselage components from@rocket.chat/fuselagefor all UI work and only create custom components when Fuselage doesn't provide what's needed
CheckTheme.d.tsfor valid color tokens when using Fuselage components
Use defensive coding with optional chaining and fallbacks for Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) to ensure cross-platform compatibility across Windows, macOS, and Linux
Files:
src/videoCallWindow/ipc.ts
🪛 ESLint
src/videoCallWindow/ipc.ts
[error] 1273-1274: Delete ⏎·······
(prettier/prettier)
🪛 GitHub Check: check (ubuntu-latest)
src/videoCallWindow/ipc.ts
[failure] 1273-1273:
Delete ⏎·······
🪛 LanguageTool
docs/pexip-auth-credentials.md
[style] ~56-~56: For conciseness, consider replacing this expression with an adverb.
Context: ...# Lifecycle - Credentials are captured at the moment the Pexip call is opened - They are hel...
(AT_THE_MOMENT)
🔇 Additional comments (2)
src/videoCallWindow/ipc.ts (1)
762-765: Good lifecycle cleanup for sensitive stateClearing both
videoCallCredentialsandvideoCallProviderNameon window close is the right containment behavior.docs/pexip-auth-credentials.md (1)
9-59: Documentation looks solid and aligned with the implementationThe API contract, lifecycle, and multi-workspace behavior are clearly documented, and the fenced diagram block now includes a language tag.
Summary
userIdandauthToken(from Meteor localStorage) when a Pexip video call is openedwindow.videoCallWindow.getAuthCredentials()Changes
src/servers/preload/internalVideoChatWindow.ts— Auto-grab Meteor credentials for Pexip provider before opening the video call windowsrc/ipc/channels.ts— Add TypeScript types for credentials inopen-windowand newget-credentialsIPC channelsrc/videoCallWindow/ipc.ts— Store credentials and provider name in memory, serve via IPC, clear on window close; add sync IPC handler for provider namesrc/videoCallWindow/preload/index.ts— ExposegetAuthCredentials()API via contextBridgesrc/videoCallWindow/preload/jitsiBridge.ts— Guard JitsiBridge initialization to only run for Jitsi providersdocs/pexip-auth-credentials.md— API documentation for the Pexip teamSecurity
providerName === 'pexip'Test plan
window.videoCallWindow.getAuthCredentials()returns{ userId, authToken, serverUrl }nullafter closing the video call windowSummary by CodeRabbit
New Features
Documentation