Firebase Authentication and keeping users logged in with Provider in Flutter.
Tags: flutter, dart, firebase, authentication
Published: 2020-11-24 05:37:28

Incorporating firebase authentication into a flutter application can now be done in no-time, but the conventional way of doing so doesn’t turn out to be user-friendly in any manner. We just can’t expect our users to be keyboard-warriors and make them tolerant of signing in every-time they get their hands on our application.

>So, let’s fix this user experience clutter by keeping the user logged in by managing the state with the Provider package until the user smashes that “Sign Out” button.

We are just gonna be managing the state of our application with the Provider and orchestrate the execution flow based on whether the user is “Signed in” or not.

![Architecture](https://miro.medium.com/max/875/1*zb3LeP930ioiWfOG3XZEdA.jpeg)

What is Provider and why is it worthwhile to use?

> On the bottom line, we are about to watch over a value(in this case, logged in or not) and take requisite actions. So typically we are gonna be listening to a value and watch over its changes to manipulate the workflow of our application. And this is where the Provider comes into play, by the time you read this article, some might have figured out what’s really powering this Provider under the hood. The Provider is just an incarnation of the [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html) and [ChangeNotifier](https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html) which lets you expose/create/listen/dispose a value. So deciphers the [offical documentation](https://pub.dev/packages/provider).

Let’s now deep dive into the to-dos.

Open the pubspec.yaml file in your Flutter project and add the following packages. ([provider](https://pub.dev/packages/provider) ,[firebase_auth](https://pub.dev/packages/firebase_auth) , [firebase_core](https://pub.dev/packages/firebase_core))

{% gist https://gist.github.com/RaajeevChandran/4bb3d3032c2c40adbbfc5cb70857ed5e %}

We’ll kick-start this application by first finishing up with our Provider. Create an **authentication.dart** file in the lib directory.
1. Import the dependencies.
2. Create an **AuthenticationProvider** class with a firebaseAuth instance.

```import 'package:firebase_auth/firebase_auth.dart';
class AuthenticationProvider{
final FirebaseAuth firebaseAuth;
// FirebaseAuth instance 
AuthenticationProvider(this.firebaseAuth);
//Constructor to initialize the Firebase Auth instance.
}```

We’ll use a Stream to continuously listen to the Authentication State(logged in or not).

```Stream<User> get authStateChanges => firebaseAuth.idTokenChanges();```

Let’s quickly add the Sign-Up, Sign in, and Sign out methods.

{% gist https://gist.github.com/RaajeevChandran/296ba9c036270c01a569ce2d79fe7f02 %}

We have now finished setting up our Authentication Provider. Let’s now fit this provider into our **main.dart** file.
1.In the **main.dart** file, import the following dependencies.

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

2.We are about to make our main method async in order to make our Firebase Authentication completely error-free and give it a few nano-seconds to gear up.

```Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp()); 
//MyApp is our root widget.
}```

> POINTS TO PONDER WHEN USING PROVIDER
Providers are strictly scoped which means that they turn out to be erroneous when not defined in the right place. Always ensure that you initialize your Providers in the root widget (top of the widget tree to be more precise) so that they remain accessible throughout the nested widget tree and nested navigation routes.
In case you run into a scenario where you don’t want your Provider to be initialized in the Root widget, remember that any attempts to accessing the Provider which you defined in some other route makes that Provider to be inaccessible to its ancestor widgets/Root Widget in the Widget tree. Hence that Provider will only be accessible by its child/descendant widgets.

3. Creating our Root Widget (MyApp). As the Providers need to rest on the top of the Widget tree, we will make the MaterialApp widget as the child of the **MultiProvider** widget to initialize our Providers in the build method.
   3.a. Initialize the **AuthenticationProvider** using Provider()
   3.b. Use StreamProvider() to read the value from the authState method in the **AuthenticationProvider**.

{% gist https://gist.github.com/RaajeevChandran/bb3628a8a12da0f36335da3a8f6f538d %}

4. Now let’s add another class Authenticate to decide which route the application has to take based on the authState.

{% gist https://gist.github.com/RaajeevChandran/037c7551da439607477fbeb2c4249ae1 %}

Complete **main.dart** file.

{% gist https://gist.github.com/RaajeevChandran/3036cb351494e0a332e480f0bff546c2 %}

Time to build our **HomePage** and **LogInPage** routes. (Make sure you import them in the **main.dart** file).

**login_page.dart**

{% gist https://gist.github.com/RaajeevChandran/898e09c6421ba18dacddef9eba75bb0c %}

**home_page.dart**

{% gist https://gist.github.com/RaajeevChandran/2bf2d3a6dab8260166db381c3f21899d %}

And that’s a wrap!
This way, we have managed the state with the Provider to keep our users logged in. Hope the article was engaging enough. Still, stuck somewhere? Feel free to check out the {% github RaajeevChandran/Firebase-Authentication-in-Flutter-with-Provider %}GitHub repository.


ORIGINALLY POSTED IN {% medium https://rajeevchandran618.medium.com/firebase-authentication-and-keeping-users-logged-in-with-provider-in-flutter-f1c66cdb1bc7 %}