From ab2a5462d4eeb874e73558920f6ac291d7766383 Mon Sep 17 00:00:00 2001 From: chan Date: Wed, 11 Feb 2026 16:25:02 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EB=B3=B4=EC=95=88=20=EC=A0=95?= =?UTF-8?q?=EC=B1=85=20=EC=A4=80=EC=88=98=EB=A5=BC=20=EC=9C=84=ED=95=B4=20?= =?UTF-8?q?Keto=20=ED=8F=AC=ED=8A=B8=20=EC=99=B8=EB=B6=80=20=EB=85=B8?= =?UTF-8?q?=EC=B6=9C=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20=EB=82=B4=EB=B6=80?= =?UTF-8?q?=20=ED=86=B5=EC=8B=A0=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?#239?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.sample | 4 ++-- adminfront/src/features/auth/LoginPage.tsx | 24 ++++--------------- compose.ory.yaml | 3 --- .../services/web_auth_integration_web.dart | 10 +++++--- .../auth/presentation/login_screen.dart | 13 +++++----- 5 files changed, 20 insertions(+), 34 deletions(-) diff --git a/.env.sample b/.env.sample index c41e15b3..463b0415 100644 --- a/.env.sample +++ b/.env.sample @@ -88,8 +88,8 @@ HYDRA_VERSION=v25.4.0-distroless # Ory Keto Configuration KETO_VERSION=v25.4.0-distroless -KETO_READ_URL=http://localhost:4466 -KETO_WRITE_URL=http://localhost:4467 +KETO_READ_URL=http://keto:4466 +KETO_WRITE_URL=http://keto:4467 # KETO_READ_PORT=4466 # Internal only # KETO_WRITE_PORT=4467 # Internal only diff --git a/adminfront/src/features/auth/LoginPage.tsx b/adminfront/src/features/auth/LoginPage.tsx index f7c376ca..0912950f 100644 --- a/adminfront/src/features/auth/LoginPage.tsx +++ b/adminfront/src/features/auth/LoginPage.tsx @@ -29,18 +29,13 @@ function LoginPage() { return () => window.removeEventListener("message", handleMessage); }, [navigate]); - const handleSSOLogin = (mode: "popup" | "redirect" = "popup") => { + const handleSSOLogin = () => { const userfrontUrl = import.meta.env.USERFRONT_URL || "https://sso.hmac.kr"; const callbackUrl = `${window.location.origin}/auth/callback`; // 항상 redirect_uri를 포함하여 로그인이 성공하면 콜백 페이지로 오도록 함 const loginUrl = `${userfrontUrl}/signin?source=adminfront&redirect_uri=${encodeURIComponent(callbackUrl)}`; - if (mode === "redirect") { - window.location.href = loginUrl; - return; - } - const width = 500; const height = 700; const left = window.screen.width / 2 - width / 2; @@ -54,7 +49,6 @@ function LoginPage() { if (popup) { setIsLoggingIn(true); - // Optional: Polling to detect if popup was closed without login const timer = setInterval(() => { if (popup.closed) { clearInterval(timer); @@ -62,8 +56,7 @@ function LoginPage() { } }, 1000); } else { - // If popup blocked, fallback to redirect - window.location.href = loginUrl; + alert("팝업 차단이 설정되어 있습니다. 팝업 허용 후 다시 시도해 주세요."); } }; @@ -94,7 +87,7 @@ function LoginPage() { - -

관리자 전역 세션은 보안을 위해 15분간 유지됩니다.
diff --git a/compose.ory.yaml b/compose.ory.yaml index c3412eb0..5e9d5f9d 100644 --- a/compose.ory.yaml +++ b/compose.ory.yaml @@ -121,9 +121,6 @@ services: keto: image: oryd/keto:${KETO_VERSION:-v25.4.0} container_name: ory_keto - ports: - - "4466:4466" # Read API - - "4467:4467" # Write API environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20 volumes: diff --git a/userfront/lib/core/services/web_auth_integration_web.dart b/userfront/lib/core/services/web_auth_integration_web.dart index 2ecaf079..454ff920 100644 --- a/userfront/lib/core/services/web_auth_integration_web.dart +++ b/userfront/lib/core/services/web_auth_integration_web.dart @@ -11,8 +11,8 @@ void implSendLoginSuccess(String token) { effectiveToken = AuthTokenStore.getToken() ?? ""; } - final uri = Uri.parse(html.window.location.href); - final redirectUri = uri.queryParameters['redirect_uri']; + final uri = Uri.base; + final redirectUri = uri.queryParameters['redirect_uri'] ?? uri.queryParameters['redirect_url']; if (redirectUri != null && redirectUri.isNotEmpty) { // Redirection flow @@ -47,5 +47,9 @@ void implSendLoginSuccess(String token) { } bool implIsPopup() { - return html.window.opener != null; + if (html.window.opener != null) return true; + + // Fallback: Check query parameters for integration source + final uri = Uri.base; + return uri.queryParameters['source'] == 'adminfront'; } diff --git a/userfront/lib/features/auth/presentation/login_screen.dart b/userfront/lib/features/auth/presentation/login_screen.dart index f4e12b3f..4b9e3cbf 100644 --- a/userfront/lib/features/auth/presentation/login_screen.dart +++ b/userfront/lib/features/auth/presentation/login_screen.dart @@ -78,6 +78,13 @@ class _LoginScreenState extends ConsumerState WidgetsBinding.instance.addPostFrameCallback((_) async { final uri = Uri.base; + + if (uri.queryParameters.containsKey('redirect_url')) { + _redirectUrl = uri.queryParameters['redirect_url']; + } else if (uri.queryParameters.containsKey('redirect_uri')) { + _redirectUrl = uri.queryParameters['redirect_uri']; + } + _loginChallenge = widget.loginChallenge ?? uri.queryParameters['login_challenge']; final loginIdParam = uri.queryParameters['loginId']; final codeParam = uri.queryParameters['code']; @@ -114,12 +121,6 @@ class _LoginScreenState extends ConsumerState if (!mounted) return; await _tryCookieSession(); } - - if (uri.queryParameters.containsKey('redirect_url')) { - _redirectUrl = uri.queryParameters['redirect_url']; - } else if (uri.queryParameters.containsKey('redirect_uri')) { - _redirectUrl = uri.queryParameters['redirect_uri']; - } }); }