Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to wait oauth callback for triggering handleRedirectURL #398

Open
cgkronos opened this issue Sep 15, 2022 · 1 comment
Open

How to wait oauth callback for triggering handleRedirectURL #398

cgkronos opened this issue Sep 15, 2022 · 1 comment

Comments

@cgkronos
Copy link

cgkronos commented Sep 15, 2022

Now, I've another issue:
I've those methods

func runOauth(){
        self.loadingLabel.isHidden=true
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.oauth2!.afterAuthorizeOrFail = self.callBackOAuth

        var url:URL?
        do{
            //the url for authorizing the user, kronos://oauth/callback" is called after the OAuth finish
            
            url = try appDelegate.oauth2!.authorizeURL(withRedirect:"kronos://oauth/callback", scope: "auth",params: ["tg":"addon/kronos/main","idx":"login.OAuth","formId":"iOS"])
            do{
                let authorizer = appDelegate.oauth2!.authorizer as! OAuth2Authorizer
                //launch OAuth in embeded view "SafariVC"
                print("Safari embeded" + url!.absoluteString)
                
                safariVC = try authorizer.authorizeSafariEmbedded(from: self,at: url!)
                
            }catch let error {
                DispatchQueue.main.async {
                    print("ERROR authorizing\(error)")
                    //self.runOauth()
                }
            }
        }catch let error {
            DispatchQueue.main.async {
                print("ERROR creating OAuth URL \(error)")
                //self.runOauth()
            }
        }
    }
func callBackOAuth(authParameters:OAuth2JSON!, error: OAuth2Error!){
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        print("Callback")
        if (error ==  nil && appDelegate.oauth2!.accessToken != nil){//OAuth succeed in
            
            //we store the token and its experation date in keychain
            print("OAuth succeed")
            self.keychain!.set(appDelegate.oauth2!.accessToken!,forKey:"Token")
            //self.keychain!.set(appDelegate.oauth2!.refreshToken!,forKey:"RefreshToken")
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let myString = formatter.string(from: appDelegate.oauth2!.accessTokenExpiry!)
            self.keychain!.set(myString,forKey:"ExpiryDate")
            self.loadingLabel.isHidden=false
            
            appDelegate.reloadView()
        }else if (error !=  nil){//OAUth failed
            print("OAuth error \(String(describing: error))")
        }else{//Another error
            print("Cannot login")
            self.showMessage(msg: "Login error", title: "Error")
            self.runOauth()
        }
    }

and in AppDelegate

func application(_ app: UIApplication,
                  open url: URL,
                  options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
        // you should probably first check if this is the callback being opened
            // if your oauth2 instance lives somewhere else, adapt accordingly
        let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
        let site=components?.host
        print("Application")
        if site == "oauth"{//OAuth terminated
            if components?.path == "/callback" {
                let viewController = self.window?.rootViewController as! ViewController
                print("oauth")
                self.oauth2!.handleRedirectURL(url)
                viewController.hideSafariView()
            }
        }

        return true
    }

My issue is that as I trigger runOauth like that it happens that application is called before callBackOAuth so after oauth viewDidAppear is recalled but with keychain token not set, so here is a way to "wait" in application that token is not nil

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        //initialize OAuth2 config parameters
        appDelegate.oauth2 = OAuth2CodeGrant(settings: OAuthParams  )
        appDelegate.oauth2!.authConfig.authorizeContext = KronosWebsite?.window
        appDelegate.oauth2!.useKeychain = false
        appDelegate.oauth2!.authConfig.authorizeEmbeddedAutoDismiss = true

        appDelegate.oauth2!.logger = OAuth2DebugLogger(.debug)
        appDelegate.oauth2!.afterAuthorizeOrFail = self.callBackOAuth
        appDelegate.oauth2!.verbose = true
        
        
        
        //try to load the Token from keychain
        let token=self.keychain!.get("Token")
        
        if(token == nil){//no token found, we launch the OAuth
            print("no token yet")
            runOauth()
        } 

EDIT: I've tried to use a DispatchGroup with no success:

groupOauth.enter() in runOauth

groupOauth.leave() in callBackOAuth

and in AppDelegate::application

 viewController.groupOauth.notify(queue: DispatchQueue.main) {
    self.oauth2!.handleRedirectURL(url)
    viewController.hideSafariView()
}
@cgkronos
Copy link
Author

I've a solution by deporting the call of the URL which logs the user (with the Oauth token stored in keychain) from viewDidAppear to viewDidLoad

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant