Flutter Login & Registration Using Firebase

Mais Alheraki
The Startup
Published in
6 min readJul 12, 2019

--

Flutter & Firebase

In this article, I will be explaining how you can use FirebaseAuth to authenticate users of your app, using the Email and Password method, and store their information in the Cloud Firestore database.

Firebase Authentication is a great way Firebase provides for you to manage the users of your app easier, less talk more code, let’s go.

What Will I Be Making?

Before I start let’s take a look at the requirements for this simple app, so you could know if you came to the right place for solutions or not…

  1. Our app has a login sheet and registering sheet.
  2. In both sheets, the app will validate the user’s input.
  3. After submission, the app should catch the errors returned by FirebaseAuth if the login or registration didn’t go correctly and display feedback for the user (wrong password, user not found, … etc).
  4. The user information (email, display name) should be stored in the database after registration.
  5. After login or registration, the user will be directed to the app’s home page where there will a welcoming message with his name (personalized welcoming).

Validating Input

To validate user’s input means to check if the required fields are empty and/or the input doesn’t match the type required (not an email in case of an email field), this is something the app itself will be doing, not Firebase yet.

To do that, first, I need a TextFormField widget, and since we have 5 input fields, I will make a custom TextFormField to have the design I want, in a separate class, so let’s make a new file and call it customTextField.dart, with the following code:

This is actually a reuse of the original widget, I’m just customizing the look so I can use it wherever we want and decrease the number of lines of code we should write. This is something that I really love about Flutter, it doesn’t strict me with its widgets, but allows me to use them to even further customization and branded design! so I actually can make literally any design I like.

This is how customTextField looks like

The most important properties we will focus on here are onSaved and validator, those two I will be using to make the validation. wrap your customTextField with a Form widget:

Now you are wondering about this _formKey and _autoValidate, let’s add them to the top of our code first and explain their job here:

final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
bool _autoValidate = false;

Form widget gives me a property called autovalidate which takes a bool value. When it’s true, the auto validation process starts, wanna see how it looks like? I really love it, it gives great and fast feedback for the user.

Auto validation

To make this possible, I need to set autovalidate to true, but where? at first, it’s still false, the user hasn’t pressed the button yet, but on pressing, I need the auto validation to start so the user can see instant feedback on his/her mistakes until the field are filled correctly. I said on pressed, right? this is a property of the button! so the whole work will be done inside onPressed property of the button widget.

In the code, I built a filledButton method of type Widget that will return the button that has the look I want, and it takes parameters, this is just another way of writing a reusable piece of code!

I will be using it 2 times, one for the login button and pass it a login validation function, and the other for the registration button with passing a register validation function.

filledButton(“LOGIN”, Colors.white, primaryColor, primaryColor, Colors.white, _validateLoginInput)filledButton("REGISTER", Colors.white, primaryColor, primaryColor, Colors.white, _validateRegisterInput)

Now you will be working on these 2 functions, they contain all the heavy work with FirebaseAuth and Firestore Database. Before I move to them, let’s take a look at how I used validator property to display these nice error messages to the user, and onSaved to save the input to variables.

CustomTextField(
icon: Icon(Icons.email),
hint: “EMAIL”,
onSaved: (input) {
_email = input;
}
,
validator: emailValidator,
)

In this example, I used my custom widget to build the email text field, on validator I will give my already-written email validation function which contains a regex to test the email, it will be invoked when the user presses on Login (or Register) button.

Important Note: onSaved won’t work until form.save() is invoked on the form, but where? the answer is inside _validateLoginInput and _validateRegisterInput functions, yes exactly! the ones I mentioned above, the ones that will be invoked when the user puts his finger on submitting buttons!

Here is where Firebase comes into action!

These 2 functions are the heart of our app, they handle the process for:

  1. Signing the user in or creating a new account.
  2. Catching errors returned from Firebase and provide feedback to the user.
  3. Invoking onSaved to save the user’s input to variables and use them.
  4. Starts the auto validation process.

Basically, it’s the same function copied twice, one for login, and the other for creating a new account, let’s take a look at the code:

First, the form state will be saved to a variable called form, the form state tells us if the form was filled correctly or not, if it is, it will start the doing the first block of code (try, catch), if not, the auto validation process starts.
Inside the try block, we finally see a Firebase code!

FirebaseUser user = await FirebaseAuth.instance .signInWithEmailAndPassword(email: _email, password: _password);

This code is going to sign the user in using the _email and _password that were saved earlier, but… what if the email didn’t belong to any account? or the password wasn’t correct? Firebase is going to throw a full detailed error, and we will be catching it from the air! Based on the error type, an alert dialog will be shown that describes what happened.

This is the other function, the only difference is that we are creating a new user here, and the kinds of errors we are catching are different.

After Login/Register

The user has successfully logged in or created an account, he/she will be navigated to the home page of the app. Create a new file home.dart with the following code:

The user is logged in now, that means you have a current user, that has a display name, that you will be using to display a custom welcoming message… but wait, what is FutureBuilder? this seems so complicated for displaying just a name!

FutureBuilder is an important widget that is used when you want to display data that may not be ready at the time of building, that means if you didn’t use and simply called the currentUser.displayName, you will get a null or an error message, but there is actually a current user, what happened then?
The build method will build everything before the data arrives from the server, that’s where FutureBuilder gives you a great solution, it simply tells the build method “hey dude, wait a sec till I get the data from the server, then I will return the widget you want to build”. Great and simple solution. I really love Flutter! :D

That’s the simplest explanation I could write, there are of course behind the scenes things, but don’t bother yourself with them now.

The full code is available on GitHub here, just make sure you include your own config files, the app won’t run without them.

Thank you for reading. 🌸

--

--

Mais Alheraki
The Startup

Software engineer, Geek, Designer, Reader & always a Lifetime Learner!