Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase - iOS Swift: FIRAuth.auth().signOut() not signing out current user

I'm building an app using Firebase with an initial SignInViewController that loads a sign in page for users to authenticate with email which triggers the following methods:

@IBAction func didTapSignIn(sender: AnyObject) {
    let email = emailField.text
    let password = passwordField.text
    FIRAuth.auth()?.signInWithEmail(email!, password: password!) { (user, error) in
        if let error = error {
            print(error.localizedDescription)
            return
        }
        self.signedIn(user!)
    }
}

func signedIn(user: FIRUser?) {
    AppState.sharedInstance.displayName = user?.displayName ?? user?.email
    AppState.sharedInstance.signedIn = true
    NSNotificationCenter.defaultCenter().postNotificationName(Constants.NotificationKeys.SignedIn, object: nil, userInfo: nil)
    performSegueWithIdentifier(Constants.Segues.SignInToHome, sender: nil)
}

The SignInViewController also checks if there is a cached current user when the app launches and, if so, signs that user in:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(true)
    //Synchronously gets the cached current user, or null if there is none.
    if let user = FirebaseConfigManager.sharedInstance.currentUser {
        self.signedIn(user)
    }
}

Once the user is signed in, the app segues to a HomeScreenViewController which displays a "Sign Out" button at the top left of the navigation bar. When a user taps the "Sign Out" button, that user is supposed to get signed out and the app should segue back to the SignInViewController with the following method:

@IBAction func didTapSignOut(sender: UIBarButtonItem) {
    print("sign out button tapped")
    let firebaseAuth = FIRAuth.auth()
    do {
        try firebaseAuth?.signOut()
        AppState.sharedInstance.signedIn = false
        dismissViewControllerAnimated(true, completion: nil)
    } catch let signOutError as NSError {
        print ("Error signing out: \(signOutError)")
    } catch {
        print("Unknown error.")
    }
}

When I tap the "Sign out" button, the didTapSignOut method gets called and gets executed. However, after the try firebaseAuth?.signOut() line of code gets executed, the current user should be nil. But when I print out the current user in the Xcode console, the current user is still logged in:

po FIRAuth.auth()?.currentUser
▿ Optional<FIRUser>
  - Some : <FIRUser: 0x7fde43540f50>

Since the current user doesn't get signed out after firebaseAuth?.signOut() gets called, once the app segues back to the SignInViewController the app still thinks there is a cached current user so that user gets signed in again.

Could this be a Keychain issue?

Does it have to do with NSNotificationCenter.defaultCenter().postNotificationName being called?

My code comes directly from the Google Firebase Swift Codelab so I'm not sure why it's not working: https://codelabs.developers.google.com/codelabs/firebase-ios-swift/#4

like image 384
alexisSchreier Avatar asked Sep 02 '16 23:09

alexisSchreier


2 Answers

You can add a listener in your viewDidAppear method of your view controller like so:

FIRAuth.auth()?.addStateDidChangeListener { auth, user in
    if let user = user {
        print("User is signed in.")
    } else {
        print("User is signed out.")
    }
}

This allows you to execute code when the user's authentication state has changed. It allows you to listen for the event since the signOut method from Firebase does not have a completion handler.

like image 116
Nick Kohrn Avatar answered Nov 14 '22 22:11

Nick Kohrn


GIDSignIn.sharedInstance().signOut()
like image 34
ChavirA Avatar answered Nov 14 '22 22:11

ChavirA