How to implement Forgot Password/Password Reset into your Flutter Apps with Firebase Auth
Tags: flutter, dart, programming, mobile
Published: 2020-12-25 01:05:52

##This is final series of our **Step by Step Guide on How to Authenticate your Flutter App with Firebase Auth**

You can check out the previous post [here](https://dev.to/dav4thevid/set-by-set-guild-on-how-authenticate-your-flutter-app-with-firebase-auth-3lb4) and [here](https://dev.to/dav4thevid/how-to-add-firebase-email-verification-to-your-flutter-app-4cbi).

Adding Forgot password/Password functionality is very essential in every app, and with firebase_auth we already have all that done for us, all we have to do is call the method, pass the right arguments, then we are good to go. 

##TLDR
If you already familiar with how firebase works, feel free clone the complete project we would be building [here](https://github.com/dav4thevid/flutter_firebase_authentication_part3)
If you are a firebase beginner, I would highly recommend you code along. Let dive right in

##FORGOT PASSWORD
Let’s start by creating our `Forgot Password Screen`, open Screens folder and add a new file, name it `ForgotPassword.dart`. import material library and add the code below.

```
class ForgotPassword extends StatelessWidget {
  static String id = 'forgot-password';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.lightBlueAccent,
      body: Form(
        child: Padding(
          padding: EdgeInsets.symmetric(horizontal: 30.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                'Email Your Email',
                style: TextStyle(fontSize: 30, color: Colors.white),
              ),
              TextFormField(
                  
                    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),
                      ),
                    ),
                  ),
              SizedBox(height: 20),
              RaisedButton(
                child: Text('Send Email'),
                onPressed: () {},
              ),
              FlatButton(
                child: Text('Sign In'),
                onPressed: () {},
              )
            ],
          ),
        ),
      ),
    );
  }
}

```
It’s just a basic UI, I won’t walk through that. Now let’s create our Forgot Password route, open `main.dart` and add this code inside our routes, `ForgotPassword.id: (context) => ForgotPassword(),`.
We also have to create a forgot password `FlatButton` inside our SignIn class, and make it navigate to our newly created route.

Open SignIn Class add this code.

```
FlatButton(
     onPressed: () {
     Navigator.pushNamed(
     context,
     ForgotPassword.id,
 );
},
 child: Text(
'Forgot Password?',
  style: TextStyle(color: Colors.grey, fontSize: 12),
   ),
),

```

The above is doing nothing fancy, it’s just takes our newly created `route id` then it passes that into `Navigator.pushNamed`, and this would trigger navigation when the user presses this `FlatButton`. Hot restart your app and test. forgot password should now take you to the Forgot Password screen.

Now that we have successfully added the UI and navigation for `ForgotPassword`, lets implement the functionality.

Create a new method, name it `passwordReset`, then we have to create an instance of firebase_auth, so we would be able to use its functions. import `import 'package:firebase_auth/firebase_auth.dart';` like so, and create an instance of it with `final _auth = FirebaseAuth.instance;` inside `passwordReset` method. We now have an instance of firebase_auth with `_auth` (i.e., any instance, variable or function with underscore, makes its private, that means we can't call it outside this class). Now add this line `await _auth.sendPasswordResetEmail();`This takes an email as an argument. Create an email String above and pass it inside `sendPasswordResetEmail' like this `await _auth.sendPasswordResetEmail(email: _email);`


We also need to prevent our code from moving to the next like when the auth request is not completed. Its an asynchronous call, we don't know how long it would take. if you are not familiar with asynchronous programming, you can check here for reference [>>>](https://dart.dev/codelabs/async-await). Add await to the instance and async to `passwordReset` method. (whew, we almost there). Now wrap your password reset method with try and catch block, should in case the request wasn't successful, it would throw an exception, so your app doesn't break. Lastly add this line.


```
 Navigator.push(
        context,
        MaterialPageRoute(builder: (context) {
          return ConfirmEmail();
        }),
   );

```


This would navigate us to our Confirm Email Screen on completion. (i.e. We created this in the previous article). Our password reset method should now look like this.


```
Future _passwordReset(String email) async {
    try {
      await _auth.sendPasswordResetEmail(email: email);

      Navigator.push(
          context,
          MaterialPageRoute(builder: (context) {
            return ConfirmEmail(
              
            );
          }
        ),
      );
    } catch (e) {
      print(e);
    }
  }
```

Notice!!!, We have an error with the context, right? That is because our Class is a stateless widget, convert it into stateful widget by clicking on our `ForgotPassword`  class and press `ctrl + .`. 
Another way of fixing this is by calling our password reset method as a callback inside our `RaisedButton` with the `onPressed` property. Either way works, I would go with this (I don't like cluttering my UI with logic).

Now add `onSaved` method inside the `TextFormField`, add newEmail as its argument, then assign our `_email` variable to `newEmail` like is 

```
 onSaved: (newEmail) {
      _email = newEmail;
   },

```
 Now call our `passwordReset` inside the `onPressed` property and pass our email variable like this. 

```
onPressed: () {
                  _passwordReset();
                  print(_email);
 },
```

Since we are using a `TextformField` widget as out input field, we need to wrap our entire field into a form widget and pass its key, If we don't do that our `TextFormField` would return null, because it’s doesn't know the current state of our form. We need to track the current state of our form. wrap the entire Column widget with a form widget. Form widget has a property `key` add that with a `_formKey` like this `key: _formKey`. create a new variable `formKey` below our email string variable like this. `final _formKey = GlobalKey<FormState>();`. Now inside our `passwordReset`, above sendPasswordReset function, add this this line. `_formKey.currentState.save();` This would save the current state of our form and send the inputted values upon submission. Your passwordReset should look like this.

```
_passwordReset() async {
    try {
       _formKey.currentState.save();
      await _auth.sendPasswordResetEmail(email: _email);

      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) {
          return ConfirmEmail();
        }),
      );
    } catch (e) {
      print(e);
    }
  }

```

Run Hot restart and test your app. This should send a mail link to the provided email for resetting password and also navigate you to the confirm email screen.

(Note: remember you have to be registered before you can reset your password, since we are not handling errors, its won't prompt you or send you email if you are not registered, but you can check your terminal for invalid emails errors and so on). 

Lastly, Notice our confirm email screen reads `"'An email has just been sent to you, Click the link provided to complete registration'"`. That is not text we won't for password, lets make `ConfirmEmail` text dynamic. (i.e another way of fixing this is by creating a separate screen for this).

Open `ConfirmEmail`add a new variable below id `String message`, add it inside the `constructor` then cut the message text and pass the message inside our Text widget.

```
child: Text(
    message,    //here
```
Now open `ForgotPassword`, create a new variable message, add the text you cut into this variable, then pass it inside our `ConfirmEmail`. Your routing should look like this.

```
 Navigator.push(
        context,
        MaterialPageRoute(builder: (context) {
          return ConfirmEmail(message: widget.message,);
        }),
      );
```

Do the same for our `SignUp` Screen.

We have finally completed this series. I might be writing another post for error handling and form validations, if you want that, feel free to comment below. If you have any question, feel free to ask them also. you can correct me if you spot any errors or typos.

Thank you for taking your time to read this.