Automatically Signing A User In With Firebase iOS

This tutorial will look at a nice way to handle user sign in with Firebase. More specifically – automatically sign them in on a device they have previously logged in on. For example, we don’t want to present a login screen each time the user opens the app. If they have logged in previously, then the app should probably do this automatically (perhaps with the exception of something like a banking app).

This isn’t going to deal with the ins and outs of using Firebase Authentication. There is a separate tutorial on that here (coming soon).

The first thing I’m going to say right at the start is…We do not need to store anything about the users login details in User Defaults, the Keychain or anywhere else. Firebase takes llre of saving an authenticated user for us. 

Secondly, this is only a way of doing it. As always there are lots of ways, but I’m using this particular setup in a current project and it’s working very nicely thus far. So lets discuss the setup.

Overview

The first view controller of our app is called AppContainerViewController. This will always be the first view controller of our application, regardless of whether or not a user has signed in. This view controller will then display the relevant view controller. This will either be a LoginViewController or (for this example) MainViewController, but this could be whatever it needs to be for your particular application.

The brains of the setup is another class called AppManager. This will be a singleton that will figure out which view controller to display. It will also be responsible for signing out a user and returning them to the login screen (via the AppContainerViewController). The nice thing about this setup is you can call this logout for anywhere inside your app and it will work just fine.

Lets get started!

The AppManager Class

Create a new swift file and call it ‘AppManager’. This is going to be a singleton. Without going into singleton classes too much, the main thing here is that the initialiser should be private, and the class itself should have a shared instance of itself. Paste the following into your new file, overwriting everything that was there.

The shared instance of the object is the only way we can interact with it’s methods and properties. By marking the init as private, we can’t access it from anywhere else in our app. If you tried to create an instance of this AppManager object from your view controller for example, you’d see the following error: AppManager’ initializer is inaccessible due to ‘private’ protection level.

To use this object our code will look like this: AppManager.shared.someMethod()

If you have some experience with iOS then this might look familiar to you. The AppDelegate, NotificationCenter and UserDefaults are just some of the common objects that Apple choose to setup in a similar way.

This object is going to have just two methods, and importantly hold a reference to the AppContainerViewController we talked about earlier. Go ahead and add the following inside the class, we’ll flesh them out in a little while.

The AppContainerViewController

Head over the the ViewController class that came with your project and rename the class to AppContainerViewController. This class is very simple, replace everything in the file with the following:

Yep, that’s the whole class.

You’ll also need to go and add the appContainer property to your AppManager class. Add the following line under the private init:

A few important things are happening here.

  • We’re making use of the viewDidAppear method not viewDidLoad. We want the AppManagers showApp method to be called every time it appears, not just when it loads.
  • We’re setting the appContainer property of your AppManager to the instance of the AppContainerViewController by passing in self.
  • Finally you’re calling the AppManagers showApp method. This is the method that will be responsible for showing the relevant view controller. Lets go and flesh out that method now.

AppManager’s showApp Method

Heading back to the AppManager class, fill in the showApp method so it looks like the following:

This is the part of the code that actually does the check. We call the Auth component of Firebase and ask for the currentUser property. This optional property is nil if no user has previously logged in or if the Auth signout method has been called. From the docs:

“Synchronously gets the cached current user, or null if there is none.”

Now we can make a decision about what view controller should be presented. In this case we’re using the instantiateViewController(withIdentifier: ) method. You’ll need to head over to your storyboard and give identifiers to the relevant view controllers. “LoginViewController” to the view controller that a user can login with and “MainViewController” to the view controller that will be the main part of your application.

Logging Out

Replace your AppManagers logout method with the following:

The first line simply signs the user out from Firebase. The second line is where the nice flexibility comes from with this setup. You can call AppManager.shared.logout() from anywhere in your application. Everything should slide out and then the login screen will be presented. Nice! :]