diff --git a/electron/main.cjs b/electron/main.cjs index cefd8194..2b0765e6 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -72,12 +72,21 @@ function createWindow() { mainWindow.setMenuBarVisibility(false); } - mainWindow.webContents.setUserAgent( - `Termix-Desktop/${appVersion} (${platform}; Electron/${electronVersion})`, + const customUserAgent = `Termix-Desktop/${appVersion} (${platform}; Electron/${electronVersion})`; + mainWindow.webContents.setUserAgent(customUserAgent); + + mainWindow.webContents.session.webRequest.onBeforeSendHeaders( + (details, callback) => { + details.requestHeaders["X-Electron-App"] = "true"; + + details.requestHeaders["User-Agent"] = customUserAgent; + + callback({ requestHeaders: details.requestHeaders }); + }, ); if (isDev) { - mainWindow.loadURL("http:://localhost:5173"); + mainWindow.loadURL("http://localhost:5173"); mainWindow.webContents.openDevTools(); } else { const indexPath = path.join(__dirname, "..", "dist", "index.html"); diff --git a/src/ui/desktop/authentication/Auth.tsx b/src/ui/desktop/authentication/Auth.tsx index 0d3d190e..ddec0713 100644 --- a/src/ui/desktop/authentication/Auth.tsx +++ b/src/ui/desktop/authentication/Auth.tsx @@ -241,6 +241,22 @@ export function Auth({ throw new Error(t("errors.loginFailed")); } + if (isInElectronWebView() && res.token) { + try { + localStorage.setItem("jwt", res.token); + window.parent.postMessage( + { + type: "AUTH_SUCCESS", + token: res.token, + source: "auth_component", + platform: "desktop", + timestamp: Date.now(), + }, + "*", + ); + } catch (e) {} + } + const [meRes] = await Promise.all([getUserInfo()]); setInternalLoggedIn(true); @@ -398,6 +414,22 @@ export function Auth({ localStorage.setItem("jwt", res.token); } + if (isInElectronWebView() && res.token) { + try { + localStorage.setItem("jwt", res.token); + window.parent.postMessage( + { + type: "AUTH_SUCCESS", + token: res.token, + source: "totp_auth_component", + platform: "desktop", + timestamp: Date.now(), + }, + "*", + ); + } catch (e) {} + } + setInternalLoggedIn(true); setLoggedIn(true); setIsAdmin(!!res.is_admin); @@ -485,6 +517,24 @@ export function Auth({ getUserInfo() .then((meRes) => { + if (isInElectronWebView()) { + const token = getCookie("jwt") || localStorage.getItem("jwt"); + if (token) { + try { + window.parent.postMessage( + { + type: "AUTH_SUCCESS", + token: token, + source: "oidc_callback", + platform: "desktop", + timestamp: Date.now(), + }, + "*", + ); + } catch (e) {} + } + } + setInternalLoggedIn(true); setLoggedIn(true); setIsAdmin(!!meRes.is_admin); @@ -577,7 +627,8 @@ export function Auth({ if (showServerConfig === null) { return (
@@ -590,7 +641,8 @@ export function Auth({ if (showServerConfig) { return (
@@ -663,7 +716,8 @@ export function Auth({ if (dbConnectionFailed) { return (
@@ -722,7 +776,8 @@ export function Auth({ return (
{isInElectronWebView() && ( diff --git a/src/ui/desktop/authentication/ElectronLoginForm.tsx b/src/ui/desktop/authentication/ElectronLoginForm.tsx index c64fdde7..c9ccfaf3 100644 --- a/src/ui/desktop/authentication/ElectronLoginForm.tsx +++ b/src/ui/desktop/authentication/ElectronLoginForm.tsx @@ -57,16 +57,13 @@ export function ElectronLoginForm({ onAuthSuccess(); } catch (err) { - console.error("[ElectronLoginForm] Error saving JWT:", err); setError(t("errors.authTokenSaveFailed")); setIsAuthenticating(false); hasAuthenticatedRef.current = false; } } } - } catch (err) { - console.error("[ElectronLoginForm] Error processing message:", err); - } + } catch (err) {} }; window.addEventListener("message", handleMessage); @@ -99,7 +96,9 @@ export function ElectronLoginForm({ let hasNotified = false; function postJWTToParent(token, source) { - if (hasNotified) return; + if (hasNotified) { + return; + } hasNotified = true; try { @@ -111,7 +110,6 @@ export function ElectronLoginForm({ timestamp: Date.now() }, '*'); } catch (e) { - console.error('[Electron WebView] Error posting message:', e); } } @@ -143,7 +141,6 @@ export function ElectronLoginForm({ } } } catch (error) { - console.error('[Electron WebView] Error in checkAuth:', error); } return false; } @@ -178,27 +175,23 @@ export function ElectronLoginForm({ clearInterval(intervalId); }, 300000); - checkAuth(); + setTimeout(() => checkAuth(), 500); })(); `; try { if (iframe.contentWindow) { - iframe.contentWindow.postMessage( - { type: "INJECT_SCRIPT", script: injectedScript }, - "*", - ); - - iframe.contentWindow.eval(injectedScript); + try { + iframe.contentWindow.eval(injectedScript); + } catch (evalError) { + iframe.contentWindow.postMessage( + { type: "INJECT_SCRIPT", script: injectedScript }, + "*", + ); + } } - } catch (err) { - console.warn( - "[ElectronLoginForm] Cannot inject script due to cross-origin restrictions", - ); - } - } catch (err) { - console.error("[ElectronLoginForm] Error in handleLoad:", err); - } + } catch (err) {} + } catch (err) {} }; const handleError = () => { diff --git a/src/ui/main-axios.ts b/src/ui/main-axios.ts index 5a6a73fc..2d30825d 100644 --- a/src/ui/main-axios.ts +++ b/src/ui/main-axios.ts @@ -1695,10 +1695,34 @@ export async function loginUser( try { const response = await authApi.post("/users/login", { username, password }); - if (isElectron() && response.data.token) { + const hasToken = response.data.token; + + if (isElectron() && hasToken) { localStorage.setItem("jwt", response.data.token); } + const isInIframe = + typeof window !== "undefined" && window.self !== window.top; + + if (isInIframe && hasToken) { + localStorage.setItem("jwt", response.data.token); + + try { + window.parent.postMessage( + { + type: "AUTH_SUCCESS", + token: response.data.token, + source: "login_api", + platform: "desktop", + timestamp: Date.now(), + }, + "*", + ); + } catch (e) { + console.error("[main-axios] Error posting message to parent:", e); + } + } + return { token: response.data.token || "cookie-based", success: response.data.success, @@ -2027,6 +2051,35 @@ export async function verifyTOTPLogin( temp_token, totp_code, }); + + const hasToken = response.data.token; + + if (isElectron() && hasToken) { + localStorage.setItem("jwt", response.data.token); + } + + const isInIframe = + typeof window !== "undefined" && window.self !== window.top; + + if (isInIframe && hasToken) { + localStorage.setItem("jwt", response.data.token); + + try { + window.parent.postMessage( + { + type: "AUTH_SUCCESS", + token: response.data.token, + source: "totp_verify", + platform: "desktop", + timestamp: Date.now(), + }, + "*", + ); + } catch (e) { + console.error("[main-axios] Error posting message to parent:", e); + } + } + return response.data; } catch (error) { handleApiError(error as AxiosError, "verify TOTP login"); diff --git a/src/ui/mobile/authentication/Auth.tsx b/src/ui/mobile/authentication/Auth.tsx index c225b908..44e97586 100644 --- a/src/ui/mobile/authentication/Auth.tsx +++ b/src/ui/mobile/authentication/Auth.tsx @@ -40,7 +40,6 @@ function postJWTToWebView() { const jwt = getCookie("jwt") || localStorage.getItem("jwt"); if (!jwt) { - console.warn("JWT not found when trying to post to WebView"); return; } @@ -53,11 +52,7 @@ function postJWTToWebView() { timestamp: Date.now(), }), ); - - console.log("JWT posted to React Native WebView"); - } catch (error) { - console.error("Failed to post JWT to WebView:", error); - } + } catch (error) {} } interface AuthProps extends React.ComponentProps<"div"> { @@ -563,7 +558,8 @@ export function Auth({ return (
{isReactNativeWebView() && (