From a2747b3f21411b338aa5b966d284011c13f82517 Mon Sep 17 00:00:00 2001 From: bhush2003 Date: Tue, 18 Aug 2026 06:55:21 +0530 Subject: [PATCH] solve issue #256 --- lib/services/account.dart | 17 +++++++++++++++-- lib/src/client_io.dart | 20 +++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/lib/services/account.dart b/lib/services/account.dart index 3b8fbded..908ab8f3 100644 --- a/lib/services/account.dart +++ b/lib/services/account.dart @@ -1033,8 +1033,15 @@ class Account extends Service { final String apiPath = '/account/sessions/oauth2/{provider}' .replaceAll('{provider}', provider.value); + // Do NOT forward the custom success URL to the server. + // The server only appends key/secret to the redirect when the success path + // matches its internal default (/auth/oauth2/success). Sending a custom URL + // causes the server to skip adding key/secret, so the Flutter webAuth + // callback never receives them → "Invalid OAuth2 Response" (500). + // Let the server use its default success path so key/secret are always + // added. The custom success URL is used only as the callbackUrlScheme so + // Flutter can intercept the redirect after key/secret have been appended. final Map params = { - if (success != null) 'success': success, if (failure != null) 'failure': failure, if (scopes != null) 'scopes': scopes, 'project': client.config['project'], @@ -1369,8 +1376,14 @@ class Account extends Service { final String apiPath = '/account/tokens/oauth2/{provider}' .replaceAll('{provider}', provider.value); + // Do NOT forward the custom success URL to the server. + // The server (account.php) only appends userId/secret to the redirect + // when the success path matches its internal default. Sending a custom + // URL causes the server to skip adding them → "Invalid OAuth2 Response" + // (500) or "Invalid success param" (400) if the URL is not registered. + // Let the server use its default path; use the custom success URL only + // as the callbackUrlScheme so Flutter can intercept the redirect. final Map params = { - if (success != null) 'success': success, if (failure != null) 'failure': failure, if (scopes != null) 'scopes': scopes, 'project': client.config['project'], diff --git a/lib/src/client_io.dart b/lib/src/client_io.dart index c675f9e1..1c6eda5d 100644 --- a/lib/src/client_io.dart +++ b/lib/src/client_io.dart @@ -479,11 +479,25 @@ class ClientIO extends ClientBase with ClientMixin { @override Future webAuth(Uri url, {String? callbackUrlScheme}) { + // Derive the actual URI scheme to listen for. + // If the caller passed a full URL (e.g. "https://myapp.com/callback"), + // extract just the scheme ("https"). Otherwise use it as-is if it looks + // like a bare scheme, or fall back to the default appwrite-callback scheme. + String resolvedScheme = "appwrite-callback-${config['project']!}"; + if (callbackUrlScheme != null && _customSchemeAllowed) { + final parsed = Uri.tryParse(callbackUrlScheme); + if (parsed != null && parsed.hasScheme && parsed.host.isNotEmpty) { + // full URL passed — use just the scheme portion + resolvedScheme = parsed.scheme; + } else { + // bare scheme passed (e.g. "myapp") — use as-is + resolvedScheme = callbackUrlScheme; + } + } + return FlutterWebAuth2.authenticate( url: url.toString(), - callbackUrlScheme: callbackUrlScheme != null && _customSchemeAllowed - ? callbackUrlScheme - : "appwrite-callback-${config['project']!}", + callbackUrlScheme: resolvedScheme, options: const FlutterWebAuth2Options( useWebview: false, ),