Step By Step Guide On How to Authenticate your Flutter App with FireBase Auth
Tags: flutter, programming, dart
Published: 2020-12-17 01:49:20

In this post, I will be walking you through how to authenticate your flutter app with firebase. we won't be building anything fancy. just a demo app with three screens (Sign-Up, Sign-In and Homepage). This post assumes you've already setup your IDE with Flutter, we won't do that here, if you ready, Lets dive right in.

**TLDR**
If you already familiar with Flutter and Firebase and this post is too long for you to read, you can download the final project we would be building [here on github](https://github.com/dav4thevid/flutter_firebase_authentication)

If you are not fully familiar with Flutter and Firebase, I would highly recommend you read through or better still code along so as to fully understand how things work.


**Firstly let create our Flutter App.**

if you are using VSCode, Open the Command Palette **( Ctrl + Shift + P) for windows** and **( Cmd + Shift + P)** for mac. click on New Project and feel free give the project any name you want. (Note: all letters has to be lower case). If you are using Android Studio as your IDE. click on file, then navigate to new flutter project. select flutter application then name the project and choose any folder path you want your project to be saved in. set package name is your app domain name, if you don't have that feel free to add this **(com.example.yourappname)** P.S: Write this down, we would be need it when we are ready to initialize our app with firebase, also Don't forget to tick all boxes then click finish.

**Lets start creating our screens.**

(Note: I would be using `VSCode` for this article, if you're using Android Studio you can click the play button to run your app.)
open your terminal then navigate to your newly created flutter project then run your app with `flutter run`. open `lib/main.dart` file and delete `MyHomePage` class, we would be creating ours shortly. Create a new folder, I will name mine screens. Now click on new file and name the file `SignUp.dart`, do same for `SignIn.dart` and `Homepage.dart` respectively.


Open our newly created SignUp.dart file import material Design with `import 'package:flutter/material.dart'` then create your signup class (Stateless Widget), you can do that by just typing `stl` an auto create would popup, just click it (there you go 😉). Name it signup class, lets make the class return a text widget with "Sign Up" text temporarily, while we create our routes. Your SignUp class should look like this.

```
import 'package:flutter/material.dart';

class SignUpScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text('Sign Up'),
    );
  }
}


```
feel free to do the same for SignIn and Homepage files.

Open the main.dart file, you would notice the myHomePage class we deleted is already prompting us of an error, delete the entire line. we would be creating ours shortly. Now add this `initialRoute: SignUp.id`.
Note: we could use any of this Material App properties (`home` or `initialRoute`) as our base route, but I prefer using initial route so as to make the naming convention the same, its doesn't really matter in our case, you could use either of the two.
PS: `home` takes a widget as its property, while `initialRoute` takes a string. Notice that its prompt an error, that is because we have not added the route to our SignUp class. Open SignUp and add this line `static String id = 'sign-up';`, Do the same for both SignInScreen and HomepageScreen.

We've added our initial route, Our app would navigate to signup screen upon launch. Now lets create our `routes`, this takes Map <String> as argument. now add this lines `SignUpScreen.id: (context) => SignUpScreen(),` Do same for both SignIn and Homepage route.
Your code should now look like this.

```
import 'package:flutter/material.dart';
import 'package:flutter_practice/Screens/Homepage.dart';
import 'package:flutter_practice/Screens/SignIn.dart';
import 'package:flutter_practice/Screens/SignUp.dart';


void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      // home: SignUpScreen(),
      initialRoute: SignUpScreen.id,
      routes: {
        SignUpScreen.id: (context) => SignUpScreen(),
        SignInScreen.id: (context) => SignInScreen(),
        HomepageScreen.id: (context) => HomepageScreen(),
      },
    );
  }
}

```

Now hot restart you your app with `capslock R`. You should see a black screen with a huge 'Sign Up' red text, (😞 Our screen is ugly, lets style it up a little). Im not going to walk through the styling process just copy and paste the below code, if you are following along.

```
import 'package:flutter/material.dart';

class SignUpScreen extends StatelessWidget {
  static String id = 'sign-up';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.lightBlueAccent,
      body: Container(
        child: Center(
          child: Padding(
            padding: const EdgeInsets.all(50.0),
            child:
                Column(mainAxisAlignment: MainAxisAlignment.center, children: [
              Text(
                'Sign Up Here',
                style: TextStyle(fontSize: 30, color: Colors.white),
              ),
              SizedBox(
                height: 20,
              ),
              TextFormField(
                obscureText: true,
                style: TextStyle(color: Colors.white),
                decoration: InputDecoration(
                  labelText: 'Email',
                  icon: Icon(
                    Icons.mail,
                    color: Colors.white,
                  ),
                  errorStyle: TextStyle(color: Colors.white),
                  labelStyle: TextStyle(color: Colors.white),
                  hintStyle: TextStyle(color: Colors.white),
                  focusedBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.white),
                  ),
                  enabledBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.white),
                  ),
                  errorBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.white),
                  ),
                ),
              ),
              TextFormField(
                style: TextStyle(color: Colors.white),
                decoration: InputDecoration(
                  labelText: 'Password',
                  icon: Icon(
                    Icons.lock,
                    color: Colors.white,
                  ),
                  errorStyle: TextStyle(color: Colors.white),
                  labelStyle: TextStyle(color: Colors.white),
                  hintStyle: TextStyle(color: Colors.white),
                  focusedBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.white),
                  ),
                  enabledBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.white),
                  ),
                  errorBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.white),
                  ),
                ),
              ),
              RaisedButton(
                onPressed: () {},
                child: Text(
                  'Submit',
                  style: TextStyle(fontSize: 18),
                ),
              )
            ]),
          ),
        ),
      ),
    );
  }
}

```
You can replicate that for the Signin screen as well, but if you like, feel free to style it to your own taste. We now have our auth screens styled up, we can now initialize our app with Firebase. Our SignUp Screen should look like this ![Sign up screen](https://ibb.co/gT9zpsb)



**Initializing App to Firebase**

visit the firbase console [here](https://console.firebase.google.com/).
P.S: You need to have a google account, SignUp if you don't have one.
click on Add Project, enter the project name, then create new project, this should take less than 20seconds.( We would be building for Android on this post). incase you forgot your package name, open android/app/build.gradle scroll downwards you would see `applicationId` thats you package name, Now click continue and download your `google.services.json` file.
P.S: Make sure to click the download button just once, so as to prevent duplicate files been downloaded, if you've download this particular file before, delete it from your downloads folder. Now move the `google.services.json` file you just downloaded into `android/app` root folder. make sure its the right folder, if not its might prevent our app from running. 

Once you've done click on next then open `android/build.gradle` and add this line under dependencies `classpath 'com.google.gms:google-services:4.3.4'` and this `google()` under all project repositories if its not already added. Now open android/app/build.gradle. and add this line `apply plugin: 'com.google.gms.google-services'` under app plugin then this `implementation 'com.google.firebase:firebase-analytics'` under dependencies. (😫phew!! we are almost there).

We need to install some Firebase packages into our app namely `firebase_auth` and `firebase_core`. open `pubspect.yaml` file and add this lines `firebase_auth: ^0.18.0+1` and `firebase_core: ^0.5.0`, make sure its properly aligned (pubspect.yaml could be funny at times, lolx).Once you've done that, click on `Get Packages` this should install these packages into our app.

Now open `main.dart` file and add this lines.
`WidgetsFlutterBinding.ensureInitialized();`
  and `await Firebase.initializeApp();`.

 Your `main.dart` file should now look like this
```
void main() async{
   WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}
```
P.S: don't forget to import `package:firebase_core/firebase_core.dart;`

Close and rerun your app on the terminal, `ctrl c` and `flutter run`. If your app runs successfully, Congratulations!!! you have successfully initialized your flutter app with firebase.

if you encounter build errors.  [ click here for fix](https://github.com/flutter/flutter/issues/38934).

*Now that we've successfully created our screens and initialized our app with flutter, its time we start writing our authentication logic.*

**Authenticating our App with Flutter.**

Open the SignUp file, since we using `TextFormField` we would have to wrap our entire column into a `form` widget. click the column widget and also click the yellow lightbulb that shows at the left side, select wrap with widget, then rename widget to `Form`.

Form has a property called key add this `key: _formKey`. This creates a container for form fields and make us get the form values upon save. We would have to create an instance for GlobalKey, which is the _formKey we added. add this line below our static id String `final _formKey = GlobalKey<FormState>();`. Now create create email, password variable. `String _email;` `String _password;`. We now have to add a call back inside our `TextFormField` to bind our email and password variable inside our callback. Add this line inside our `TextFormField` 
```
onSaved: (emailValue) {
    _email = emailValue;
  },
``` Do same for password TextFormField. Now lets test and see if our binding works correctly. Inside our `RaisedButton` add this line. 
```
 onPressed: () {
     _formKey.currentState.save();
     print(_email);
     print(_password);
   },
```
Type in a dummy email and password inside the text field and click submit, you should see the text you typed inside your terminal. Lets move on.

Now add this line inside the onPressed callback 
```
onPressed: () async {
      _formKey.currentState.save();
      try {
    final new_user = await _auth.createUserWithEmailAndPassword(
    email: _email, password: _password);
    if (new_user != null) {
    Navigator.pushNamed(context, HomepageScreen.id);
             }
      } catch (e) {
         print(e);
       }
    },
```
The above code takes our `_auth` instance from firebase and pass our email and password values into the `createUserWithEmailAndPassword` function from firebase. its also check if user is not available, if so its navigate us to the homescreen page. if there is an error, its catches the error and print it on the terminal.

*We have to enable email and password authentication from firebase console*

Now visit the firebase console [here](https://console.firebase.google.com/) then click on your project, on the left, click on authentication, click on sign in methods, You can see Email/Password is disabled. enable it and save.

Before we test, lets go to our Homepage screen and add some contents to it, so its doesn't show a complete blank screen. Inside the Homepage screen, delete the entire class and add this 
```

class HomepageScreen extends StatelessWidget {
  static String id = 'homepage';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: null,
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.close),
              onPressed: () {
              }),
        ],
        title: Text(
          'Homepage',
          style: TextStyle(color: Colors.white),
        ),
        backgroundColor: Colors.lightBlueAccent,
      ),
      body: Center(child: Text('Homepage'),),
    );
  }
}
```
Open terminal and run hot restart. Now test sign up, its should sign the user up and navigate to Homepage Screen. You can click on users on firebase console, to see the list of registered users. 
P.S: When testing make sure your password is 6 characters or above, firebase won't accept anything lower than that.

*Lets implement `signOut` on our app.*

Inside the method in our `IconButton` widget, add this 
              ` _auth.signOut();
               Navigator.pop(context);`. also import firebase auth `import 'package:firebase_auth/firebase_auth.dart';` and create its instance like so `final _auth = FirebaseAuth.instance;` . Your Homepage screen should now look like this.

```
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';

class HomepageScreen extends StatelessWidget {
  static String id = 'homepage';
  final _auth = FirebaseAuth.instance;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: null,
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.close),
              onPressed: () {
                // Implement logout functionality
                _auth.signOut();
                Navigator.pop(context);
              }),
        ],
        title: Text(
          'Homepage',
          style: TextStyle(color: Colors.white),
        ),
        backgroundColor: Colors.lightBlueAccent,
      ),
      body: Center(child: Text('Homepage')),
    );
  }
}
```
Now run hot reload `r` and test the log out functionality. its should take you back to the SignUp Screen. We are almost there, *lets implement the SignIn functionality*

Underneath the `RaisedButton` create a FlatButton and give it Text widget like so. 
``` 
FlatButton(
    onPressed: () {
    Navigator.pushNamed(context, SignInScreen.id);
},
     child: Text('Sign In'),
    )
``` 

The `navigator.pushNamed` line would make our app navigate to the `Sign In Screen`. Now test and see if its working.

Open the SignIn Screen and wrap the `column ` widget with a form widget add the key property also. Create an email and password variable like we did when implementing the Sign Up functionality, I wont walk through that again, you can check the SignUp Screen or scroll up for reference.

Inside the onPressed callback in our `RaisedButton` add this line 
```
  onPressed: () async{
_formKey.currentState.save();
   try {
      final user = await _auth.signInWithEmailAndPassword(
      email: _email, password: _password);
      if (user != null) {
      Navigator.pushNamed(context, HomepageScreen.id);
       }
                       
       } catch (e) {
        print(e);
      }
   },
```



This should navigate you into HomepageScreen, if you entered your correct credentials. (phew 😌! Finally, haha). We have successfully authentication our app with firebase auth. Congratulations!!!. 

Feel free to correct me if you spot any errors, you can also checkout my future posts where I would be walking you through how to add forget password, reset password with firebase. 

Your feedbacks and comments would be greatly appreciated. Thanks for your time.