From 3d64200e79bd88c071317907a627f2a0b1d2b729 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Fri, 28 Nov 2025 00:38:27 +0100 Subject: [PATCH] Small fix for oauth redirect on pwa --- .../helpers/resources/oauth_callback.html | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/music_assistant/helpers/resources/oauth_callback.html b/music_assistant/helpers/resources/oauth_callback.html index 1bd898d4..0b6f5c5e 100644 --- a/music_assistant/helpers/resources/oauth_callback.html +++ b/music_assistant/helpers/resources/oauth_callback.html @@ -135,6 +135,15 @@ const redirectUrl = '{REDIRECT_URL}'; const requiresConsent = {REQUIRES_CONSENT}; + // Detect if running in PWA/standalone mode + // iOS Safari sets window.navigator.standalone + // Other browsers support display-mode media query + const isPWA = (window.navigator.standalone === true) || + window.matchMedia('(display-mode: standalone)').matches || + window.matchMedia('(display-mode: minimal-ui)').matches; + + console.log('OAuth callback - isPWA:', isPWA, 'opener:', window.opener !== null); + // Validate URL to prevent XSS attacks // Note: Server-side validation is the primary security layer function isValidRedirectUrl(url) { @@ -152,6 +161,29 @@ function performRedirect() { const isPopup = window.opener !== null; + // PWA mode: Always use direct redirect since popups don't work properly + // The OAuth flow on iOS PWAs opens in Safari, then redirects back to PWA + // This means window.opener is always null and localStorage is not shared + if (isPWA) { + statusEl.textContent = 'Login Complete!'; + messageEl.textContent = 'Returning to app...'; + + // Don't store token in localStorage here - it's already in the redirect URL + // The frontend will extract it from the URL query parameter + // PWAs on iOS may not share localStorage between Safari and the PWA context + + console.log('PWA mode - redirecting to:', redirectUrl); + + // Navigate to redirect URL (token is already in URL as query param 'code') + if (isValidRedirectUrl(redirectUrl)) { + window.location.href = redirectUrl; + } else { + console.warn('Invalid redirect URL, using fallback:', redirectUrl); + window.location.href = '/'; + } + return; + } + if (isPopup) { // Popup mode - send token to parent and close statusEl.textContent = 'Login Complete!'; -- 2.34.1