From 440b69138ec1693ef78b201663384e0deaf1f651 Mon Sep 17 00:00:00 2001 From: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Date: Fri, 12 Dec 2025 16:05:33 +0100 Subject: [PATCH] treat web version as extension (#25834) Co-authored-by: CarinaWolli --- companion/services/oauthService.ts | 70 ++++++------------------------ 1 file changed, 14 insertions(+), 56 deletions(-) diff --git a/companion/services/oauthService.ts b/companion/services/oauthService.ts index 93669af44e..c99bdb023c 100644 --- a/companion/services/oauthService.ts +++ b/companion/services/oauthService.ts @@ -144,38 +144,9 @@ export class CalComOAuthService { } } - // Detect browser extension environment using reliable indicators - private isBrowserExtension(): boolean { - if (Platform.OS !== "web" || typeof window === "undefined") { - return false; - } - - if (typeof chrome !== "undefined" && chrome.runtime?.id) { - return true; - } - - if (window.location.protocol === "chrome-extension:") { - return true; - } - - // Extension content script injects companion app as iframe - if (window.parent !== window) { - try { - const parentOrigin = window.parent.location.origin; - const currentOrigin = window.location.origin; - - if (parentOrigin !== currentOrigin && window.location.hostname === "localhost") { - return true; - } - } catch { - // Cross-origin access blocked - expected for extension iframes - if (window.location.hostname === "localhost") { - return true; - } - } - } - - return false; + // Detect if this is a mobile app (not web/extension) + private isMobileApp(): boolean { + return Platform.OS !== "web"; } private async launchExtensionAuthFlow(authUrl: string): Promise { @@ -251,9 +222,17 @@ export class CalComOAuthService { ): Promise }> { const authUrl = this.buildAuthorizationUrl(codeChallenge, state); - const isExtension = this.isBrowserExtension(); + if (this.isMobileApp()) { + const result = await WebBrowser.openAuthSessionAsync(authUrl, this.config.redirectUri); - if (isExtension) { + if (result.type === "success") { + const params = this.parseCallbackUrl(result.url); + return { type: "success" as const, params }; + } + + return { type: result.type, params: {} } as { type: string; params: Record }; + } else { + // Treat everything else as browser extension try { const responseUrl = await this.launchExtensionAuthFlow(authUrl); const params = this.parseCallbackUrl(responseUrl); @@ -265,27 +244,6 @@ export class CalComOAuthService { params: Record; }; } - } else if (Platform.OS === "web") { - const discovery = await this.getDiscoveryEndpoints(); - const request = new AuthSession.AuthRequest({ - clientId: this.config.clientId, - redirectUri: this.config.redirectUri, - responseType: AuthSession.ResponseType.Code, - state: state, - codeChallenge: codeChallenge, - codeChallengeMethod: AuthSession.CodeChallengeMethod.S256, - }); - - return await request.promptAsync(discovery); - } else { - const result = await WebBrowser.openAuthSessionAsync(authUrl, this.config.redirectUri); - - if (result.type === "success") { - const params = this.parseCallbackUrl(result.url); - return { type: "success" as const, params }; - } - - return { type: result.type, params: {} } as { type: string; params: Record }; } } @@ -348,7 +306,7 @@ export class CalComOAuthService { } // Extension: use APIs to avoid CORS - if (this.isBrowserExtension() && window.parent !== window) { + if (!this.isMobileApp() && typeof window !== "undefined" && window.parent !== window) { return await this.exchangeTokensViaExtension(code, state); }