Simple Login Flow in Flutter, then Firebase

Part One: Implementing the login flow without Firebase to build a baseline application for those not using Firebase

In this piece, we will create a simple application with the following components:

  • Default Main App Entry Point
  • Use of FutureBuilder Widget to wait for data before rendering UI, the concept used throughout the app
  • Login Page
  • Home Page
  • Authentication Service
  • Demonstrate the use of the Provider as discussed in the Flutter Documentation Simple App State Management

There are plenty of examples online about setting up Firebase for Flutter so I will jump right into the code instead of walking thru the basics.

See Google CodeLabs Flutter for Firebase for step-by-step instructions for setting up you project on iOS or Android

Create a Test User in Firebase

Since we are just building the application and there is no functionality to create users right now, log in to you Firebase Console and add a user to your project. Be sure to enable email authentication when updating the project in your Firebase Console.


Cleaning Up the Default Flutter Project

First, let's create the project:

flutter create simple_firebase_auth

Now let's do some project cleanup, open up the project and delete the existing HomePage and HomePageState widget from the file main.dart.

Change the home property of the MaterialApp widget to point to the LoginPage widget we are about to create in the next section.

The file should look similar to this when completed:


Create the Login Page Widget

Let's walk through the creation of the LoginPage for the application. We need to capture an email and a password to pass to the AuthService to call the login function.

We are going to create a simple page with the required TextFormField widgets and one RaisedButton that will log a user in when clicked.

  1. Open your editor and create a new file in the lib directory named login_page.dart
  2. Paste the contents below into the file login_page.dart

You should be able to run the code to see what the screen looks like now. Be sure to change the default route or home property in main.dart widget to LoginPage while we work through the UI so you can see the changes update live.


Style and Adding Text Fields

Let's make the body of the page a centered Column with the children of the column being primarily the TextFormField and the RaisedButton.

The centered container to hold the form fields and buttons:

Next, add the actual form field widgets and the buttons as children of the Column widget. We will do some basic styling of the form fields so that this looks presentable. See the Flutter documentation for more information on TextFormFields.

Let’s add some spacing between the fields in the column so it is more presentable. We are going to use the SizedBox widget and set the height property to get some spacing in the application. Replace the children property of the Column widget to get the desired spacing.


Getting Text Values from Form Fields

We are going to be using a Form widget and a GlobalKey, additional information on these concepts can be found in the flutter cookbook section Building a form with validation.

Add the formKey in the LoginPage widget:

Then add two new fields to hold the email address and password values we will need to send to Firebase for authentication:

Next, add a property onSaved to the TextFormFields we have for email and password. When the save method is called on the form, all of the widgets onSaved methods will be called to update the local variables.

Wrap the Column widget with a new Form widget, the code should look similar to this:

Now that the fields are set and the TextFormField are updated, we can use the _formKey to not only validate the fields provided but also retrieve the values locally by calling the save method.

Replace the code in the RaisedButton onPressed method to the following, and you will see that we are getting the values for email and password set in out widget. We can now pass these values to the AuthService that wraps the Firebase sign-in functionality.


Create the Home Page Widget

For now, we will keep the home page simple, since our goal is to demonstrate how the flow works. Ignore the commented out LogoutButton widget, we will discuss that in a later section of the tutorial.

  1. Open your editor and create a new file in the lib directory named home_page.dart
  2. Paste the contents below into the file home_page.dart

3. Open main.dart and add the following import statement

4. To verify that the page is working properly, change the home property from this:

To this:


Creating a Template for an Authentication Service

Here we will build out the authentication service separate from Firebase, validate that everything works and then integrate Firebase.

In this service, we are using a mixin called ChangeNotifier and a method notifyListeners which will allow for the widgets that are using this Service to be updated when the method is called. We are calling notifyListeners when we update the currentUser property because that means that the user has either logged in or logged out and we want the application to update based on the user's state.

More information on Provider and State Management can be found here in the Flutter Documentation

What we need as a baseline is the following:

We will keep a local property in the service call currentUser which is the object storing the user when the user calls the login method and if the password matches we will set currentUser and the user will be logged in. This will now provide a user when the call is made to getUser method. For logging the user out, we will set the currentUser property to null indicating that we are no longer logged into the system.


Determining User State On Application Launch

The first challenge when working with the application is to determine which page to open when the application starts up. What we want to do here is determine if we have a user or not. We will be using an AuthService we created above combined with the FutureBuilder widget from Flutter to render the correct first page of either a HomePage or a LoginPage.


Using the Provider

In main.dart we will need to update the default main method to look like this; we are wrapping the whole application with the ChangeNotifierProvider to get the ability to scan up the widget tree and find an object of type AuthService.


Modifying the MyApp Widget

Go into the main.dart and make the following changes that will allow the MyApp widget to set the route. This widget will determine if the application should navigate to the HomePage widget or LoginPage widget when the app is launched.


Modifying the Login Page Widget

Now that the AuthService can be accessed using the Provider, we can call the login function when the used clicks the button. Open the file login_page.dart and find the onPressed method for the login button and make the following change

We are using the Provider.of method to look up the widget tree and get our AuthService and then we have access to all of the methods, specifically the loginUser method.


Conclusion

At this point, you should have a functioning application with the basic login flow where the user will be logged in successfully if you provide the password as password123.

I added in a little extra functionality of displaying an error message in a dialog box if some sort of error occurs.

See Part Two of this Story Here

Resources

Source Code available here: [ make sure you are on the part-one branch ] https://github.com/aaronksaunders/simple_firebase_auth/tree/completed-part-one