MaikuB / flutter_appauth

A Flutter wrapper for AppAuth iOS and Android SDKs
269 stars 239 forks source link

[flutter_appauth][flutter_appauth_platform_interface] Ability to programmatically close login flow in iOS #398

Open viplavrawal opened 1 year ago

viplavrawal commented 1 year ago

I needed a way to programmatically close the login flow. In android this was could be done using Navigator.pop, but for iOS, this was not possible.

This PR saves the OIDExternalUserAgent and FlutterResult in FlutterAppAuthPlugin.m so that a new method call (cancelAuthorization) can later close the login window and return the result.

MaikuB commented 1 year ago

Thanks for the PR and apologies for late response. Are you able to elaborate more on the use case for this? For example, can you explain you've been realistically being using this in your own app? Trying to get a better understanding as a login flow is typically a modal one so that means the login flow blocks interacting with the application's UI. Even so, a user can back out of the login flow of their own. The only example I was able to come up so far was that perhaps a timer happening in the background that will cancel the login flow. If so, IMO this is a potentially worse UX as the user may just be taking longer to go through the flow or this might be cancelling the login flow the user intentionally started and could violate this principle.

FYI another thing I've seen is on Android popping via navigator doesn't work. I'm not surprised by this as the navigator is a Flutter specific API. Login flows on Android use Chrome custom tabs and these are displayed in "front" of the Flutter application. In the case of the example app, when I made changes to try to test this out, the Chrome custom tab remained after the pop call and that took place is the same expected behaviour of calling pop() within the app even when there isn't a Chrome custom tab. Based on what I understand you're trying to do, unless AppAuth Android SDK exposes an API to dismiss the Chrome custom tab then I don't believe it's possible to achieve what you're after. I've attached a video of the example app running on Android for reference

https://user-images.githubusercontent.com/25263378/229245764-79c0f7bb-0677-4c51-9d63-b2d1ca15e1d2.mov

viplavrawal commented 1 year ago

Hi @MaikuB Thanks for your reply.

In our application, we have the forgot password flow which starts from within the webPage. If the user clicks on forgot password, they will receive a mail. In the mail, there's a link to create a new password, after which there's a deepLink which should take the user back to the login screen of the app. When this deepLink is triggered, we want to close the browser window from flutter code.

For android, just resetting the page stack with Navigator.popUntil(context, ModalRoute.withName('/')); closes the browser window, but the same doesn't happen for iOS, for which we had to make these changes in our code.

Please let me know if I can help in any other way. Thanks

noskova commented 1 year ago

Hi @MaikuB! Just wanted to add that I also need this option very much for the same case (user clicks Forgot password in in-app web browser, receives email, returns to the app from an email through a deepLink and I need to close web browser at this moment in order user is able to see the app screen they need (because otherwise it is below web browser). Hope you decide to merge it.

MaikuB commented 1 year ago

@noskova how would you solve the issue on Android then as the PR only has changes for iOS? Note that it will also throw an UnimplementedError on Android due to this as well. @viplavrawal talks about how they were able to use the Navigator API but that is specific Flutter and wouldn't close the Chrome Custom Tab on Android. However, your post would indicate that you're aware of how using navigation only affects the app that is hidden underneath the browser. I uploaded a video in my previous post (note: it had the wrong recording before but that is fixed) to show that popping wouldn't work and makes sense that it wouldn't given that is a Flutter-specific API

FYI in case you weren't aware, you can also reference @viplavrawal to make use of the changes to see how it works in your own app.