Skip to content

feat: Pexip video call auth credentials for persistent chat#3232

Merged
jeanfbrito merged 7 commits intodevfrom
feature/pexip-auth-credentials
Mar 6, 2026
Merged

feat: Pexip video call auth credentials for persistent chat#3232
jeanfbrito merged 7 commits intodevfrom
feature/pexip-auth-credentials

Conversation

@jeanfbrito
Copy link
Copy Markdown
Member

@jeanfbrito jeanfbrito commented Mar 4, 2026

Summary

  • Automatically capture the logged-in user's userId and authToken (from Meteor localStorage) when a Pexip video call is opened
  • Store credentials in memory in the main process and expose them to the Pexip webview via window.videoCallWindow.getAuthCredentials()
  • Pexip can use these credentials to authenticate an embedded Rocket.Chat iframe for persistent chat
  • Skip JitsiBridge initialization for non-Jitsi providers using synchronous IPC provider check (the preload runs in the webview context, so query params from the BrowserWindow are not accessible)

Changes

  • src/servers/preload/internalVideoChatWindow.ts — Auto-grab Meteor credentials for Pexip provider before opening the video call window
  • src/ipc/channels.ts — Add TypeScript types for credentials in open-window and new get-credentials IPC channel
  • src/videoCallWindow/ipc.ts — Store credentials and provider name in memory, serve via IPC, clear on window close; add sync IPC handler for provider name
  • src/videoCallWindow/preload/index.ts — Expose getAuthCredentials() API via contextBridge
  • src/videoCallWindow/preload/jitsiBridge.ts — Guard JitsiBridge initialization to only run for Jitsi providers
  • docs/pexip-auth-credentials.md — API documentation for the Pexip team

Security

  • Credentials only captured when providerName === 'pexip'
  • Held in memory only — never written to disk
  • Cleared immediately when video call window closes
  • Multi-workspace safe: credentials come from the specific workspace that initiated the call

Test plan

  • Open a Pexip video call, verify window.videoCallWindow.getAuthCredentials() returns { userId, authToken, serverUrl }
  • Verify credentials are null after closing the video call window
  • Open a Jitsi video call, verify JitsiBridge initializes normally and screen sharing works
  • Test with multiple workspaces connected — verify correct credentials per workspace

Summary by CodeRabbit

  • New Features

    • Pexip video call credential support with automatic lifecycle: credentials captured when a call opens, held in memory, cleared on close.
    • New video-call API to fetch auth credentials (userId, authToken, serverUrl) from the active call window.
    • Provider-aware initialization so integrations initialize only when their provider applies.
  • Documentation

    • Added documentation detailing the Pexip authentication credentials flow and integration behavior.

…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.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4312a764-ee98-4541-8b22-cdd253f24fde

📥 Commits

Reviewing files that changed from the base of the PR and between e1f1f0d and 2ac3c19.

📒 Files selected for processing (1)
  • src/videoCallWindow/ipc.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/videoCallWindow/ipc.ts
📜 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)
  • GitHub Check: check (windows-latest)
  • GitHub Check: check (ubuntu-latest)
  • GitHub Check: check (macos-latest)

Walkthrough

Adds Pexip authentication credential capture, memory storage, and IPC retrieval for video call windows; exposes a new preload API window.videoCallWindow.getAuthCredentials() with credentials lifecycle tied to video call window open/close events.

Changes

Cohort / File(s) Summary
Documentation
docs/pexip-auth-credentials.md
New doc describing the Pexip auth credentials flow, the window.videoCallWindow.getAuthCredentials() API, lifecycle, multi-workspace behavior, and response structure.
IPC Channel Definitions
src/ipc/channels.ts
video-call-window/open-window signature extended to accept optional options (including providerName and credentials); new video-call-window/get-credentials channel added to return stored credentials or null.
Main Process: Video Call Window State
src/videoCallWindow/ipc.ts
Introduced videoCallCredentials and videoCallProviderName state; store credentials/provider on open, derive serverUrl from window URL for Pexip, clear on close/destroy; added guarded handler video-call-window/get-credentials and synchronous get-provider-sync.
Preload / Server Enrichment
src/servers/preload/internalVideoChatWindow.ts
Added optional credentials to videoCallWindowOptions; getCredentialsForPexip reads Meteor loginToken/userId from localStorage and enriches options for provider pexip; openInternalVideoChatWindow passes enriched options to IPC open-window.
Preload API & Jitsi Bridge
src/videoCallWindow/preload/index.ts, src/videoCallWindow/preload/jitsiBridge.ts
Exposed getAuthCredentials() in preload returning `{ userId, authToken, serverUrl }

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately describes the main change: adding Pexip video call authentication credentials support for persistent chat integration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between efd1118 and 2c1dad5.

📒 Files selected for processing (6)
  • docs/pexip-auth-credentials.md
  • src/ipc/channels.ts
  • src/servers/preload/internalVideoChatWindow.ts
  • src/videoCallWindow/ipc.ts
  • src/videoCallWindow/preload/index.ts
  • src/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/fuselage for all UI work and only create custom components when Fuselage doesn't provide what's needed
Check Theme.d.ts for 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.ts
  • src/videoCallWindow/ipc.ts
  • src/ipc/channels.ts
  • src/servers/preload/internalVideoChatWindow.ts
  • src/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
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/videoCallWindow/ipc.ts (1)

557-572: ⚠️ Potential issue | 🔴 Critical

Gate credential persistence behind trusted destination validation

Line 557 stores videoCallProviderName/videoCallCredentials before 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

📥 Commits

Reviewing files that changed from the base of the PR and between 2c1dad5 and e1f1f0d.

📒 Files selected for processing (2)
  • docs/pexip-auth-credentials.md
  • src/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/fuselage for all UI work and only create custom components when Fuselage doesn't provide what's needed
Check Theme.d.ts for 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 state

Clearing both videoCallCredentials and videoCallProviderName on window close is the right containment behavior.

docs/pexip-auth-credentials.md (1)

9-59: Documentation looks solid and aligned with the implementation

The API contract, lifecycle, and multi-workspace behavior are clearly documented, and the fenced diagram block now includes a language tag.

@jeanfbrito jeanfbrito merged commit 7393185 into dev Mar 6, 2026
8 of 9 checks passed
@jeanfbrito jeanfbrito deleted the feature/pexip-auth-credentials branch March 6, 2026 16:06
@jeanfbrito jeanfbrito mentioned this pull request Mar 6, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant