Flutter url_launcher (inAppBrowser) with a redirect back to iOS app

  Kiến thức lập trình

My login flow for oauth on iOS works using universal applinks, when accessed via url_launcher with mode = external e.g.

if (!await launchUrl(
  Uri.parse('$myAPI/$myAPIVersion/google/login?return_url=https://example.com/token'),
  mode: LaunchMode.externalApplication
  )) {
    throw Exception('Could not launch');
  }

However, Apple rejects the mode = external pattern for login flows, in favour of an in-app browser (e.g. Safari View Controller).

The url_launcher plugin provides support for in-app browsers, but I can’t see how you can get them to work for this use case.

I see 2x obvious approaches, but neither of them work..

1. Universal links

e.g.

// link to a universal link via https
if (!await launchUrl(
  Uri.parse('$myAPI/$myAPIVersion/google/login?return_url=https://example.com/token'),
  mode: LaunchMode.inAppBrowserView // use safariVC
  )) {
    throw Exception('Could not launch');
  }

This fails because a universal link is not detected in the redirect – the user is not returned to the app and ends up staying in safari.

2. Custom scheme links

e.g.

Define a custom scheme to be more explicit about the intended destination of the redirect.

Define scheme:

<key>CFBundleURLTypes</key>
<array>
  <dict>
      <key>CFBundleURLName</key>
      <string>com.example.app</string>
      <key>CFBundleURLSchemes</key>
      <array>
          <string>myscheme</string>
      </array>
  </dict>
</array>

Use it:

// link via myscheme
if (!await launchUrl(
    Uri.parse('$myAPI/$myAPIVersion/google/login?return_url=myscheme://token'),
    mode: LaunchMode.inAppBrowserView // use safariVC
  )) {
    throw Exception('Could not launch');
  }

But this results in an error:

flutter: PlatformException(Error, Error while launching https://api.example.com/v1/google/login?return_url=myscheme://token, null, null)
flutter:
#0      UrlLauncherIOS._failedSafariViewControllerLoadException (package:url_launcher_ios/url_launcher_ios.dart:168:5)
#1      UrlLauncherIOS._mapInAppLoadResult (package:url_launcher_ios/url_launcher_ios.dart:142:15)
#2      UrlLauncherIOS.launchUrl (package:url_launcher_ios/url_launcher_ios.dart:93:14)

Any ideas or alternate approaches? (would prefer to avoid the manual “click this button to return to the app” approach, if possible).

I also note that I tried using flutter_custom_tabs, which allowed the login flow to complete as expected using a custom scheme, but then get stuck with the browser open at the end of the flow.


Related questions that are not dupes:

  • Navigate back to app from url_launcher webview – Flutter – Android (specifically about WebView – which is not suitable for OAuth flows)
  • url_launcher not opening app on iOS but works on Android in flutter (specifically about canLaunch)
  • iOS redirect back to apps (specific to swift and a particular business case)

LEAVE A COMMENT