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)