From 50209a1506fc4ba6c3c473debb170834ebc955e4 Mon Sep 17 00:00:00 2001 From: chan Date: Wed, 11 Feb 2026 15:41:27 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20SSO=20=ED=8C=9D=EC=97=85=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=8B=9C=20postMessage=20=ED=9D=90?= =?UTF-8?q?=EB=A6=84=20=EB=B3=B4=EC=9E=A5=20=EB=B0=8F=20=EC=BD=9C=EB=B0=B1?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=8C=9D=EC=97=85=20=EB=8C=80?= =?UTF-8?q?=EC=9D=91=20#243?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/features/auth/AuthCallbackPage.tsx | 11 +++++++++-- adminfront/src/features/auth/LoginPage.tsx | 6 +++++- .../auth/presentation/login_screen.dart | 17 ++++++++++------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/adminfront/src/features/auth/AuthCallbackPage.tsx b/adminfront/src/features/auth/AuthCallbackPage.tsx index fb98fa68..0817f96e 100644 --- a/adminfront/src/features/auth/AuthCallbackPage.tsx +++ b/adminfront/src/features/auth/AuthCallbackPage.tsx @@ -10,8 +10,15 @@ function AuthCallbackPage() { const token = searchParams.get("token"); if (token) { window.localStorage.setItem("admin_session", token); - // Redirect to home after a short delay or immediately - navigate("/", { replace: true }); + + // 만약 팝업창에서 실행 중이라면 부모 창에 알리고 닫기 + if (window.opener) { + window.opener.postMessage({ type: "LOGIN_SUCCESS", token }, "*"); + window.close(); + } else { + // 일반 리다이렉트 방식인 경우 홈으로 이동 + navigate("/", { replace: true }); + } } else { console.error("No token found in callback URL"); navigate("/login", { replace: true }); diff --git a/adminfront/src/features/auth/LoginPage.tsx b/adminfront/src/features/auth/LoginPage.tsx index 2292f5c4..a8fa4060 100644 --- a/adminfront/src/features/auth/LoginPage.tsx +++ b/adminfront/src/features/auth/LoginPage.tsx @@ -32,7 +32,11 @@ function LoginPage() { const handleSSOLogin = (mode: "popup" | "redirect" = "popup") => { const userfrontUrl = import.meta.env.USERFRONT_URL || "https://sso.hmac.kr"; const callbackUrl = `${window.location.origin}/auth/callback`; - const loginUrl = `${userfrontUrl}/signin?source=adminfront&redirect_uri=${encodeURIComponent(callbackUrl)}`; + + // 팝업 방식일 때는 redirect_uri를 보내지 않아야 postMessage 로직이 작동함 + const loginUrl = mode === "redirect" + ? `${userfrontUrl}/signin?source=adminfront&redirect_uri=${encodeURIComponent(callbackUrl)}` + : `${userfrontUrl}/signin?source=adminfront`; if (mode === "redirect") { window.location.href = loginUrl; diff --git a/userfront/lib/features/auth/presentation/login_screen.dart b/userfront/lib/features/auth/presentation/login_screen.dart index 459b9363..82a3ae6a 100644 --- a/userfront/lib/features/auth/presentation/login_screen.dart +++ b/userfront/lib/features/auth/presentation/login_screen.dart @@ -117,6 +117,8 @@ class _LoginScreenState extends ConsumerState if (uri.queryParameters.containsKey('redirect_url')) { _redirectUrl = uri.queryParameters['redirect_url']; + } else if (uri.queryParameters.containsKey('redirect_uri')) { + _redirectUrl = uri.queryParameters['redirect_uri']; } }); } @@ -1124,13 +1126,14 @@ class _LoginScreenState extends ConsumerState if (WebAuthIntegration.isPopup()) { debugPrint("[Auth] Popup detected. Notifying opener and attempting to close."); WebAuthIntegration.sendLoginSuccess(token); - } else { - if (_redirectUrl != null && _redirectUrl!.isNotEmpty) { - debugPrint("[Auth] Redirecting standalone window to: $_redirectUrl"); - final target = "$_redirectUrl?token=$token"; - launchUrlString(target, webOnlyWindowName: '_self'); - return; - } + return; // Stop here for popups + } + + if (_redirectUrl != null && _redirectUrl!.isNotEmpty) { + debugPrint("[Auth] Redirecting standalone window to: $_redirectUrl"); + final target = "$_redirectUrl?token=$token"; + launchUrlString(target, webOnlyWindowName: '_self'); + return; } debugPrint("[Auth] Login success. Navigating to root.");