From b65fca8116a90fde2241ae69f209df84e292ca14 Mon Sep 17 00:00:00 2001 From: mso7nueh Date: Tue, 30 Sep 2025 16:11:30 +0300 Subject: [PATCH] feat(auth): Issue-691 --- .../auth/presentation/pages/auth_screen.dart | 17 --- lib/features/auth/sdk/social_auth_facade.dart | 102 ++++++++---------- lib/main.dart | 2 - 3 files changed, 47 insertions(+), 74 deletions(-) diff --git a/lib/features/auth/presentation/pages/auth_screen.dart b/lib/features/auth/presentation/pages/auth_screen.dart index 5f9496ac..30ef29cf 100644 --- a/lib/features/auth/presentation/pages/auth_screen.dart +++ b/lib/features/auth/presentation/pages/auth_screen.dart @@ -389,63 +389,46 @@ class _SocialButton extends StatelessWidget { } void _onVkPressed(BuildContext context) async { - print('[VK] VK button pressed'); try { final accessToken = await SocialAuthFacade.signInWithVk(context: context); - print('[VK] Got access token: ${accessToken != null ? 'success' : 'null'}'); if (accessToken == null) { - print('[VK] No access token received'); return; } final isAuthenticated = await sl().getTokenBySocial(provider: 'vk', accessToken: accessToken); - print('[VK] Authentication result: $isAuthenticated'); if (isAuthenticated) { if (AppRouter.navigatorKey.currentContext != null) { - // Reuse success flow - // ignore: use_build_context_synchronously await _reconnectAfterAuth(); } } } catch (e) { - print('[VK] Error during VK auth: $e'); } } void _onOkPressed() async { - print('[OK] OK button pressed'); try { final accessToken = await SocialAuthFacade.signInWithOk(); - print('[OK] Got access token: ${accessToken != null ? 'success' : 'null'}'); if (accessToken == null) { - print('[OK] No access token received'); return; } final isAuthenticated = await sl().getTokenBySocial(provider: 'ok', accessToken: accessToken); - print('[OK] Authentication result: $isAuthenticated'); if (isAuthenticated) { await _reconnectAfterAuth(); } } catch (e) { - print('[OK] Error during OK auth: $e'); } } void _onMailRuPressed() async { - print('[MailRu] MailRu button pressed'); try { final accessToken = await SocialAuthFacade.signInWithMailRu(); - print('[MailRu] Got access token: ${accessToken != null ? 'success' : 'null'}'); if (accessToken == null) { - print('[MailRu] No access token received'); return; } final isAuthenticated = await sl().getTokenBySocial(provider: 'mailru', accessToken: accessToken); - print('[MailRu] Authentication result: $isAuthenticated'); if (isAuthenticated) { await _reconnectAfterAuth(); } } catch (e) { - print('[MailRu] Error during MailRu auth: $e'); } } diff --git a/lib/features/auth/sdk/social_auth_facade.dart b/lib/features/auth/sdk/social_auth_facade.dart index 90d07e95..74959498 100644 --- a/lib/features/auth/sdk/social_auth_facade.dart +++ b/lib/features/auth/sdk/social_auth_facade.dart @@ -29,51 +29,35 @@ class SocialAuthFacade { static Future signInWithVkAndFetchProfile({required BuildContext context}) async { final clientIdStr = EnvConfig.vkClientId.trim(); - print('[VK] VK_CLIENT_ID from EnvConfig: $clientIdStr'); if (clientIdStr.isEmpty) { - print('[VK] VK_CLIENT_ID is not set. Configure it in .env'); return null; } try { - print('[VK] Creating VkIDController with clientId: $clientIdStr'); dynamic controller = VkIDController(clID: int.parse(clientIdStr)); final authUri = controller.generateAuthorizeLinkWithCodeVerifier(); - print('[VK] Generated auth URI: $authUri'); - // Extract URL from MapEntry String authUrl; if (authUri is MapEntry) { authUrl = authUri.value.toString(); } else { authUrl = authUri.toString(); } - print('[VK] Extracted auth URL: $authUrl'); final redirectScheme = 'vk$clientIdStr://'; - print('[VK] Redirect scheme: $redirectScheme'); final redirectParams = await _presentOAuthWebView(context: context, initialUrl: authUrl, redirectSchemePrefix: redirectScheme); - print('[VK] WebView returned params: $redirectParams'); if (redirectParams == null) { - print('[VK] No redirect params received'); return null; } final code = redirectParams['code']; final deviceId = redirectParams['device_id']; - print('[VK] Code: $code, DeviceId: $deviceId'); if (code == null || deviceId == null) { - print('[VK] Missing code or deviceId'); return null; } - - // Instead of exchanging the code on-device (the sdk method is not available), - // return the authorization code so the backend can exchange it securely. - print('[VK] Returning authorization code to backend for exchange'); return VkAuthResult(accessToken: code); } catch (e) { - print('[VK] Error in signInWithVkAndFetchProfile: $e'); return null; } } @@ -94,20 +78,47 @@ class SocialAuthFacade { final clientId = EnvConfig.yandexClientId.trim(); final redirectUri = EnvConfig.yandexRedirectUri.trim(); - print('[Yandex] Client ID: $clientId'); - print('[Yandex] Redirect URI: $redirectUri'); - if (clientId.isEmpty || redirectUri.isEmpty) { - print('[Yandex] Missing YANDEX_CLIENT_ID or YANDEX_REDIRECT_URI in .env'); return null; } + try { - final plugin = FlutterLoginYandex(); - final response = await plugin.signIn(); - final token = (response is Map) ? response['token'] as String? : null; - return (token != null && token.isNotEmpty) ? token : null; - } catch (_) { + final context = AppRouter.navigatorKey.currentContext; + if (context == null) return null; + + final authorizeUrl = Uri.https('oauth.yandex.ru', '/authorize', { + 'response_type': 'token', + 'client_id': clientId, + 'redirect_uri': redirectUri, + 'force_confirm': 'yes', + }).toString(); + + final redirectSchemePrefix = redirectUri; + + final params = await _presentOAuthWebView(context: context, initialUrl: authorizeUrl, redirectSchemePrefix: redirectSchemePrefix); + + if (params == null) return null; + + final token = params['access_token']; + if (token != null && token.isNotEmpty) { + return token; + } + + final code = params['code']; + if (code != null && code.isNotEmpty) { + return code; + } + return null; + } catch (e) { + try { + final plugin = FlutterLoginYandex(); + final response = await plugin.signIn(); + final token = (response is Map) ? response['token'] as String? : null; + return (token != null && token.isNotEmpty) ? token : null; + } catch (_) { + return null; + } } } @@ -117,26 +128,16 @@ class SocialAuthFacade { return null; } try { - print('[VK] Provider flow start: $provider, clientId: $clientIdStr'); dynamic controller = VkIDController(clID: int.parse(clientIdStr)); - // Try different approaches for provider parameter dynamic authUri; try { - // First try with provider as string authUri = controller.generateAuthorizeLinkWithCodeVerifier(provider: provider); - print('[VK] [$provider] Generated auth URI with string provider: $authUri'); } catch (e) { - print('[VK] [$provider] Failed with string provider, trying null: $e'); try { - // Try with null provider authUri = controller.generateAuthorizeLinkWithCodeVerifier(provider: null); - print('[VK] [$provider] Generated auth URI with null provider: $authUri'); } catch (e2) { - print('[VK] [$provider] Failed with null provider, trying without provider: $e2'); - // Try without provider parameter authUri = controller.generateAuthorizeLinkWithCodeVerifier(); - print('[VK] [$provider] Generated auth URI without provider: $authUri'); } } @@ -147,61 +148,53 @@ class SocialAuthFacade { } else { authUrl = authUri.toString(); } - print('[VK] [$provider] Extracted auth URL: $authUrl'); - final redirectScheme = 'vk$clientIdStr://'; - print('[VK] [$provider] Redirect scheme: $redirectScheme'); final redirectParams = await _presentOAuthWebView(context: context, initialUrl: authUrl, redirectSchemePrefix: redirectScheme); - print('[VK] [$provider] WebView returned params: $redirectParams'); if (redirectParams == null) return null; final code = redirectParams['code']; final deviceId = redirectParams['device_id']; - print('[VK] [$provider] Code: $code, DeviceId: $deviceId'); if (code == null || deviceId == null) return null; - // Return the authorization code to be exchanged by the backend for provider flow return code; } catch (e) { - print('[VK] [$provider] Error in provider flow: $e'); return null; } } - // Token extraction is no longer needed because we return the authorization code - // to the backend for exchange. - static Future?> _presentOAuthWebView({ required BuildContext context, required String initialUrl, required String redirectSchemePrefix, }) async { - print('[VK] WebView: Loading URL: $initialUrl'); - print('[VK] WebView: Redirect scheme: $redirectSchemePrefix'); - final controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setNavigationDelegate( NavigationDelegate( onNavigationRequest: (request) { final url = request.url; - print('[VK] WebView: Navigation to: $url'); if (url.startsWith(redirectSchemePrefix)) { - print('[VK] WebView: Redirect detected, parsing params'); final uri = Uri.parse(url); final params = {}..addAll(uri.queryParameters); - print('[VK] WebView: Parsed params: $params'); + if (uri.fragment.isNotEmpty) { + final fragPairs = uri.fragment.split('&'); + for (final pair in fragPairs) { + final eq = pair.indexOf('='); + if (eq > 0 && eq < pair.length - 1) { + final key = Uri.decodeComponent(pair.substring(0, eq)); + final value = Uri.decodeComponent(pair.substring(eq + 1)); + params[key] = value; + } + } + } Navigator.of(context, rootNavigator: true).pop(params); return NavigationDecision.prevent; } return NavigationDecision.navigate; }, onPageStarted: (url) { - print('[VK] WebView: Page started loading: $url'); }, onPageFinished: (url) { - print('[VK] WebView: Page finished loading: $url'); }, onWebResourceError: (error) { - print('[VK] WebView: Error: ${error.description}'); }, ), ); @@ -209,7 +202,6 @@ class SocialAuthFacade { try { await controller.loadRequest(Uri.parse(initialUrl)); } catch (e) { - print('[VK] WebView: Failed to load URL: $e'); return null; } diff --git a/lib/main.dart b/lib/main.dart index e0492219..d716f3fa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -31,8 +31,6 @@ Future main() async { FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); await dotenv.load(fileName: ".env"); - print('[ENV] Loaded .env file'); - print('[ENV] VK_CLIENT_ID: ${dotenv.maybeGet('VK_CLIENT_ID')}'); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await FirebaseMessaging.instance.requestPermission();