From 31e9074ad9991dd7ca8bd8d0b785b6919fb0c663 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Wed, 7 Feb 2024 22:26:31 +0100 Subject: [PATCH] Improve webview approach and introduce Linows class --- flutter_web_auth_2/example/lib/main.dart | 22 +++------- .../flutter/generated_plugin_registrant.cc | 4 ++ .../linux/flutter/generated_plugins.cmake | 1 + .../Flutter/GeneratedPluginRegistrant.swift | 4 ++ .../example/windows/flutter/CMakeLists.txt | 7 ++- .../flutter/generated_plugin_registrant.cc | 3 ++ .../windows/flutter/generated_plugins.cmake | 1 + .../lib/flutter_web_auth_2.dart | 3 +- flutter_web_auth_2/lib/src/linows.dart | 44 +++++++++++++++++++ flutter_web_auth_2/lib/src/options.dart | 14 +++++- .../lib/src/{windows.dart => webview.dart} | 17 ++++--- flutter_web_auth_2/pubspec.yaml | 8 ++-- 12 files changed, 95 insertions(+), 33 deletions(-) create mode 100644 flutter_web_auth_2/lib/src/linows.dart rename flutter_web_auth_2/lib/src/{windows.dart => webview.dart} (82%) diff --git a/flutter_web_auth_2/example/lib/main.dart b/flutter_web_auth_2/example/lib/main.dart index 0423cc1..3687dd9 100644 --- a/flutter_web_auth_2/example/lib/main.dart +++ b/flutter_web_auth_2/example/lib/main.dart @@ -1,5 +1,5 @@ import 'dart:async'; -import 'dart:io' show HttpServer, Platform; +import 'dart:io' show HttpServer; import 'package:desktop_webview_window/desktop_webview_window.dart'; import 'package:flutter/foundation.dart'; @@ -99,17 +99,11 @@ class MyAppState extends State { req.response.headers.add('Content-Type', 'text/html'); - // Windows needs some callback URL on localhost req.response.write( - (Platform.isLinux) - ? html.replaceFirst( - 'CALLBACK_URL_HERE', - 'http://localhost:43824/success?code=1337', - ) - : html.replaceFirst( - 'CALLBACK_URL_HERE', - 'foobar://success?code=1337', - ), + html.replaceFirst( + 'CALLBACK_URL_HERE', + 'foobar://success?code=1337', + ), ); await req.response.close(); @@ -126,14 +120,10 @@ class MyAppState extends State { // the socket server... final url = kIsWeb ? '${Uri.base}auth.html' : 'http://127.0.0.1:43823/'; - // Windows needs some callback URL on localhost - final callbackUrlScheme = - !kIsWeb && (Platform.isLinux) ? 'http://localhost:43824' : 'foobar'; - try { final result = await FlutterWebAuth2.authenticate( url: url, - callbackUrlScheme: callbackUrlScheme, + callbackUrlScheme: 'foobar', options: const FlutterWebAuth2Options( timeout: 5, // example: 5 seconds timeout ), diff --git a/flutter_web_auth_2/example/linux/flutter/generated_plugin_registrant.cc b/flutter_web_auth_2/example/linux/flutter/generated_plugin_registrant.cc index 25f9f58..9f3151b 100644 --- a/flutter_web_auth_2/example/linux/flutter/generated_plugin_registrant.cc +++ b/flutter_web_auth_2/example/linux/flutter/generated_plugin_registrant.cc @@ -6,10 +6,14 @@ #include "generated_plugin_registrant.h" +#include #include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) desktop_webview_window_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopWebviewWindowPlugin"); + desktop_webview_window_plugin_register_with_registrar(desktop_webview_window_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/flutter_web_auth_2/example/linux/flutter/generated_plugins.cmake b/flutter_web_auth_2/example/linux/flutter/generated_plugins.cmake index e9e5df3..9bc27dc 100644 --- a/flutter_web_auth_2/example/linux/flutter/generated_plugins.cmake +++ b/flutter_web_auth_2/example/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + desktop_webview_window url_launcher_linux window_to_front ) diff --git a/flutter_web_auth_2/example/macos/Flutter/GeneratedPluginRegistrant.swift b/flutter_web_auth_2/example/macos/Flutter/GeneratedPluginRegistrant.swift index 5b2c1bd..a0f9915 100644 --- a/flutter_web_auth_2/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/flutter_web_auth_2/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,12 +5,16 @@ import FlutterMacOS import Foundation +import desktop_webview_window import flutter_web_auth_2 +import path_provider_foundation import url_launcher_macos import window_to_front func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + DesktopWebviewWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWebviewWindowPlugin")) FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin")) } diff --git a/flutter_web_auth_2/example/windows/flutter/CMakeLists.txt b/flutter_web_auth_2/example/windows/flutter/CMakeLists.txt index 930d207..903f489 100644 --- a/flutter_web_auth_2/example/windows/flutter/CMakeLists.txt +++ b/flutter_web_auth_2/example/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/flutter_web_auth_2/example/windows/flutter/generated_plugin_registrant.cc b/flutter_web_auth_2/example/windows/flutter/generated_plugin_registrant.cc index 157b2ee..3a6d25f 100644 --- a/flutter_web_auth_2/example/windows/flutter/generated_plugin_registrant.cc +++ b/flutter_web_auth_2/example/windows/flutter/generated_plugin_registrant.cc @@ -6,10 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + DesktopWebviewWindowPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); WindowToFrontPluginRegisterWithRegistrar( diff --git a/flutter_web_auth_2/example/windows/flutter/generated_plugins.cmake b/flutter_web_auth_2/example/windows/flutter/generated_plugins.cmake index 70c6850..cf17c65 100644 --- a/flutter_web_auth_2/example/windows/flutter/generated_plugins.cmake +++ b/flutter_web_auth_2/example/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + desktop_webview_window url_launcher_windows window_to_front ) diff --git a/flutter_web_auth_2/lib/flutter_web_auth_2.dart b/flutter_web_auth_2/lib/flutter_web_auth_2.dart index c9084b9..787e5ba 100644 --- a/flutter_web_auth_2/lib/flutter_web_auth_2.dart +++ b/flutter_web_auth_2/lib/flutter_web_auth_2.dart @@ -8,9 +8,8 @@ import 'package:flutter_web_auth_2_platform_interface/flutter_web_auth_2_platfor export 'src/options.dart'; export 'src/unsupported.dart' - if (dart.library.io) 'src/server.dart' + if (dart.library.io) 'src/linows.dart' if (dart.library.html) 'src/web.dart'; -export 'src/windows.dart'; class _OnAppLifecycleResumeObserver extends WidgetsBindingObserver { final Function onResumed; diff --git a/flutter_web_auth_2/lib/src/linows.dart b/flutter_web_auth_2/lib/src/linows.dart new file mode 100644 index 0000000..9e207b9 --- /dev/null +++ b/flutter_web_auth_2/lib/src/linows.dart @@ -0,0 +1,44 @@ +import 'dart:async'; + +import 'package:flutter_web_auth_2/flutter_web_auth_2.dart'; +import 'package:flutter_web_auth_2/src/server.dart'; +import 'package:flutter_web_auth_2/src/webview.dart'; +import 'package:flutter_web_auth_2_platform_interface/flutter_web_auth_2_platform_interface.dart'; + +/// Implements the plugin interface for Linux and Windows (Linows) +class FlutterWebAuth2LinowsPlugin extends FlutterWebAuth2Platform { + final FlutterWebAuth2Platform _webviewImpl = FlutterWebAuth2WebViewPlugin(); + final FlutterWebAuth2Platform _serverImpl = FlutterWebAuth2ServerPlugin(); + + /// Registers the Linows super-implementation. + static void registerWith() { + FlutterWebAuth2Platform.instance = FlutterWebAuth2LinowsPlugin(); + } + + @override + Future authenticate({ + required String url, + required String callbackUrlScheme, + required Map options, + }) async { + final parsedOptions = FlutterWebAuth2Options.fromJson(options); + if (parsedOptions.useWebview) { + return _webviewImpl.authenticate( + url: url, + callbackUrlScheme: callbackUrlScheme, + options: options, + ); + } + return _serverImpl.authenticate( + url: url, + callbackUrlScheme: callbackUrlScheme, + options: options, + ); + } + + @override + Future clearAllDanglingCalls() async { + await _serverImpl.clearAllDanglingCalls(); + await _webviewImpl.clearAllDanglingCalls(); + } +} diff --git a/flutter_web_auth_2/lib/src/options.dart b/flutter_web_auth_2/lib/src/options.dart index f822259..23b8816 100644 --- a/flutter_web_auth_2/lib/src/options.dart +++ b/flutter_web_auth_2/lib/src/options.dart @@ -96,6 +96,14 @@ class FlutterWebAuth2Options { /// MALICIOUS ATTACKERS! final bool silentAuth; + /// **Only has an effect on Linux and Windows!** + /// When set to `true`, use the new Webview implementation. + /// When set to `false`, the old approach using an internal server is being + /// used in order to fetch the HTTP result. When using the internal server, + /// please keep in mind that you cannot choose any callback URL scheme, as + /// described in https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/25 + final bool useWebview; + const FlutterWebAuth2Options({ bool? preferEphemeral, this.debugOrigin, @@ -104,11 +112,13 @@ class FlutterWebAuth2Options { int? timeout, String? landingPageHtml, bool? silentAuth, + bool? useWebview, }) : preferEphemeral = preferEphemeral ?? false, intentFlags = intentFlags ?? defaultIntentFlags, timeout = timeout ?? 5 * 60, landingPageHtml = landingPageHtml ?? _defaultLandingPage, - silentAuth = silentAuth ?? false; + silentAuth = silentAuth ?? false, + useWebview = useWebview ?? true; FlutterWebAuth2Options.fromJson(Map json) : this( @@ -119,6 +129,7 @@ class FlutterWebAuth2Options { timeout: json['timeout'], landingPageHtml: json['landingPageHtml'], silentAuth: json['silentAuth'], + useWebview: json['useWebview'], ); Map toJson() => { @@ -129,5 +140,6 @@ class FlutterWebAuth2Options { 'timeout': timeout, 'landingPageHtml': landingPageHtml, 'silentAuth': silentAuth, + 'useWebview': useWebview, }; } diff --git a/flutter_web_auth_2/lib/src/windows.dart b/flutter_web_auth_2/lib/src/webview.dart similarity index 82% rename from flutter_web_auth_2/lib/src/windows.dart rename to flutter_web_auth_2/lib/src/webview.dart index 0030ad8..dad99a5 100644 --- a/flutter_web_auth_2/lib/src/windows.dart +++ b/flutter_web_auth_2/lib/src/webview.dart @@ -1,17 +1,19 @@ import 'dart:async'; import 'package:desktop_webview_window/desktop_webview_window.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:flutter_web_auth_2_platform_interface/flutter_web_auth_2_platform_interface.dart'; import 'package:path_provider/path_provider.dart'; -class FlutterWebAuth2WindowsPlugin extends FlutterWebAuth2Platform { +/// Implements the plugin interface using the Webview interface (currently used +/// by Windows and Linux). +class FlutterWebAuth2WebViewPlugin extends FlutterWebAuth2Platform { bool authenticated = false; Webview? webview; + /// Registers the Webview implementation. static void registerWith() { - FlutterWebAuth2Platform.instance = FlutterWebAuth2WindowsPlugin(); + FlutterWebAuth2Platform.instance = FlutterWebAuth2WebViewPlugin(); } @override @@ -21,7 +23,7 @@ class FlutterWebAuth2WindowsPlugin extends FlutterWebAuth2Platform { required Map options, }) async { if (!await WebviewWindow.isWebviewAvailable()) { - //Microsofts WebView2 must be installed for this to work + // Microsoft's WebView2 must be installed for this to work throw StateError('Webview is not available'); } //Reset @@ -29,9 +31,6 @@ class FlutterWebAuth2WindowsPlugin extends FlutterWebAuth2Platform { webview?.close(); final c = Completer(); - debugPrint( - '''Launching webview with url: $url, callbackUrlScheme: $callbackUrlScheme, tmpDir: ${(await getTemporaryDirectory()).path}''', - ); webview = await WebviewWindow.create( configuration: CreateConfiguration( windowHeight: 720, @@ -47,7 +46,7 @@ class FlutterWebAuth2WindowsPlugin extends FlutterWebAuth2Platform { authenticated = true; webview?.close(); /** - * Not setting the webview to null will cause a crash if the + * Not setting the webview to null will cause a crash if the * application tries to open another webview */ webview = null; @@ -58,7 +57,7 @@ class FlutterWebAuth2WindowsPlugin extends FlutterWebAuth2Platform { webview!.onClose.whenComplete( () { /** - * Not setting the webview to null will cause a crash if the + * Not setting the webview to null will cause a crash if the * application tries to open another webview */ webview = null; diff --git a/flutter_web_auth_2/pubspec.yaml b/flutter_web_auth_2/pubspec.yaml index 658423e..f8896d8 100644 --- a/flutter_web_auth_2/pubspec.yaml +++ b/flutter_web_auth_2/pubspec.yaml @@ -48,13 +48,13 @@ flutter: ios: pluginClass: FlutterWebAuth2Plugin linux: - dartPluginClass: FlutterWebAuth2ServerPlugin - fileName: src/server.dart + dartPluginClass: FlutterWebAuth2LinowsPlugin + fileName: src/linows.dart macos: pluginClass: FlutterWebAuth2Plugin web: pluginClass: FlutterWebAuth2WebPlugin fileName: src/web.dart windows: - dartPluginClass: FlutterWebAuth2WindowsPlugin - fileName: src/windows.dart + dartPluginClass: FlutterWebAuth2LinowsPlugin + fileName: src/linows.dart