From 03a78d75ae16b66df0f9d681f7d8c761cf66ec82 Mon Sep 17 00:00:00 2001 From: Lectom C Han Date: Fri, 30 Jan 2026 17:55:43 +0900 Subject: [PATCH] =?UTF-8?q?gateway=20=EB=B6=84=EB=A6=AC=20=EC=95=84?= =?UTF-8?q?=ED=82=A4=ED=85=8D=EC=B2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/core/services/auth_proxy_service.dart | 17 ++++++++ .../auth/presentation/login_screen.dart | 43 ++++++++++++++----- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/userfront/lib/core/services/auth_proxy_service.dart b/userfront/lib/core/services/auth_proxy_service.dart index d321a411..2a07288b 100644 --- a/userfront/lib/core/services/auth_proxy_service.dart +++ b/userfront/lib/core/services/auth_proxy_service.dart @@ -52,6 +52,23 @@ class AuthProxyService { } } + static Future getSessionStatus({String? token, bool useCookie = false}) async { + final url = Uri.parse('$_baseUrl/api/v1/user/me'); + final client = createHttpClient(withCredentials: useCookie); + try { + final headers = { + 'Content-Type': 'application/json', + }; + if (!useCookie && token != null && token.isNotEmpty) { + headers['Authorization'] = 'Bearer $token'; + } + final response = await client.get(url, headers: headers); + return response.statusCode; + } finally { + client.close(); + } + } + static Future> initEnchantedLink( String loginId, { String? method, diff --git a/userfront/lib/features/auth/presentation/login_screen.dart b/userfront/lib/features/auth/presentation/login_screen.dart index f2730a8e..f71c025b 100644 --- a/userfront/lib/features/auth/presentation/login_screen.dart +++ b/userfront/lib/features/auth/presentation/login_screen.dart @@ -345,11 +345,28 @@ class _LoginScreenState extends ConsumerState _onLoginSuccess(token, provider: provider); } - bool _hasLocalSession() { - if (AuthTokenStore.getToken() != null) { - return true; + Future _hasValidLocalSession() async { + final token = AuthTokenStore.getToken(); + final usesCookie = AuthTokenStore.usesCookie(); + if (token == null && !usesCookie) { + return false; } - return AuthTokenStore.usesCookie(); + + try { + final status = await AuthProxyService.getSessionStatus( + token: token, + useCookie: usesCookie, + ); + if (status == 200) { + return true; + } + if (status == 401 || status == 403) { + AuthTokenStore.clear(); + } + } catch (e) { + debugPrint("[Auth] 세션 확인 실패: $e"); + } + return false; } void _markVerificationApproved( @@ -416,11 +433,10 @@ class _LoginScreenState extends ConsumerState final res = await AuthProxyService.verifyMagicLink(token); debugPrint("[Auth] Verification successful for token: $token"); final jwt = res['token'] ?? res['sessionJwt']; - final provider = res['provider'] as String?; - final hasLocalSession = _hasLocalSession(); + final hasLocalSession = await _hasValidLocalSession(); if (jwt is String && jwt.isNotEmpty) { - if (hasLocalSession) { + if (hasLocalSession) { _markVerificationApproved( "승인 되었습니다. 이 기기는 로그인되어 있는 상태입니다. 원격 창도 로그인이 될 예정입니다", ); @@ -460,7 +476,7 @@ class _LoginScreenState extends ConsumerState final jwt = res['sessionJwt'] ?? res['token']; final status = res['status']?.toString(); debugPrint("[Auth] Code verification successful for loginId: $sanitizedLoginId"); - final hasLocalSession = _hasLocalSession(); + final hasLocalSession = await _hasValidLocalSession(); if (jwt == null && status == 'approved') { if (mounted) { @@ -476,7 +492,14 @@ class _LoginScreenState extends ConsumerState ); return; } - _completeLoginFromToken(jwt, provider: res['provider'] as String?); + _markVerificationApproved( + "링크로 로그인 되었습니다. 잠시 후 로그인 화면으로 이동합니다.", + title: '링크 로그인 완료', + pageTitle: '링크 로그인', + actionLabel: '로그인 화면으로 이동', + actionPath: '/signin', + autoRedirect: true, + ); return; } @@ -500,7 +523,7 @@ class _LoginScreenState extends ConsumerState final jwt = res['sessionJwt'] ?? res['token']; final status = res['status']?.toString(); debugPrint("[Auth] Short code verification successful"); - final hasLocalSession = _hasLocalSession(); + final hasLocalSession = await _hasValidLocalSession(); if (jwt == null && status == 'approved') { if (mounted) {