+
+#ifdef FLUTTER_PLUGIN_IMPL
+#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport)
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+FLUTTER_PLUGIN_EXPORT void FlutterTtsPluginRegisterWithRegistrar(
+ FlutterDesktopPluginRegistrarRef registrar);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#endif // FLUTTER_PLUGIN_FLUTTER_TTS_PLUGIN_H_
diff --git a/third_party/flutter_web_auth_2/CHANGELOG.md b/third_party/flutter_web_auth_2/CHANGELOG.md
new file mode 100644
index 00000000..285fcb61
--- /dev/null
+++ b/third_party/flutter_web_auth_2/CHANGELOG.md
@@ -0,0 +1,406 @@
+## 6.0.0-alpha.7
+
+- 🐛 Handle missing `authUri`/`callbackScheme` gracefully (Thanks to [@md-shohan-ahmed](https://github.com/md-shohan-ahmed) in [#209](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/209), related to [#207](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/207))
+
+## 5.1.0
+
+- 🐛 Catch `SecurityException` when launching the auth tab (Thanks to [@hokeroid](https://github.com/hokeroid) in [#212](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/212), related to [#211](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/211))
+- 🐛 Handle missing `authUri`/`callbackScheme` gracefully (Thanks to [@md-shohan-ahmed](https://github.com/md-shohan-ahmed) in [#209](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/209), related to [#207](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/207))
+
+## 6.0.0-alpha.6
+
+- 🐛 Catch `SecurityException` when launching the auth tab (Thanks to [@hokeroid](https://github.com/hokeroid) in [#212](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/212), related to [#211](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/211))
+
+## 6.0.0-alpha.5
+
+- 🌹 Allow `window_to_front` versions `1.x`
+- 🌹 Bump `melos` to `8.x`
+
+## 6.0.0-alpha.4
+
+- 💥 Drop support for `web` versions `0.x`
+- 🌹 Bump `window_to_front` to `0.1.0`
+
+## 6.0.0-alpha.3
+
+- 🐛 Refactor error handling to use Swift `Error` type for improved compatibility (Thanks to [@Abhishek-Khanal](https://github.com/Abhishek-Khanal) in [#204](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/204))
+
+## 6.0.0-alpha.2
+
+- 💥 Bump Flutter and Dart SDK constraints to `3.44.0` and `3.12.0` stable, respectively
+- 🌹 Enhancement: provide detailed error information in FlutterError responses for iOS and macOS (Thanks to [@Abhishek-Khanal](https://github.com/Abhishek-Khanal) in [#200](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/200))
+- 🌹 Migrate iOS plugin to UIScene lifecycle (Thanks to [@alihamza0173](https://github.com/alihamza0173) in [#201](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/201))
+
+## 6.0.0-alpha.1
+
+- 🌹 Bump `desktop_webview_window` to `0.3.0`
+
+## 5.0.3
+
+- 🌹 Bump `desktop_webview_window` to `0.3.0`
+
+## 6.0.0-alpha.0
+
+- 💥 Bump Flutter and Dart SDK constraints to `3.44.0` and `3.12.0` betas, respectively
+- 💥 Regenerate entire project skeleton (also migrates to built-in Kotlin)
+- 💥 Rename `cleanUpDanglingCalls` -> `clearAllDanglingCalls` (unification)
+
+## 5.0.2
+
+- 🐛 Fix possible NPE on Android (Thanks to [@henry11996](https://github.com/henry11996) in [#196](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/196))
+- 🌹 Dummy implementation for `cleanUpDanglingCalls` on web to prevent unneeded crashes
+
+## 5.0.1
+
+- 🐛 Fix crash on Android and implement proper feedback if no browser is installed (Thanks to [@Mino5531](https://github.com/Mino5531) in [#190](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/190))
+
+## 5.0.0
+
+*No changes - just the official version release!*
+
+## 5.0.0-alpha.7
+
+- 🌹 Update Android intricacies
+- 🐛 Revert to `CustomTabsIntent` when needed (Thanks to [@StevenSorial](https://github.com/StevenSorial) in [#181](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/181))
+
+## 5.0.0-alpha.6
+
+- 🌹 Fix ephemeral web views on Android; re-introduces `preferEphemeral` on Android for more iOS/Android parity (Thanks to [@ApofisXII](https://github.com/ApofisXII) in [#180](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/180), related to [#169](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/169))
+
+## 5.0.0-alpha.5
+
+- 🌹 Include more error details on iOS (Thanks to [@PawlikMichal25](https://github.com/PawlikMichal25) in [#179](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/179), related to [#178](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/178))
+
+## 5.0.0-alpha.4
+
+- 🌹 Update melos to regular `7.x` releases
+- 🌹 Update linter to `6.x`
+- 🌹 Fix a few Android warnings (Gradle `9.x` complaints)
+
+## 5.0.0-alpha.3
+
+- 💥 Migrate to Swift Package Manager - see [here](https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-app-developers) for more info (Thanks to [@lishaduck](https://github.com/lishaduck) in [#165](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/165))
+
+## 5.0.0-alpha.2
+
+- 💥 Even newer Android authentication approach (Thanks to [@titanous](https://github.com/titanous) in [#163](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/163))
+- 🌹 Add auto-close to old server method default landing page on Windows and Linux
+
+## 5.0.0-alpha.1
+
+- 🌹 Added migration guide for `5.x` and updated migration guide for `4.x`
+
+## 5.0.0-alpha.0
+
+- 💥 Update melos to `7.x` (requires SDK `>=3.5.0`)
+- 💥 New Android authentication approach (Thanks to [@Mino5531](https://github.com/Mino5531) in [#156](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/156))
+
+## 4.1.0
+
+- 🌹 Add host and path comparator to webview implementation (related to [#146](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/146))
+- 🐛 Hopefully fix WASM compatibility
+
+## 4.0.2
+
+- 🌹 Improve README (additions to migration guide and Google scopes)
+
+## 4.0.1
+
+- 🌹 Update `flutter_lints` to `5.x` - should not really change anything!
+
+## 4.0.0
+
+*No changes - just the official version release!*
+
+## 4.0.0-alpha.9
+
+- 🐛 Fix Chrome always taking precedence on Android (Thanks to [@obrand69](https://github.com/obrand69) in [#125](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/125))
+
+## 4.0.0-alpha.8
+
+- 🌹 Allow also `web` versions `0.5.x` again (Thanks to [@Rexios80](https://github.com/Rexios80) in [#118](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/118))
+- 🌹 Improve documentation
+
+## 4.0.0-alpha.7
+
+- 🎉 Enable `ASWebAuthenticationSession.Callback.https` support to fix Universal Links on iOS (Thanks to [@GabrielDamasceno](https://github.com/GabrielDamasceno) in [#117](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/117), related to [#65](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/65) and [#104](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/104))
+- 🌹 Update `web` to `1.x`
+
+## 4.0.0-alpha.6
+
+- 🌹 Allow custom browser priority and rework Android code (Thanks to [@kecson](https://github.com/kecson) in [#111](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/111))
+- 🌹 Enable partial `ASWebAuthenticationSession.Callback` support (related to [#104](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/104))
+
+## 4.0.0-alpha.5
+
+- 💥 Remove Android embedding v1 support (in accordance with Flutter `3.22.0`)
+- 💥 Increase Android min SDK to `21` (in accordance with Flutter `3.22.0`)
+- 💥 Increase Android JVM version to `11` (in accordance with Flutter `3.22.0`)
+- 🌹 Update AndroidX browser to `1.8.0`
+- 🌹 Migrate Android and Web examples to newest standards
+
+## 4.0.0-alpha.4
+
+- 🐛 Fix recursion errors in Flutter `3.22.0`
+- 🌹 Update dependencies (`melos` and `flutter_lints`)
+
+## 3.1.2
+
+- 🐛 Fix recursion errors in Flutter `3.22.0`
+- 🌹 Update `melos` to `5.1.0` to have cleaner CI commands
+
+## 4.0.0-alpha.3
+
+- 🐛 Fix `iframe` approach
+- 🌹 Update `melos` to `5.1.0` to have cleaner CI commands
+
+## 4.0.0-alpha.2
+
+- 🌹 Migrate to `web` package
+
+## 4.0.0-alpha.1
+
+- 🌹 Fix lint for Flutter 3.19.x
+
+## 4.0.0-alpha.0
+
+- 🎉 Add Webview approach for Windows and Linux (Thanks to [@Mino5531](https://github.com/Mino5531) in [#92](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/92))
+
+## 3.1.1
+
+- 🐛 Fix null-safe options (again)
+
+## 3.1.0
+
+- 🎉 Implement `iframe` authentication approach (Thanks to [@rundfunk47](https://github.com/rundfunk47) in [#88](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/88))
+- 🌹 Fix lint for Flutter 3.16.x
+
+## 3.0.4
+
+- 🐛 Fix null-safe options
+
+## 3.0.3
+
+- 🌹 Fix Web implementation not being found properly (See [#82](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/82))
+
+## 3.0.2
+
+- 🌹 Fix deprecations in Gradle 8.x
+
+## 3.0.1
+
+- 🌹 Better null-safe options
+
+## 3.0.0
+
+- 💥 Release next major version, yay!
+- 🐛 Fix Apple implementations
+
+## 3.0.0-alpha.6
+
+- 🐛 Trying a few attempts to fix iOS implementations
+
+## 3.0.0-alpha.5
+
+- 🌹 Fix iOS "screenshot"
+- 🐛 Trying a few attempts to fix iOS and MacOS implementations
+
+## 3.0.0-alpha.4
+
+- 🐛 Trying a few attempts to fix iOS and MacOS implementations
+
+## 3.0.0-alpha.3
+
+- 🌹 Add more entries to the pubspec
+- 🌹 Add reference to `android_intent_plus`
+
+## 3.0.0-alpha.2
+
+- 🎉 Customizable landing page on Windows and Linux
+- 🌹 Update some files from official Flutter template
+
+## 3.0.0-alpha.1
+
+- 🐛 Update platform interface version
+
+## 3.0.0-alpha.0
+
+- 💥 Bump Dart SDK constraints to `>=2.15.0`
+- 💥 Huge refactor with more configuration possibilities
+- 🎉 Add `melos` to project
+- 🌹 Cleanup Android implementation
+
+## 2.2.1
+
+- 🌹 Timeouts (5 minutes) on Web throw real errors now
+
+## 2.2.0
+
+- 🎉 Add fallback for `window.opener` being `null` on Web (See [#58](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/58)) **(See enhanced/better setup instructions for Web in the README!)**
+- 🌹 Add delay to example
+- 🌹 Bring back support for older AGP versions
+- 🐛 Fix `compileOptions` on Android (See [#59](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/59))
+
+## 2.1.5
+
+- 🌹 Fix example support for Dart `3.x`
+- 🐛 Implement protocol handler to supply `ASPresentationAnchor` (See [#51](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/51))
+
+## 2.1.4
+
+- 🌹 Fix support for Dart `3.x`
+- 🌹 Support AGP `8.x` namespace declaration
+- 🌹 Fix web example to work "properly"
+- 🐛 Update `flutter_web_auth_2_platform_interface` to require `2.1.4` at least
+
+## 2.1.3
+
+- 🌹 Add `contextArgs` for web implementations (See [#40](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/40))
+
+## 2.1.2
+
+- 🐛 Downgrade Kotlin to fix some compatibility issues
+
+## 2.1.1
+
+- 🌹 Fix formatting
+
+## 2.1.0
+
+- 🎉 Add support for Linux ([#31](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/31))
+- 🌹 Get rid of dependency on `win32` and `ffi` by using `window_to_front` instead
+- 🌹 Update linter rules
+- 🌹 Update Android dependencies
+
+## 2.0.4
+
+- 🐛 Partially fix ([#135](https://github.com/LinusU/flutter_web_auth/issues/135))
+- 🌹 Support `win32` versions `2.7.0` until `4.x`
+- 🌹 Fix typos in README
+
+## 2.0.3
+
+- 🌹 Add Universal link support ([#26](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/26))
+- 🌹 Some small documentation changes
+
+## 2.0.2
+
+- 🐛 Fix windows callback verification ([#22](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/22))
+- 🐛 Force-update platform interface ([#21](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/21))
+
+## 2.0.1
+
+- 🌹 Merge upstream changes (most notably troubleshooting documentation)
+- 🌹 Added `redirectOriginOverride` for web implementations (By [Rexios80](https://github.com/Rexios80))
+- 🌹 Fix some documentation and changelogs
+
+## 2.0.0
+
+- 💥 Full two-package federated plugin refactor
+
+## 1.1.2
+
+- 🌹 Support `win32` versions `2.7.0` until `3.x`
+
+## 1.1.1
+
+- 🐛 Fix Windows support and support for future platforms
+- 🐛 Fix example on Windows
+- 🌹 `127.0.0.1` is now also a supported callback URL host on Windows
+- 🌹 Cleaned up platform implementations
+
+## 1.1.0
+
+- 🌹 Tested `flutter_web_auth_2` with Flutter `3.3.0`, seems to work!
+- 🌹 Update `win32` to `3.0.0` (relevant only for Windows users)
+- 🌹 Add `android:exported` tag to documentation *before* users start to complain
+- 🌹 Overhauled example layout
+
+## 1.0.1
+
+- 🐛 Remove path dependency
+- 🌹 Add migration guide README
+- 🌹 Add more documentation
+
+## 1.0.0
+
+- 💥 Old project, new maintainers! Due to the lack of updates in the main project, we forked the project and will update it as time passes!
+- 💥 Update to Flutter 3 ([#118](https://github.com/LinusU/flutter_web_auth/pull/118))
+- 💥 Federated plugin refactor ([#98](https://github.com/LinusU/flutter_web_auth/pull/98))
+- 💥 Windows support (By [Jon-Salmon](https://github.com/Jon-Salmon/flutter_web_auth/tree/windows-implementation))
+- 🎉 Add support for ephemeral sessions on MacOS ([#112](https://github.com/LinusU/flutter_web_auth/pull/112))
+
+## 0.4.1
+
+- 🎉 Add support for Flutter "add to app" ([#106](https://github.com/LinusU/flutter_web_auth/pull/106))
+
+## 0.4.0
+
+- 💥 Upgrade to Android V2 embedding ([#87](https://github.com/LinusU/flutter_web_auth/pull/87))
+
+ Migration guide:
+
+ Make sure that you are running a recent version of Flutter before upgrading.
+
+## 0.3.2
+
+- 🎉 Add Web support ([#77](https://github.com/LinusU/flutter_web_auth/pull/77))
+
+## 0.3.1
+
+- 🎉 Add support for Android Plugin API v2 ([#67](https://github.com/LinusU/flutter_web_auth/pull/67))
+- 🎉 Add support for ephemeral sessions ([#64](https://github.com/LinusU/flutter_web_auth/pull/64))
+- 🌹 Avoid deprecated RaisedButton in example ([#75](https://github.com/LinusU/flutter_web_auth/pull/75))
+- 🌹 Cleanup metadata
+
+## 0.3.0
+
+- 💥 Add null safety support ([#60](https://github.com/LinusU/flutter_web_auth/pull/60))
+
+ Migration guide:
+
+ This version drops support for Flutter 1.x, please upgrade to Flutter 2 for continued support.
+
+## 0.2.4
+
+- 🐛 Fix building on iOS ([#36](https://github.com/LinusU/flutter_web_auth/pull/36))
+
+## 0.2.3
+
+- 🐛 Remove NoHistory flag ([#33](https://github.com/LinusU/flutter_web_auth/pull/33))
+- 🐛 Fix building on iOS 8, 9, and 10 ([#29](https://github.com/LinusU/flutter_web_auth/pull/29))
+- 🐛 Always terminate 'authenticate' callbacks on Android ([#28](https://github.com/LinusU/flutter_web_auth/pull/28))
+
+## 0.2.2
+
+- 🐛 Fix propagation of "CANCELED" error on iOS ([#31](https://github.com/LinusU/flutter_web_auth/pull/31))
+
+## 0.2.1
+
+- 🐛 Fix AndroidX build issues ([#27](https://github.com/LinusU/flutter_web_auth/pull/27))
+
+## 0.2.0
+
+- 💥 Add macOS support ([#20](https://github.com/LinusU/flutter_web_auth/pull/20))
+
+ Migration guide:
+
+ This version drops support for Flutter 1.9 and older, please upgrade to Flutter 1.12 for continued support.
+
+## 0.1.3
+
+- 🎉 Update the kotlin plugin version to 1.3.61
+
+## 0.1.2
+
+- 🎉 Add support for iOS 13
+
+## 0.1.1
+
+- 🐛 Add swift_version to the Podspec
+- 🐛 Update Gradle and Kotlin versions
+- 🐛 Add missing link in readme
+
+## 0.1.0
+
+- 🎉 Add initial implementation
diff --git a/third_party/flutter_web_auth_2/LICENSE b/third_party/flutter_web_auth_2/LICENSE
new file mode 100644
index 00000000..02642e58
--- /dev/null
+++ b/third_party/flutter_web_auth_2/LICENSE
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) 2019 Linus Unnebäck
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/third_party/flutter_web_auth_2/README.md b/third_party/flutter_web_auth_2/README.md
new file mode 100644
index 00000000..64031b20
--- /dev/null
+++ b/third_party/flutter_web_auth_2/README.md
@@ -0,0 +1,396 @@
+# Web Auth 2 for Flutter
+
+**This project is a continuation of [flutter_web_auth](https://github.com/LinusU/flutter_web_auth) by Linus Unnebäck with many new features and bug fixes.**
+
+[](https://github.com/invertase/melos)
+
+A Flutter plugin for authenticating a user with a web service, even if the web service is run by a third party. Most commonly used with OAuth2, but can be used with any web flow that can redirect to a custom scheme.
+
+In the background, this plugin uses [`ASWebAuthenticationSession`](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) on iOS 12+ and macOS 10.15+, [`SFAuthenticationSession`](https://developer.apple.com/documentation/safariservices/sfauthenticationsession) on iOS 11, [Chrome Auth Tab](https://developer.chrome.com/docs/android/custom-tabs/guide-auth-tab) on Android and opens a new window on Web. You can build it with iOS 8+, but it is currently only supported by iOS 11 or higher.
+
+
+
+## Usage
+
+Add the following snippet to your `pubspec.yaml` and follow the [Setup guide](#setup):
+
+```yaml
+dependencies:
+ flutter_web_auth_2: ^5.0.0
+```
+
+To authenticate against your own custom site:
+
+```dart
+import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
+
+// Present the dialog to the user
+final result = await FlutterWebAuth2.authenticate(url: "https://my-custom-app.com/connect", callbackUrlScheme: "my-custom-app");
+
+// Extract token from resulting url
+final token = Uri.parse(result).queryParameters['token'];
+```
+
+To authenticate the user using Google's OAuth2:
+
+```dart
+import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
+
+import 'dart:convert' show jsonDecode;
+import 'package:http/http.dart' as http;
+
+// App specific variables
+final googleClientId = 'XXXXXXXXXXXX-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com';
+final callbackUrlScheme = 'com.googleusercontent.apps.XXXXXXXXXXXX-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+
+// Construct the url
+final url = Uri.https('accounts.google.com', '/o/oauth2/v2/auth', {
+ 'response_type': 'code',
+ 'client_id': googleClientId,
+ 'redirect_uri': '$callbackUrlScheme:/',
+ 'scope': 'email',
+});
+
+// Present the dialog to the user
+final result = await FlutterWebAuth2.authenticate(url: url.toString(), callbackUrlScheme: callbackUrlScheme);
+
+// Extract code from resulting url
+final code = Uri.parse(result).queryParameters['code'];
+
+// Construct an Uri to Google's oauth2 endpoint
+final url = Uri.https('www.googleapis.com', 'oauth2/v4/token');
+
+// Use this code to get an access token
+final response = await http.post(url, body: {
+ 'client_id': googleClientId,
+ 'redirect_uri': '$callbackUrlScheme:/',
+ 'grant_type': 'authorization_code',
+ 'code': code,
+});
+
+// Get the access token from the response
+final accessToken = jsonDecode(response.body)['access_token'] as String;
+```
+
+**Note (Google multiple scopes):** To use multiple scopes with Google, you need to encode them as a single string, separated by spaces (`%20`). For example, `scope: 'email https://www.googleapis.com/auth/userinfo.profile'`. Here is [a list of all supported scopes](https://developers.google.com/identity/protocols/oauth2/scopes).
+
+**Note (ephemeral auth):** Due to a [known Chrome bug](https://issuetracker.google.com/issues/444173718), when setting `preferEphemeral: true` on Android with Chrome < 141, the package will launch an auth session with older implementation to avoid crashes.
+
+## Migration
+
+### Upgrading to `5.x`
+
+The following constraints have been added in `5.0.0`:
+- The existing Android approach has been replaced with a new (improved) one (no migration necessary; is automatically used)
+- Android now uses Auth Tab: `httpsHost` and `httpsPath` are now required on Android if you are using a `https` in `callbackUrlScheme`
+- On Android, issues with `taskAffinity`s have been fixed and it is strongly advised to set `android:taskAffinity=""` for all exported `Activity`s (this usually includes your `MainActivity` and `flutter_web_auth_2`'s `CallbackActivity`)
+- Dart SDK `>=3.5.0` is now required (due to migration to melos `7.x`)
+- If you want ephemeral authentication on Android, use `preferEphemeral` instead of `ephemeralIntentFlags` as `intentFlags` have other influences now
+
+### Upgrading to `4.x`
+
+Generally, the following constraints have been added in version `4.0.0`:
+- Android embedding v1 support has been removed (it was deprecated already long ago)
+- Android min SDK and JVM version has been increased to 21 and 11, respectively (in accordance with
+ Flutter `3.22.0`)
+- Migrated away from deprecated iOS and macOS functions (now iOS 17.4 and macOS 14.4 are required!)
+
+Version `4.0.0` also introduced a new approach for Linux and Windows to authenticate users - using
+Webview APIs. Hence, you only need to change your code if you are targeting Linux or Windows.
+If you are fine with still using the old version, here is what you need to change:
+- Pass `useWebview: false` into the options of your call to `authenticate`, like so:
+ ```dart
+ final result = await FlutterWebAuth2.authenticate(
+ url: url,
+ callbackUrlScheme: 'foobar',
+ options: const FlutterWebAuth2Options(useWebview: false),
+ );
+ ```
+
+If you want to use the new approach (**default behaviour!**), you need to do a bit more:
+- Follow the "Getting started" guide of
+ [desktop_webview_window](https://pub.dev/packages/desktop_webview_window#getting-started)
+- Make sure that your users know about the new requirements, as described
+ [here](https://pub.dev/packages/desktop_webview_window)
+
+Last, but not least, version `4.0.0` also added *full* support for Universal links on iOS and macOS!
+In order to do this, two additional options have been added (which are *required* if
+`callbackUrlScheme` is `https`!):
+- `httpsHost` is the host of the callback URL
+- `httpsPath` is the path of the callback URL
+
+### Upgrading to `3.x`
+
+Version `3.0.0` featured a huge refactor which made it possible to maintain even more configuration
+possibilities. Even platform-specific ones! If you want to upgrade, you need to do the following:
+- Follow the [Setup] within this README again for your platform and do it from scratch (there might
+ be changes!)
+- Dart SDK constraints have been updated to `>=2.15.0`.
+- The configuration parameters have been removed from the `authenticate` function. Now, you have to
+ pass a `FlutterWebAuth2Options` object with those options in it instead:
+ - `contextArgs`: This is now called `windowName` within `FlutterWebAuth2Options`.
+ - `redirectOriginOverride`: This is now called `debugOrigin` within `FlutterWebAuth2Options`.
+ - `preferEphemeral`: This has been split into the two named parameters `preferEphemeral` (for
+ iOS and MacOS) and `intentFlags` (for Android) within `FlutterWebAuth2Options`. The former works
+ exactly the same. However, if you want the old behaviour using `preferEphemeral` on Android, use
+ the `ephemeralIntentFlags` constant as value for `intentFlags`. **(THIS WAS REVERTED IN 5.x)**
+
+### Upgrading from `flutter_web_auth`
+
+If you used `flutter_web_auth` correctly (and without extra hackage) before, it should be sufficient to replace the following strings *everywhere* (yes, also in `AndroidManifest.xml` for example):
+- `FlutterWebAuth` -> `FlutterWebAuth2`
+- `flutter_web_auth` -> `flutter_web_auth_2`
+
+If you are using versions `>= 3.0.0`, you also need to follow the migration guide(s) above!
+
+If you are still unsure or something is not working as well as before, please [open a new issue](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/new/choose).
+
+### Built-in KGP/AGP 9+ support
+
+If you need to use built-in Kotlin Gradle plugin or Android Gradle Plugin 9+, use versions `6.x`.
+
+## Setup
+
+Setup is the same as for any Flutter plugin, with the following caveats:
+
+### Android
+
+In order to capture the callback url, the following `activity` needs to be added to your `AndroidManifest.xml`. Be sure to replace `YOUR_CALLBACK_URL_SCHEME_HERE` with your actual callback url scheme.
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+If you are using `http` or `https` as your callback scheme, you also need to specify a host etc.
+See [c:geo](https://github.com/cgeo/cgeo/blob/d7ab67629ac4798adaae194e563afe7df134fcd0/main/AndroidManifest.xml#L164) as an example for this.
+
+### iOS
+
+For "normal" authentication, just use this library as usual; there is nothing special to do!
+
+To authenticate using [Universal Links](https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html)
+on iOS, use `https` as the provided `callbackUrlScheme`:
+
+```dart
+final result = await FlutterWebAuth2.authenticate(url: "https://my-custom-app.com/connect", callbackUrlScheme: "https");
+```
+
+### Web
+
+On the Web platform, an endpoint must be created that captures the callback URL and sends it to the application using the JavaScript `postMessage()` method. In the `./web` folder of the project, create an HTML file named, e.g. `auth.html` with content:
+
+```html
+
+Authentication complete
+Authentication is complete. If this does not happen automatically, please close the window.
+
+```
+
+This HTML file is designed to handle both traditional `window`-based and `iframe`-based authentication flows. The JavaScript code checks the context and sends the authentication response accordingly.
+
+The redirect URL passed to the authentication service must be the same as the URL the application is running on (schema, host, port if necessary) and the path must point to the generated HTML file, in this case `/auth.html`. The `callbackUrlScheme` parameter of the `authenticate()` method does not take this into account, so it is possible to use a schema for native platforms in the code.
+
+For the Sign in with Apple in web_message response mode, postMessage from https://appleid.apple.com is also captured, and the authorisation object is returned as a URL fragment encoded as a query string (for compatibility with other providers).
+
+Additional parameters for the URL open call can be passed in the `authenticate` function using the `windowName` parameter from the options. The `silentAuth` parameter can be used to enable silent authentication within a hidden `iframe`, rather than opening a new window or tab. This is particularly useful for scenarios where a full-page redirect is not desirable. Setting this parameter to `true` allows for a seamless user experience by performing authentication in the background, making it ideal for token refreshes or maintaining user sessions without requiring explicit interaction from the user.
+
+### Windows and Linux
+
+When using `useWebview: false`, there is a limitation that the callback URL scheme must start with `http://localhost:{port}`.
+
+When specifying `useWebview: true` (which is the default behaviour), you need to make sure to follow [desktop_webview_window's guide](https://pub.dev/packages/desktop_webview_window).
+Also be aware that your users might need to install a Webview API (which is preinstalled on Windows 11 and some Windows 10 and Linux installations).
+For details, see also desktop_webview_window's guide above.
+
+## Troubleshooting
+
+When you use this package for the first time, you may experience some problems. These are some of the most common solutions:
+
+### General troubleshooting steps
+
+1. Stop the application if it is running.
+2. Run the following commands:
+ - `flutter clean`
+ - `flutter pub upgrade`
+3. Rerun the application after executing the above commands. Sometimes, they work wonders!
+
+### Troubleshooting `callbackUrlScheme`
+
+- `callbackUrlScheme` must be a valid schema string or else this library won't work
+- A valid RFC 3986 URL scheme must consist of "a letter and followed by any combination of letters, digits, plus "`+`", period "`.`", or hyphen "`-`"
+- scheme = `ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )`
+- This means you can not use underscore "`_`", space "` `" or uppercase "`ABCDEF...`". It must also not start with a number. See [RFC3986#page-17](https://www.rfc-editor.org/rfc/rfc3986#page-17)
+- Examples of VALID `callbackUrlScheme`s are `callback-scheme`, `another.scheme`, `examplescheme`
+- Examples of INVALID `callbackUrlScheme`s are `callback_scheme`,`1another.scheme`, `exampleScheme`
+
+### Troubleshooting Flutter App
+
+- You have to tell the `FlutterWebAuth2.authenticate` function what your `callbackUrlScheme` is.
+- Example: If your `callbackUrlScheme` is `valid-callback-scheme`, your dart code will look like
+
+ ```dart
+ import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
+
+ // Present the dialog to the user
+ final result = await FlutterWebAuth2.authenticate(url: "https://my-custom-app.com/connect", callbackUrlScheme: "valid-callback-scheme");
+ ```
+
+### Troubleshooting Android
+
+- You will need to update your `AndroidManifest.xml` to include the `com.linusu.flutter_web_auth_2.CallbackActivity` activity, something like
+
+ ```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+- Example of a valid `AndroidManifest.xml` with VALID `callbackUrlScheme`. In the example below our `callbackUrlScheme` is `valid-callback-scheme`.
+
+ ```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+- If you are targeting S+ (SDK version 31 and above) you need to provide an explicit value for `android:exported`. If you followed earlier installation instructions, this was not included. Make sure that you add `android:exported="true"` to the `com.linusu.flutter_web_auth.CallbackActivity` activity in your `AndroidManifest.xml` file.
+
+ ```diff
+ -
+ +
+ ```
+
+- If you want to have a callback URL with `http` or `https` scheme, you also need to specify a host etc.
+ See [c:geo](https://github.com/cgeo/cgeo/blob/d7ab67629ac4798adaae194e563afe7df134fcd0/main/AndroidManifest.xml#L164) as an example for this.
+- In older versions of this package, there was a known problem with task affinities and launch modes (see [#113](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/113)). In order to ensure that `flutter_web_auth_2` works correctly on these versions (prior to `5.0.0-alpha.2`), set `android:launchMode="singleTop"` and remove any `android:taskAffinity` entries. This configuration is guaranteed to work. In newer versions, this should not cause problems!
+
+### Troubleshooting OAuth redirects
+
+- Your OAuth Provider must redirect to the valid `callbackUrlScheme` + `://`. This mean if your `callbackUrlScheme` is `validscheme`, your OAuth Provider must redirect to `validscheme://`
+- Example with `PHP`:
+ ```php
+ Go Back to App
+ ```
+
+### Troubleshooting passing data to app
+
+- You can pass data back to your app by adding GET query parameters. This is done by adding a `name=value` type of data after your `callbackUrlScheme` + `://` + `?`
+- Example to pass `access-token` to your app:
+
+ ```text
+ my-callback-schema://?access-token=jdu9292s
+ ```
+
+- You can pass multiple dates by concatenating them with `&`:
+
+ ```text
+ my-callback-schema://?data1=value1&data2=value2
+ ```
+
+- Example to pass `access-token` and `user_id` to your app:
+
+ ```text
+ my-callback-schema://?access-token=jdu9292s&user_id=23
+ ```
+
+- You can get the data in your app through `Uri.parse(result).queryParameters`:
+
+ ```dart
+ // Present the dialog to the user
+ final result = await FlutterWebAuth2.authenticate(url: "https://my-custom-app.com/connect", callbackUrlScheme: "valid-callback-scheme");
+ // Extract token from resulting url
+ String accessToken = Uri.parse(result).queryParameters['access-token'];
+ String userId = Uri.parse(result).queryParameters['user_id'];
+ ```
+
+### Cannot open keyboard on iOS
+
+This seems to be a bug in `ASWebAuthenticationSession` and no workarounds have been found yet. Please see issue [#120](https://github.com/LinusU/flutter_web_auth/issues/120) for more info.
+
+### Error on macOS if Chrome is default browser
+
+This seems to be a bug in `ASWebAuthenticationSession` and no workarounds have been found yet. Please see issue [#136](https://github.com/LinusU/flutter_web_auth/issues/136) for more info.
diff --git a/third_party/flutter_web_auth_2/android/build.gradle b/third_party/flutter_web_auth_2/android/build.gradle
new file mode 100644
index 00000000..380bf8ed
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/build.gradle
@@ -0,0 +1,59 @@
+group = 'com.linusu.flutter_web_auth_2'
+version = '1.0-SNAPSHOT'
+
+buildscript {
+ ext.kotlin_version = '2.1.0'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:8.13.0'
+ }
+}
+
+rootProject.allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+ compileSdk = 36
+
+ if (project.android.hasProperty("namespace")) {
+ namespace = 'com.linusu.flutter_web_auth_2'
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
+
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ minSdk = 21
+ }
+
+ dependencies {
+ implementation 'androidx.browser:browser:1.9.0'
+ implementation 'androidx.activity:activity-ktx:1.10.1'
+ }
+}
+
+// Halkyon's patch (4 Nov 2026): Kotlin built into the Android Gradle plugin
+// (AGP 9, android.builtInKotlin=true) rather than the Kotlin Gradle plugin
+// applied here, as Flutter's guide for plugin authors has it.
+kotlin {
+ compilerOptions {
+ jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11
+ }
+}
diff --git a/third_party/flutter_web_auth_2/android/gradle.properties b/third_party/flutter_web_auth_2/android/gradle.properties
new file mode 100644
index 00000000..94adc3a3
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/third_party/flutter_web_auth_2/android/gradle/wrapper/gradle-wrapper.jar b/third_party/flutter_web_auth_2/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..1b33c55b
Binary files /dev/null and b/third_party/flutter_web_auth_2/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/third_party/flutter_web_auth_2/android/gradle/wrapper/gradle-wrapper.properties b/third_party/flutter_web_auth_2/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..d4081da4
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/third_party/flutter_web_auth_2/android/gradlew b/third_party/flutter_web_auth_2/android/gradlew
new file mode 100644
index 00000000..23d15a93
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/gradlew
@@ -0,0 +1,251 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH="\\\"\\\""
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/third_party/flutter_web_auth_2/android/gradlew.bat b/third_party/flutter_web_auth_2/android/gradlew.bat
new file mode 100755
index 00000000..5eed7ee8
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/gradlew.bat
@@ -0,0 +1,94 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/third_party/flutter_web_auth_2/android/settings.gradle b/third_party/flutter_web_auth_2/android/settings.gradle
new file mode 100644
index 00000000..15aa3ff1
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'flutter_web_auth_2'
diff --git a/third_party/flutter_web_auth_2/android/src/main/AndroidManifest.xml b/third_party/flutter_web_auth_2/android/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..54f16c08
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/third_party/flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/AuthenticationManagementActivity.kt b/third_party/flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/AuthenticationManagementActivity.kt
new file mode 100644
index 00000000..6c52cf93
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/AuthenticationManagementActivity.kt
@@ -0,0 +1,248 @@
+package com.linusu.flutter_web_auth_2
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.util.Log
+import androidx.activity.ComponentActivity
+import androidx.activity.result.ActivityResultLauncher
+import androidx.browser.auth.AuthTabIntent
+import androidx.browser.auth.AuthTabIntent.AuthResult
+import androidx.browser.customtabs.CustomTabsIntent
+
+@SuppressLint("UnsafeOptInUsageError", "UnsafeOptInUsageWarning")
+class AuthenticationManagementActivity : ComponentActivity() {
+ companion object {
+ const val KEY_AUTH_STARTED: String = "authStarted"
+ const val KEY_AUTH_URI: String = "authUri"
+ const val KEY_AUTH_OPTION_INTENT_FLAGS: String = "authOptionsIntentFlags"
+ const val KEY_AUTH_OPTION_TARGET_PACKAGE: String = "authOptionsTargetPackage"
+ const val KEY_AUTH_OPTION_PREFER_EPHEMERAL: String = "authOptionsPreferEphemeral"
+ const val KEY_AUTH_CALLBACK_SCHEME: String = "authCallbackScheme"
+ const val KEY_AUTH_CALLBACK_HOST: String = "authCallbackHost"
+ const val KEY_AUTH_CALLBACK_PATH: String = "authCallbackPath"
+
+ fun createResponseHandlingIntent(context: Context): Intent {
+ val intent = Intent(context, AuthenticationManagementActivity::class.java)
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
+ return intent
+ }
+ }
+
+ private var authStarted: Boolean = false
+ private var hasValidState: Boolean = false
+ private lateinit var authenticationUri: Uri
+ private var intentFlags: Int = 0
+ private var targetPackage: String? = null
+ private var preferEphemeral: Boolean = false
+ private lateinit var callbackScheme: String
+ private var callbackHost: String? = null
+ private var callbackPath: String? = null
+
+ private lateinit var authLauncher: ActivityResultLauncher
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ // Register the activity result launcher
+ authLauncher = AuthTabIntent.registerActivityResultLauncher(this, this::handleAuthResult)
+
+ if (savedInstanceState == null) {
+ extractState(intent.extras)
+ } else {
+ extractState(savedInstanceState)
+ }
+ }
+
+ private fun handleAuthResult(result: AuthResult) {
+ val callback = FlutterWebAuth2Plugin.callbacks[callbackScheme]
+ if (callback == null) {
+ finish()
+ return
+ }
+
+ when (result.resultCode) {
+ AuthTabIntent.RESULT_OK -> {
+ val uri = result.resultUri
+ if (uri != null) {
+ callback.success(uri.toString())
+ } else {
+ callback.error("FAILED", "Authentication returned no URI", null)
+ }
+ }
+
+ AuthTabIntent.RESULT_CANCELED -> {
+ callback.error("CANCELED", "User canceled authentication", null)
+ }
+
+ else -> {
+ callback.error("FAILED", "Authentication failed with code: ${result.resultCode}", null)
+ }
+ }
+
+ FlutterWebAuth2Plugin.callbacks.remove(callbackScheme)
+ finish()
+ }
+
+ override fun onResume() {
+ super.onResume()
+
+ // If we couldn't restore a valid authentication state (e.g. the app process was
+ // killed while the user was completing authentication in an external browser),
+ // extractState() has already finished this activity. Bail out here instead of
+ // touching the not-yet-initialized fields below.
+ if (!hasValidState) {
+ return
+ }
+
+ if (!authStarted) {
+
+ val intentBuilder = if (shouldUseAuthTabs()) {
+ Log.d(LOG_TAG, "Using AuthTabIntent")
+ AuthTabBuilderWrapper(AuthTabIntent.Builder())
+ } else {
+ Log.d(LOG_TAG, "Using CustomTabsIntent")
+ CtBuilderWrapper(CustomTabsIntent.Builder())
+ }
+
+ // Set ephemeral browsing if requested and supported
+ if (preferEphemeral) {
+ try {
+ intentBuilder.setEphemeralBrowsingEnabled(true)
+ Log.d(LOG_TAG, "Ephemeral browsing enabled")
+ } catch (e: Exception) {
+ Log.w(LOG_TAG, "Failed to enable ephemeral browsing: ${e.message}")
+ }
+ }
+
+ val intent = intentBuilder.build()
+
+ intent.intent.addFlags(intentFlags)
+ if (targetPackage != null) {
+ intent.intent.setPackage(targetPackage)
+ }
+
+ try {
+ if (callbackScheme == "https" && callbackHost != null && callbackPath != null) {
+ Log.d(LOG_TAG, "Using https host and path: $callbackHost, $callbackPath")
+ intent.launch(this, authLauncher, authenticationUri, callbackHost!!, callbackPath!!)
+ } else {
+ Log.d(LOG_TAG, "Using custom scheme: $callbackScheme")
+ intent.launch(this, authLauncher, authenticationUri, callbackScheme)
+ }
+ } catch (e: android.content.ActivityNotFoundException){
+ Log.e(LOG_TAG, "Failed to start authentication. No browser available (Activity not found)")
+ val callback = FlutterWebAuth2Plugin.callbacks[callbackScheme]
+ callback?.error("NO_BROWSER", "No valid browser available for authentication.", e.message)
+ FlutterWebAuth2Plugin.callbacks.remove(callbackScheme)
+ finish()
+ } catch (e: SecurityException) {
+ // Some apps register themselves as browsers but do not export their
+ // intent-handling activity; launching the tab then throws instead of
+ // ActivityNotFoundException. Fail the attempt like the no-browser case
+ // rather than crashing the host app.
+ Log.e(LOG_TAG, "Failed to start authentication. Most likely, the selected browser activity is not exported (SecurityException)")
+ val callback = FlutterWebAuth2Plugin.callbacks[callbackScheme]
+ callback?.error("SECURITY_EXCEPTION", "Selected browser cannot be accessed for authentication.", e.message)
+ FlutterWebAuth2Plugin.callbacks.remove(callbackScheme)
+ finish()
+ }
+
+ authStarted = true
+ return
+ }
+ /* If the authentication was already started and we've returned here, the user either
+ * completed or cancelled authentication.
+ * Either way we want to return to our original flutter activity, so just finish here
+ */
+ finish()
+ }
+
+ fun shouldUseAuthTabs(): Boolean {
+
+ if (!preferEphemeral || targetPackage == null) return true
+ val packageMajorVersion = getInstalledVersion(targetPackage!!)?.substringBefore(".")?.toIntOrNull() ?: 0
+ Log.d(LOG_TAG, "Chosen package: $targetPackage with version: $packageMajorVersion")
+
+ val chromePackages = setOf(
+ PackageNames.CHROME_STABLE,
+ PackageNames.CHROME_BETA,
+ PackageNames.CHROME_DEV,
+ )
+
+ if (chromePackages.contains(targetPackage)) {
+ return packageMajorVersion >= 141
+ } else if (targetPackage == PackageNames.MICROSOFT_EDGE) {
+ return packageMajorVersion >= 141
+ } else if (targetPackage == PackageNames.SAMSUNG_INTERNET) {
+ return packageMajorVersion >= 28
+ } else if (targetPackage == PackageNames.FIREFOX) {
+ return packageMajorVersion >= 143
+ }
+
+ return true
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ outState.putBoolean(KEY_AUTH_STARTED, authStarted)
+ outState.putParcelable(KEY_AUTH_URI, authenticationUri)
+ outState.putInt(KEY_AUTH_OPTION_INTENT_FLAGS, intentFlags)
+ outState.putString(KEY_AUTH_OPTION_TARGET_PACKAGE, targetPackage)
+ outState.putBoolean(KEY_AUTH_OPTION_PREFER_EPHEMERAL, preferEphemeral)
+ outState.putString(KEY_AUTH_CALLBACK_SCHEME, callbackScheme)
+ outState.putString(KEY_AUTH_CALLBACK_HOST, callbackHost)
+ outState.putString(KEY_AUTH_CALLBACK_PATH, callbackPath)
+ }
+
+ private fun extractState(state: Bundle?) {
+ if (state == null) {
+ finish()
+ return
+ }
+
+ val scheme = state.getString(KEY_AUTH_CALLBACK_SCHEME)
+ val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ state.getParcelable(KEY_AUTH_URI, Uri::class.java)
+ } else {
+ @Suppress("deprecation")
+ state.getParcelable(KEY_AUTH_URI)
+ }
+
+ if (uri == null || scheme == null) {
+ // This can happen when Android recreates this activity from an incomplete
+ // saved-state Bundle after the app's process was killed (e.g. low memory)
+ // while the user was completing authentication in an external browser.
+ // Finish gracefully instead of crashing the host app, and resolve any
+ // still-pending callback with an error so callers don't hang forever.
+ Log.e(
+ LOG_TAG,
+ "Unable to restore authentication state (missing authUri and/or " +
+ "callbackScheme), likely due to process death. Finishing gracefully"
+ )
+ if (scheme != null) {
+ FlutterWebAuth2Plugin.callbacks[scheme]?.error(
+ "CANNOT_RESTORE",
+ "Authentication session was lost, likely because the app was killed in the background. Please try again.",
+ null
+ )
+ FlutterWebAuth2Plugin.callbacks.remove(scheme)
+ }
+ finish()
+ return
+ }
+
+ authStarted = state.getBoolean(KEY_AUTH_STARTED, false)
+ authenticationUri = uri
+ intentFlags = state.getInt(KEY_AUTH_OPTION_INTENT_FLAGS, 0)
+ targetPackage = state.getString(KEY_AUTH_OPTION_TARGET_PACKAGE)
+ preferEphemeral = state.getBoolean(KEY_AUTH_OPTION_PREFER_EPHEMERAL, false)
+ callbackScheme = scheme
+ callbackHost = state.getString(KEY_AUTH_CALLBACK_HOST)
+ callbackPath = state.getString(KEY_AUTH_CALLBACK_PATH)
+ hasValidState = true
+ }
+}
diff --git a/third_party/flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/CallbackActivity.kt b/third_party/flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/CallbackActivity.kt
new file mode 100644
index 00000000..520d17de
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/CallbackActivity.kt
@@ -0,0 +1,48 @@
+package com.linusu.flutter_web_auth_2
+
+import android.app.Activity
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+
+class CallbackActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val url = intent?.data ?: fixAutoVerifyNotWorks(intent)
+ val scheme = url?.scheme
+
+ if (scheme != null) {
+ FlutterWebAuth2Plugin.callbacks.remove(scheme)?.success(url.toString())
+ }
+ startActivity(AuthenticationManagementActivity.createResponseHandlingIntent(this))
+ finish()
+ }
+
+
+ /** Fix sometimes android:autoVerify="true" cannot works when it can't access Google after installation.
+ * See https://stackoverflow.com/questions/76383106/auto-verify-not-always-working-in-app-links-using-android
+ *
+ * must register in AndroidManifest.xml :
+ *
+ *
+ *
+ *
+ *
+ */
+ private fun fixAutoVerifyNotWorks(intent: Intent?): Uri? {
+ if (intent?.action == Intent.ACTION_SEND && "text/plain" == intent.type) {
+ return intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
+ try {
+ //scheme://host/path#id_token=xxx
+ return Uri.parse(it)
+ } catch (e: Exception) {
+ return null
+ }
+ }
+ }
+ return null
+ }
+
+}
diff --git a/third_party/flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/FlutterWebAuth2Plugin.kt b/third_party/flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/FlutterWebAuth2Plugin.kt
new file mode 100644
index 00000000..5569e002
--- /dev/null
+++ b/third_party/flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/FlutterWebAuth2Plugin.kt
@@ -0,0 +1,165 @@
+package com.linusu.flutter_web_auth_2
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import androidx.browser.customtabs.CustomTabsClient
+
+import io.flutter.embedding.engine.plugins.FlutterPlugin
+import io.flutter.embedding.engine.plugins.activity.ActivityAware
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
+import io.flutter.plugin.common.BinaryMessenger
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler
+import io.flutter.plugin.common.MethodChannel.Result
+
+class FlutterWebAuth2Plugin(
+ private var context: Context? = null,
+ private var channel: MethodChannel? = null,
+ private var activity: Activity? = null,
+) : MethodCallHandler, FlutterPlugin, ActivityAware {
+ companion object {
+ val callbacks = mutableMapOf()
+ }
+
+ private fun initInstance(messenger: BinaryMessenger, context: Context) {
+ this.context = context
+ channel = MethodChannel(messenger, "flutter_web_auth_2")
+ channel?.setMethodCallHandler(this)
+ }
+
+ override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
+ initInstance(binding.binaryMessenger, binding.applicationContext)
+ }
+
+ override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
+ context = null
+ channel = null
+ }
+
+ override fun onMethodCall(call: MethodCall, resultCallback: Result) {
+ when (call.method) {
+ "authenticate" -> {
+ val url = Uri.parse(call.argument("url"))
+ val callbackUrlScheme: String = call.argument("callbackUrlScheme")!!
+ val options = call.argument