LinusU / flutter_web_auth

Flutter plugin for authenticating a user with a web service
MIT License
198 stars 176 forks source link

iOS 8.0+ compatibility #19

Closed eesayas closed 3 years ago

eesayas commented 4 years ago

Can the package be modified to run on iOS 8.0+

LinusU commented 4 years ago

We could potentially add in support for iOS 9.0+ by using SFSafariViewController 🤔

iOS 9 is supported on the same devices as iOS 8, are you sure that you need iOS 8 support?

eesayas commented 4 years ago

I am trying to implement SFSafariViewController but I'm having trouble present/pushing it.

present and presentViewController are unresolved.

eesayas commented 4 years ago

I got it to work using an extension

extension UIApplication {
    class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController {
            return topViewController(base: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController {
                return topViewController(base: selected)
            }
        }
        if let presented = base?.presentedViewController {
            return topViewController(base: presented)
        }
        return base
    }
}

and this is how I call presentViewController

UIApplication.topViewController()?.present(safari, animated: true, completion: nil)

but I'm having trouble defining the completionHandler since it seems that I can't just plugin in the exisiting one

eesayas commented 4 years ago

Current problems

  1. I can't seem to figure out how to handle callback to the app
  2. How do I get the response url from the auth
Niggelgame commented 4 years ago

I think you can use:

(at the top:)

var accountResult: FlutterResult?

Then set the else to

else if #available(iOS 11, *)

and add a new else

in this you could put this:

let vc = SFSafariViewController(url: url)
                guard let provider = UIApplication.shared.delegate?.window??.rootViewController as? FlutterViewController else {
                    result(FlutterError(code: "FAILED", message: "Failed to aquire root FlutterViewController" , details: nil))
                    return
                }
                provider.present(vc, animated: true, completion: nil)

to show it. Then to get the callback you could use an url-scheme, just like for the other ones.

I thought about something like this:

public func application(_ application: UIApplication,
                                     open url: URL, sourceApplication: String?, annotation: Any) -> Bool {

            guard let provider = UIApplication.shared.delegate?.window??.rootViewController as? FlutterViewController else {
                return true
            }
            provider.dismiss(animated: true)
            accountResult!(url.absoluteString)

    }

But for some reason it won't perform the open-url.

I tried it on an iPhone 4s with iOS 9.3.5.

If somebody figures out how to let the "open url" receive the URL-Scheme, i would really appreciate an answer and create the fitting PR.

Niggelgame commented 4 years ago

I just created a PR #29 . It enables building with iOS 8, but you need to pack the authenticate into a try catch block, because it will throw an Exception if it's tried by running it from iOS 8-10. I recommend using device_info to check the version String before.

I personally use it to realise Sign in with Apple on all platforms, and to give build possibility to those users too.

LinusU commented 3 years ago

This was fixed in 🚢 0.2.3 / 2020-05-11