From 1afa944fa02cacd02f0df96b9ab0d40f914ff9f7 Mon Sep 17 00:00:00 2001 From: Ramon Candel Segura Date: Mon, 9 Feb 2026 18:02:10 +0100 Subject: [PATCH] Allow new meet cloudflare preview domain for oauth sign in --- src/services/oauth.service.test.ts | 100 +++++++++++++++++++++++++++++ src/services/oauth.service.ts | 4 +- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/src/services/oauth.service.test.ts b/src/services/oauth.service.test.ts index 2f79e9be3a..b5446b6dfd 100644 --- a/src/services/oauth.service.test.ts +++ b/src/services/oauth.service.test.ts @@ -254,6 +254,106 @@ describe('OAuth authentication service', () => { expect(httpOpener.postMessage).not.toHaveBeenCalled(); }); + it('when parent window matches Cloudflare Workers preview pattern, then transmission is allowed', () => { + const workersPreviewOpener = { + postMessage: vi.fn(), + location: { + origin: 'https://0930e143-meet-web.storageinternxt.workers.dev', + }, + }; + + Object.defineProperty(window, 'opener', { + value: workersPreviewOpener, + writable: true, + configurable: true, + }); + + const result = oauthService.sendAuthSuccess(mockUserSettings, mockNewToken); + + expect(result).toBe(true); + expect(workersPreviewOpener.postMessage).toHaveBeenCalledWith( + { + type: OAuthMessageType.SUCCESS, + payload: { + mnemonic: btoa(mockUserSettings.mnemonic), + newToken: btoa(mockNewToken), + }, + }, + 'https://0930e143-meet-web.storageinternxt.workers.dev', + ); + }); + + it('when referrer matches Cloudflare Workers preview pattern, then transmission is allowed', () => { + const crossOriginOpener = { + postMessage: vi.fn(), + get location() { + throw new Error('Cross-origin access denied'); + }, + }; + + Object.defineProperty(document, 'referrer', { + value: 'https://abc12345-meet-web.storageinternxt.workers.dev/login', + writable: true, + configurable: true, + }); + + Object.defineProperty(window, 'opener', { + value: crossOriginOpener, + writable: true, + configurable: true, + }); + + const result = oauthService.sendAuthSuccess(mockUserSettings, mockNewToken); + + expect(result).toBe(true); + expect(crossOriginOpener.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ + type: OAuthMessageType.SUCCESS, + }), + 'https://abc12345-meet-web.storageinternxt.workers.dev', + ); + }); + + it('when parent window uses HTTP on Workers preview, then transmission is blocked', () => { + const httpWorkersOpener = { + postMessage: vi.fn(), + location: { + origin: 'http://0930e143-meet-web.storageinternxt.workers.dev', + }, + }; + + Object.defineProperty(window, 'opener', { + value: httpWorkersOpener, + writable: true, + configurable: true, + }); + + const result = oauthService.sendAuthSuccess(mockUserSettings, mockNewToken); + + expect(result).toBe(false); + expect(httpWorkersOpener.postMessage).not.toHaveBeenCalled(); + }); + + it('when parent window is a non-meet Workers preview, then transmission is blocked', () => { + const otherWorkersOpener = { + postMessage: vi.fn(), + location: { + origin: 'https://0930e143-other-app.storageinternxt.workers.dev', + }, + }; + + Object.defineProperty(window, 'opener', { + value: otherWorkersOpener, + writable: true, + configurable: true, + }); + + const result = oauthService.sendAuthSuccess(mockUserSettings, mockNewToken); + + expect(result).toBe(false); + expect(otherWorkersOpener.postMessage).not.toHaveBeenCalled(); + }); + it('when parent window does not match allowed domain patterns, then transmission is blocked', () => { const disallowedPatternOpener = { postMessage: vi.fn(), diff --git a/src/services/oauth.service.ts b/src/services/oauth.service.ts index d0558a331b..aba685d316 100644 --- a/src/services/oauth.service.ts +++ b/src/services/oauth.service.ts @@ -25,7 +25,9 @@ const isAllowedOrigin = (origin: string): boolean => { const url = new URL(origin); if ( url.protocol === 'https:' && - (url.hostname === 'meet-web.pages.dev' || url.hostname.endsWith('.meet-web.pages.dev')) + (url.hostname === 'meet-web.pages.dev' || + url.hostname.endsWith('.meet-web.pages.dev') || + url.hostname.endsWith('-meet-web.storageinternxt.workers.dev')) ) { return true; }