Build a Flutter 🐦 app that uses Firebase 🔥 Google SignIn and Firestore for user authentication. Learn how to use both StatefulWidget and StreamBuilder to create a reactive UI. https://fireship.io/lessons/flutter-firebase-google-oauth-firestore/

- Flutter https://flutter.io
- FlutterFire https://firebase.google.com/docs/flutter/setup
2024-02-04T07:04:07.795Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
4eaccade-cc3e-40e8-aee9-3ae396df7554
fc96757af161b0aa25f38b3c7c97165d2d976fcfa6d40fb62bcf7bdb62b822fb
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Welcome to the first ever Flutter video on this channel.
Today, we'll start from scratch and build a user authentication system using Firebase Google sign in and Firestore.
The UI is nothing special, but this video is important because it will show you how to handle real time streams of data from external sources and update the UI reactively.
If you're new here, like and subscribe, and you can grab the full source code from FireShip IO.
I'd like to start by saying that this video is intermediate level.
So if you're brand new to Flutter, it might seem a little overwhelming.
But don't worry because next week, I have a more gentle introduction plan that's typically for JavaScript and or TypeScript developers.
We're starting from scratch, so the first thing we'll do is run Flutter create from the command line to create a new app.
We can then open up the app in Versus Code, and we'll have some configuration to do for the platforms we wanna use.
In this case, we'll only be setting up Android, But the iOS setup is super easy, so feel free to do that if you're on a Mac.
From here, we'll jump into the Firebase console, click on the Android button, and And then we'll need to set a package ID for our project.
That should be something like com, your company name followed by the app name.
So io.fireship.lessnap in this case.
The next thing we'll wanna do is generate a sign in certificate specifically for Google OAuth.
We can generate it by copying and pasting this command.
I'll link that in the full lesson and then going to the terminal and entering the command.
I'm not sure if this is a problem on my end or if the command is just outdated but it gives me an error if I try to use export cert and list together.
If it works for you, then that's great.
But if not, you'll wanna go in here and take out the list from the command.
And then when prompted for a password, type in Android in all lowercase.
And finally, copy and paste the same command, but this time delete export cert from it.
That should give you an SHA one certificate that you can just copy and paste in there and then click the next step, and that will give us our Google services JSON file.
We can download it and save it in the Android app directory inside of our Flutter project.
Now getting back to Versus Code, we'll go into that Android directory.
It should look something like this and then we'll open up the build Gradle file inside of the app directory.
Inside this file, you'll see the application ID.
We'll wanna switch that to the application ID that we chose on Firebase.
Then down at the very bottom, we will apply the plugin that's required for Google services.
And lastly, we need to go up one level to the Android directory and you'll See another build Gradle file there.
In this one we need to find the dependencies and then add the class path that references the Google services plug in.
Then the final thing we'll do is go into the pubspec YAML and add our actual dependencies for this project.
For a Firebase mobile app, you'll almost always need Firebase core and analytics.
And then we'll also bring in Firestore, Firebase auth, and Google sign in is its own plugin.
And lastly, I'm adding RXDart which is optional but it gives you a lot of power when working with real time streams in Firebase.
And we'll see direct examples of that throughout this lesson.
At this point, let's go ahead and run Flutter run just to make sure we don't have any It's in the console or in the app itself.
That should give us the default Flutter app that looks something like this.
From here, we're going to transform this app into a login button that reacts to the user's authentication state.
In addition, this feature will save any custom data that we want to the Firestore database.
For example, we might want to customize the user profile with a unique username or some other unique data or we might have additional relational data that we need to query based on the user's user ID.
Okay.
So now let's write some code.
First, I'm going into the main Dart file and I'm just going to delete pretty much everything in here.
The only thing I wanna keep is the my app widget just so we have a container to display our button.
So inside the material app, you'll see a body property.
And in that, we can go ahead and set up a child that is a column.
And the reason I'm using a column here is because we can add multiple widgets to it, and they'll just be stacked on top of each other.
So basically, what we're going to do is just flush out our UI inside this widget array.
We're going to need 2 different buttons.
We'll have one to sign in with Google and then one to sign out.
Every material button has an on pressed event handler that we can implement to do something when the user clicks on a button.
Right now it does nothing, but we'll set that up in the next step.
Then we'll go ahead and set up a second material button.
This one will be to log out when the user is authenticated.
It's the exact same widget just with some different coloring and text.
So if we run the app at this point you should see the 2 buttons up here at the top of the view.
If we want to center our buttons we can actually go into the column widget and adjust the main axis this alignment to center.
And that puts our buttons in the middle.
Now it's time to switch gears and talk about the authentication logic.
It's generally a good idea to separate your business logic from your UI or presentation logic.
And that's exactly what we're going to do here by creating a new file called auth.
Dart.
Now Now Flutter is not very opinionated about the way you share global data or handle your state management, and you'll see a lot of examples out there that use Redux or inherited widgets.
But when you're just prototyping, one of the easiest things to do is just expose a global variable.
So that's what we're going to do here by creating an auth class, and then we'll go ahead and instantiate that as our auth service and just have that sit in the global name space.
It's not a true singleton, but we will only instantiate it once and it will live outside of our actual widget tree.
Inside the class itself, we'll start by defining some private members for Firebase and Google sign in.
Then the actual values that will be available to our widgets will all be either observables or streams.
And it's also important that they are multi subscription streams or hot observables.
In Dart, a stream is only able to handle 1 subscription by default, but we want to share these streams in potentially many different widgets globally throughout the app.
So that's an important rule to follow if you're exposing a global stream.
The observable user is the user that we get from Firebase authentication, while the profile is the custom user data that we save about that user in the database.
And lastly, we'll create a subject for the loading state, which is just an observable that we can push new values to manually.
So these 3 streams define our state, and then we'll have our widgets listen to them and then update the UI reactively.
The next thing we'll do is just go over all the methods that are available on service.
Google sign in will be used when the user taps a button and it will take them to their Google account so they can log in and authenticate.
Update user data will update that user's record in Firestore, and sign out will assign the user out of Firebase.
The first thing we'll do is go up here to the constructor and define the user observable.
So by default, Firebase has already given this to us as a stream, so we can just wrap it inside of observable.
And that will change anytime the user signs in or signs out.
Now in order to retrieve the user's profile from Firestore, we first need to know the value of their user ID.
This is where Rx start is going to start making our life a lot easier because we can just use this switch map operator, which will listen to the value of the user observable, Then it will switch to a different observable, in this case, the observable of the Firestore data for that user.
So we can just point to the user's collection, Grab the document with the corresponding user ID, grab the snapshots, and then I'm also going to map the snapshots to their actual data payload just for convenience here.
When the user is not signed in, we're not going to have a user ID.
So in that case, we want to return some observable data from switch map, which we can do with observable just and an empty object.
So that gives us observables we can listen to in the widgets.
Now we just need a way for the user to sign in.
As soon as the user clicks on the Google sign in button, we're going to flip the loading state to Drew.
And we can do that by simply calling add on our loading stream.
Then the next thing we'll do is just follow the steps required to get the user signed in.
So first, we will call the Google sign in method, and that will trigger the sign in process.
Once that's completed, it will give us the user's ID token and auth token.
At this point, the user will be signed in with Google but not Firebase.
But we can easily sign them into Firebase by just taking the tokens and then passing them to the Google sign in method from Firebase auth.
Then we'll update their user data in Firestore, which we'll implement here in the next step, and then we'll flip the loading state to false.
The reason I put this in a separate method is that if you have multiple sign in options, you can reuse this code for each of them.
And, basically, we're just making a reference to the same Firestore document, and then we're calling ref set data with whatever custom data we wanna put in there.
I'm going to add a time stamp of the current date just so we can see that update when we sign in and sign out.
And adding the merge true option will make this Structive update so it won't overwrite any existing user data in that document.
And lastly, we can just call auth sign out to sign out the user.
So that takes care of our business logic for authentication.
Now we can get to the really cool part, which is making Flutter reactive.
We'll look at 2 different ways we can make the UI update when the values in those streams change.
The first one we'll look at is a stateful widget, which works very similar to a React JS component if you're familiar with React.
But first, we'll go into the buttons that we defined earlier and implement their on pressed event handlers.
That's as simple as calling auth service Google sign in and sign out inside of these functions.
At this point, you should be able to sign in to the app with your Google account.
And when you do that, you should also see the data updated in Firestore.
The first thing we'll do is define a new widget called the user profile that extends stateful widget.
The only thing this widget needs to do is call the create state method for the user profile state.
The next step is to define the state, which is the user profile state, and it extends the state class with the user profile that we just defined.
Now this widget can listen to our global streams and then set its own internal state that we can actually show in the UI.
In this demo, I'm just going to be really lazy with the UI, and we'll just show the user profile and the loading state as a string.
Now when you set up listeners on a stream or observable, you usually wanna make sure that the state is initialized, which you can do inside the init date life cycle hook.
So all we have to do here is call the auth service profile listen.
That will set up the subscription, and then that will give us the state from that subscription, and then we'll use it to call set state on the stateful widget.
Set state is important, and it's built into stateful widgets, and it just tells the widget to rerender when it's called.
So you should only use set state to update values on the widget.
All the computation should be done outside of it.
Then we can go ahead and do the exact same thing for the loading state from the auth service, And now the UI for this widget will rerender anytime the values in these streams change.
Now we don't have any UI in this widget yet, so let's go ahead and add that inside of its build function.
Again, I'm being super lazy with the UI here, so I'm just setting up a column that has a container.
Then we'll render out the underlying data as text widgets.
So this is nice for debugging, but obviously not what you'd want in a real app.
When we log in, we should see this object that's the data from Firestore, and then below that, we have false for the loading state.
You'll notice that even though we're logged in, we're still showing both the login button and the logout button.
Instead of doing that in a stateful widget, We can actually do it in a state list widget using a thing called a stream builder.
You'll also notice that it has a lot less complexity and boilerplate code than the stateful widget.
The stream builder is a widget itself that takes 2 arguments.
The first one is the stream to listen to, and then the second one is a function that will return some UI elements based on the state of the stream.
So for our login button, we want to listen to the user observable.
And then if the user's logged in, we'll show the sign out button.
If not, we'll show the sign in with Google button.
So the builder function gives you 2 things to work with, the context and then the snapshot of the stream itself.
In our case, the snapshot will be the user.
So we can see if the user has data, then we know that the user is logged in.
Otherwise, we know the user is logged out.
So we can actually just go and grab the material buttons that we already created, then put them into the corresponding spot in this conditional.
So now whenever the stream emits a new value, it will just Automatically rerender based on this logic in the builder function.
I'm gonna go ahead and wrap things up there.
If this video helped you, please like and Scribe.
And I'm really curious to get your feedback on this video.
My plan is to make a lot more Flutter videos in the future, but it's really based on what you guys wanna see.
Make sure to grab the full source code from FireShip IO.
Thanks Thanks for watching, and I will talk to you soon.

Speaker 0: Welcome to the first ever Flutter video on this channel. Today, we'll start from scratch and build a user authentication system using Firebase Google sign in and Firestore. The UI is nothing special, but this video is important because it will show you how to handle real time streams of data from external sources and update the UI reactively. If you're new here, like and subscribe, and you can grab the full source code from FireShip IO. I'd like to start by saying that this video is intermediate level.

So if you're brand new to Flutter, it might seem a little overwhelming. But don't worry because next week, I have a more gentle introduction plan that's typically for JavaScript and or TypeScript developers. We're starting from scratch, so the first thing we'll do is run Flutter create from the command line to create a new app. We can then open up the app in Versus Code, and we'll have some configuration to do for the platforms we wanna use. In this case, we'll only be setting up Android, But the iOS setup is super easy, so feel free to do that if you're on a Mac.

From here, we'll jump into the Firebase console, click on the Android button, and And then we'll need to set a package ID for our project. That should be something like com, your company name followed by the app name. So io.fireship.lessnap in this case. The next thing we'll wanna do is generate a sign in certificate specifically for Google OAuth. We can generate it by copying and pasting this command.

I'll link that in the full lesson and then going to the terminal and entering the command. I'm not sure if this is a problem on my end or if the command is just outdated but it gives me an error if I try to use export cert and list together. If it works for you, then that's great. But if not, you'll wanna go in here and take out the list from the command. And then when prompted for a password, type in Android in all lowercase.

And finally, copy and paste the same command, but this time delete export cert from it. That should give you an SHA one certificate that you can just copy and paste in there and then click the next step, and that will give us our Google services JSON file. We can download it and save it in the Android app directory inside of our Flutter project. Now getting back to Versus Code, we'll go into that Android directory. It should look something like this and then we'll open up the build Gradle file inside of the app directory.

Inside this file, you'll see the application ID. We'll wanna switch that to the application ID that we chose on Firebase. Then down at the very bottom, we will apply the plugin that's required for Google services. And lastly, we need to go up one level to the Android directory and you'll See another build Gradle file there. In this one we need to find the dependencies and then add the class path that references the Google services plug in.

Then the final thing we'll do is go into the pubspec YAML and add our actual dependencies for this project. For a Firebase mobile app, you'll almost always need Firebase core and analytics. And then we'll also bring in Firestore, Firebase auth, and Google sign in is its own plugin. And lastly, I'm adding RXDart which is optional but it gives you a lot of power when working with real time streams in Firebase. And we'll see direct examples of that throughout this lesson.

At this point, let's go ahead and run Flutter run just to make sure we don't have any It's in the console or in the app itself. That should give us the default Flutter app that looks something like this. From here, we're going to transform this app into a login button that reacts to the user's authentication state. In addition, this feature will save any custom data that we want to the Firestore database. For example, we might want to customize the user profile with a unique username or some other unique data or we might have additional relational data that we need to query based on the user's user ID.

Okay. So now let's write some code. First, I'm going into the main Dart file and I'm just going to delete pretty much everything in here. The only thing I wanna keep is the my app widget just so we have a container to display our button. So inside the material app, you'll see a body property.

And in that, we can go ahead and set up a child that is a column. And the reason I'm using a column here is because we can add multiple widgets to it, and they'll just be stacked on top of each other. So basically, what we're going to do is just flush out our UI inside this widget array. We're going to need 2 different buttons. We'll have one to sign in with Google and then one to sign out.

Every material button has an on pressed event handler that we can implement to do something when the user clicks on a button. Right now it does nothing, but we'll set that up in the next step. Then we'll go ahead and set up a second material button. This one will be to log out when the user is authenticated. It's the exact same widget just with some different coloring and text.

So if we run the app at this point you should see the 2 buttons up here at the top of the view. If we want to center our buttons we can actually go into the column widget and adjust the main axis this alignment to center. And that puts our buttons in the middle. Now it's time to switch gears and talk about the authentication logic. It's generally a good idea to separate your business logic from your UI or presentation logic.

And that's exactly what we're going to do here by creating a new file called auth. Dart. Now Now Flutter is not very opinionated about the way you share global data or handle your state management, and you'll see a lot of examples out there that use Redux or inherited widgets. But when you're just prototyping, one of the easiest things to do is just expose a global variable. So that's what we're going to do here by creating an auth class, and then we'll go ahead and instantiate that as our auth service and just have that sit in the global name space.

It's not a true singleton, but we will only instantiate it once and it will live outside of our actual widget tree. Inside the class itself, we'll start by defining some private members for Firebase and Google sign in. Then the actual values that will be available to our widgets will all be either observables or streams. And it's also important that they are multi subscription streams or hot observables. In Dart, a stream is only able to handle 1 subscription by default, but we want to share these streams in potentially many different widgets globally throughout the app.

So that's an important rule to follow if you're exposing a global stream. The observable user is the user that we get from Firebase authentication, while the profile is the custom user data that we save about that user in the database. And lastly, we'll create a subject for the loading state, which is just an observable that we can push new values to manually. So these 3 streams define our state, and then we'll have our widgets listen to them and then update the UI reactively. The next thing we'll do is just go over all the methods that are available on service.

Google sign in will be used when the user taps a button and it will take them to their Google account so they can log in and authenticate. Update user data will update that user's record in Firestore, and sign out will assign the user out of Firebase. The first thing we'll do is go up here to the constructor and define the user observable. So by default, Firebase has already given this to us as a stream, so we can just wrap it inside of observable. And that will change anytime the user signs in or signs out.

Now in order to retrieve the user's profile from Firestore, we first need to know the value of their user ID. This is where Rx start is going to start making our life a lot easier because we can just use this switch map operator, which will listen to the value of the user observable, Then it will switch to a different observable, in this case, the observable of the Firestore data for that user. So we can just point to the user's collection, Grab the document with the corresponding user ID, grab the snapshots, and then I'm also going to map the snapshots to their actual data payload just for convenience here. When the user is not signed in, we're not going to have a user ID. So in that case, we want to return some observable data from switch map, which we can do with observable just and an empty object.

So that gives us observables we can listen to in the widgets. Now we just need a way for the user to sign in. As soon as the user clicks on the Google sign in button, we're going to flip the loading state to Drew. And we can do that by simply calling add on our loading stream. Then the next thing we'll do is just follow the steps required to get the user signed in.

So first, we will call the Google sign in method, and that will trigger the sign in process. Once that's completed, it will give us the user's ID token and auth token. At this point, the user will be signed in with Google but not Firebase. But we can easily sign them into Firebase by just taking the tokens and then passing them to the Google sign in method from Firebase auth. Then we'll update their user data in Firestore, which we'll implement here in the next step, and then we'll flip the loading state to false.

The reason I put this in a separate method is that if you have multiple sign in options, you can reuse this code for each of them. And, basically, we're just making a reference to the same Firestore document, and then we're calling ref set data with whatever custom data we wanna put in there. I'm going to add a time stamp of the current date just so we can see that update when we sign in and sign out. And adding the merge true option will make this Structive update so it won't overwrite any existing user data in that document. And lastly, we can just call auth sign out to sign out the user.

So that takes care of our business logic for authentication. Now we can get to the really cool part, which is making Flutter reactive. We'll look at 2 different ways we can make the UI update when the values in those streams change. The first one we'll look at is a stateful widget, which works very similar to a React JS component if you're familiar with React. But first, we'll go into the buttons that we defined earlier and implement their on pressed event handlers.

That's as simple as calling auth service Google sign in and sign out inside of these functions. At this point, you should be able to sign in to the app with your Google account. And when you do that, you should also see the data updated in Firestore. The first thing we'll do is define a new widget called the user profile that extends stateful widget. The only thing this widget needs to do is call the create state method for the user profile state.

The next step is to define the state, which is the user profile state, and it extends the state class with the user profile that we just defined. Now this widget can listen to our global streams and then set its own internal state that we can actually show in the UI. In this demo, I'm just going to be really lazy with the UI, and we'll just show the user profile and the loading state as a string. Now when you set up listeners on a stream or observable, you usually wanna make sure that the state is initialized, which you can do inside the init date life cycle hook. So all we have to do here is call the auth service profile listen.

That will set up the subscription, and then that will give us the state from that subscription, and then we'll use it to call set state on the stateful widget. Set state is important, and it's built into stateful widgets, and it just tells the widget to rerender when it's called. So you should only use set state to update values on the widget. All the computation should be done outside of it. Then we can go ahead and do the exact same thing for the loading state from the auth service, And now the UI for this widget will rerender anytime the values in these streams change.

Now we don't have any UI in this widget yet, so let's go ahead and add that inside of its build function. Again, I'm being super lazy with the UI here, so I'm just setting up a column that has a container. Then we'll render out the underlying data as text widgets. So this is nice for debugging, but obviously not what you'd want in a real app. When we log in, we should see this object that's the data from Firestore, and then below that, we have false for the loading state.

You'll notice that even though we're logged in, we're still showing both the login button and the logout button. Instead of doing that in a stateful widget, We can actually do it in a state list widget using a thing called a stream builder. You'll also notice that it has a lot less complexity and boilerplate code than the stateful widget. The stream builder is a widget itself that takes 2 arguments. The first one is the stream to listen to, and then the second one is a function that will return some UI elements based on the state of the stream.

So for our login button, we want to listen to the user observable. And then if the user's logged in, we'll show the sign out button. If not, we'll show the sign in with Google button. So the builder function gives you 2 things to work with, the context and then the snapshot of the stream itself. In our case, the snapshot will be the user.

So we can see if the user has data, then we know that the user is logged in. Otherwise, we know the user is logged out. So we can actually just go and grab the material buttons that we already created, then put them into the corresponding spot in this conditional. So now whenever the stream emits a new value, it will just Automatically rerender based on this logic in the builder function. I'm gonna go ahead and wrap things up there.

If this video helped you, please like and Scribe. And I'm really curious to get your feedback on this video. My plan is to make a lot more Flutter videos in the future, but it's really based on what you guys wanna see. Make sure to grab the full source code from FireShip IO. Thanks Thanks for watching, and I will talk to you soon.
Welcome to the first ever Flutter video on this channel. Today, we'll start from scratch and build a user authentication system using Firebase Google sign in and Firestore. The UI is nothing special, but this video is important because it will show you how to handle real time streams of data from external sources and update the UI reactively. If you're new here, like and subscribe, and you can grab the full source code from FireShip IO. I'd like to start by saying that this video is intermediate level. So if you're brand new to Flutter, it might seem a little overwhelming. But don't worry because next week, I have a more gentle introduction plan that's typically for JavaScript and or TypeScript developers.
multimedia
streaming
video gaming
youtube
We're starting from scratch, so the first thing we'll do is run Flutter create from the command line to create a new app. We can then open up the app in Versus Code, and we'll have some configuration to do for the platforms we wanna use. In this case, we'll only be setting up Android, But the iOS setup is super easy, so feel free to do that if you're on a Mac. From here, we'll jump into the Firebase console, click on the Android button, and And then we'll need to set a package ID for our project.
That should be something like com, your company name followed by the app name. So io.fireship.lessnap in this case. The next thing we'll wanna do is generate a sign in certificate specifically for Google OAuth. We can generate it by copying and pasting this command. I'll link that in the full lesson and then going to the terminal and entering the command.
google
I'm not sure if this is a problem on my end or if the command is just outdated but it gives me an error if I try to use export cert and list together. If it works for you, then that's great. But if not, you'll wanna go in here and take out the list from the command. And then when prompted for a password, type in Android in all lowercase. And finally, copy and paste the same command, but this time delete export cert from it. That should give you an SHA one certificate that you can just copy and paste in there and then click the next step, and that will give us our Google services JSON file. We can download it and save it in the Android app directory inside of our Flutter project. Now getting back to Versus Code, we'll go into that Android directory. It should look something like this and then we'll open up the build Gradle file inside of the app directory. Inside this file, you'll see the application ID.
We'll wanna switch that to the application ID that we chose on Firebase. Then down at the very bottom, we will apply the plugin that's required for Google services. And lastly, we need to go up one level to the Android directory and you'll See another build Gradle file there.
google
In this one we need to find the dependencies and then add the class path that references the Google services plug in. Then the final thing we'll do is go into the pubspec YAML and add our actual dependencies for this project. For a Firebase mobile app, you'll almost always need Firebase core and analytics. And then we'll also bring in Firestore, Firebase auth, and Google sign in is its own plugin. And lastly, I'm adding RXDart which is optional but it gives you a lot of power when working with real time streams in Firebase. And we'll see direct examples of that throughout this lesson. At this point, let's go ahead and run Flutter run just to make sure we don't have any It's in the console or in the app itself. That should give us the default Flutter app that looks something like this. From here, we're going to transform this app into a login button that reacts to the user's authentication state.
In addition, this feature will save any custom data that we want to the Firestore database. For example, we might want to customize the user profile with a unique username or some other unique data or we might have additional relational data that we need to query based on the user's user ID.
databases
data management
Okay. So now let's write some code. First, I'm going into the main Dart file and I'm just going to delete pretty much everything in here. The only thing I wanna keep is the my app widget just so we have a container to display our button. So inside the material app, you'll see a body property. And in that, we can go ahead and set up a child that is a column. And the reason I'm using a column here is because we can add multiple widgets to it, and they'll just be stacked on top of each other. So basically, what we're going to do is just flush out our UI inside this widget array. We're going to need 2 different buttons. We'll have one to sign in with Google and then one to sign out. Every material button has an on pressed event handler that we can implement to do something when the user clicks on a button. Right now it does nothing, but we'll set that up in the next step. Then we'll go ahead and set up a second material button. This one will be to log out when the user is authenticated. It's the exact same widget just with some different coloring and text. So if we run the app at this point you should see the 2 buttons up here at the top of the view. If we want to center our buttons we can actually go into the column widget and adjust the main axis this alignment to center.
And that puts our buttons in the middle. Now it's time to switch gears and talk about the authentication logic. It's generally a good idea to separate your business logic from your UI or presentation logic. And that's exactly what we're going to do here by creating a new file called auth.
logic
Dart. Now Now Flutter is not very opinionated about the way you share global data or handle your state management, and you'll see a lot of examples out there that use Redux or inherited widgets. But when you're just prototyping, one of the easiest things to do is just expose a global variable. So that's what we're going to do here by creating an auth class, and then we'll go ahead and instantiate that as our auth service and just have that sit in the global name space. It's not a true singleton, but we will only instantiate it once and it will live outside of our actual widget tree. Inside the class itself, we'll start by defining some private members for Firebase and Google sign in.
Then the actual values that will be available to our widgets will all be either observables or streams. And it's also important that they are multi subscription streams or hot observables. In Dart, a stream is only able to handle 1 subscription by default, but we want to share these streams in potentially many different widgets globally throughout the app. So that's an important rule to follow if you're exposing a global stream. The observable user is the user that we get from Firebase authentication, while the profile is the custom user data that we save about that user in the database. And lastly, we'll create a subject for the loading state, which is just an observable that we can push new values to manually. So these 3 streams define our state, and then we'll have our widgets listen to them and then update the UI reactively. The next thing we'll do is just go over all the methods that are available on service. Google sign in will be used when the user taps a button and it will take them to their Google account so they can log in and authenticate. Update user data will update that user's record in Firestore, and sign out will assign the user out of Firebase.
google
streaming
systems
programming
security
The first thing we'll do is go up here to the constructor and define the user observable. So by default, Firebase has already given this to us as a stream, so we can just wrap it inside of observable. And that will change anytime the user signs in or signs out. Now in order to retrieve the user's profile from Firestore, we first need to know the value of their user ID. This is where Rx start is going to start making our life a lot easier because we can just use this switch map operator, which will listen to the value of the user observable, Then it will switch to a different observable, in this case, the observable of the Firestore data for that user. So we can just point to the user's collection, Grab the document with the corresponding user ID, grab the snapshots, and then I'm also going to map the snapshots to their actual data payload just for convenience here. When the user is not signed in, we're not going to have a user ID. So in that case, we want to return some observable data from switch map, which we can do with observable just and an empty object. So that gives us observables we can listen to in the widgets. Now we just need a way for the user to sign in. As soon as the user clicks on the Google sign in button, we're going to flip the loading state to Drew.
And we can do that by simply calling add on our loading stream. Then the next thing we'll do is just follow the steps required to get the user signed in. So first, we will call the Google sign in method, and that will trigger the sign in process. Once that's completed, it will give us the user's ID token and auth token. At this point, the user will be signed in with Google but not Firebase. But we can easily sign them into Firebase by just taking the tokens and then passing them to the Google sign in method from Firebase auth. Then we'll update their user data in Firestore, which we'll implement here in the next step, and then we'll flip the loading state to false.
google
The reason I put this in a separate method is that if you have multiple sign in options, you can reuse this code for each of them. And, basically, we're just making a reference to the same Firestore document, and then we're calling ref set data with whatever custom data we wanna put in there. I'm going to add a time stamp of the current date just so we can see that update when we sign in and sign out. And adding the merge true option will make this Structive update so it won't overwrite any existing user data in that document. And lastly, we can just call auth sign out to sign out the user. So that takes care of our business logic for authentication. Now we can get to the really cool part, which is making Flutter reactive. We'll look at 2 different ways we can make the UI update when the values in those streams change. The first one we'll look at is a stateful widget, which works very similar to a React JS component if you're familiar with React. But first, we'll go into the buttons that we defined earlier and implement their on pressed event handlers.
That's as simple as calling auth service Google sign in and sign out inside of these functions. At this point, you should be able to sign in to the app with your Google account. And when you do that, you should also see the data updated in Firestore. The first thing we'll do is define a new widget called the user profile that extends stateful widget.
google
The only thing this widget needs to do is call the create state method for the user profile state. The next step is to define the state, which is the user profile state, and it extends the state class with the user profile that we just defined.
Now this widget can listen to our global streams and then set its own internal state that we can actually show in the UI. In this demo, I'm just going to be really lazy with the UI, and we'll just show the user profile and the loading state as a string.
streaming
programming
Now when you set up listeners on a stream or observable, you usually wanna make sure that the state is initialized, which you can do inside the init date life cycle hook.
So all we have to do here is call the auth service profile listen. That will set up the subscription, and then that will give us the state from that subscription, and then we'll use it to call set state on the stateful widget. Set state is important, and it's built into stateful widgets, and it just tells the widget to rerender when it's called.
networking
telecommunications
So you should only use set state to update values on the widget.
All the computation should be done outside of it. Then we can go ahead and do the exact same thing for the loading state from the auth service, And now the UI for this widget will rerender anytime the values in these streams change. Now we don't have any UI in this widget yet, so let's go ahead and add that inside of its build function.
programming
Again, I'm being super lazy with the UI here, so I'm just setting up a column that has a container. Then we'll render out the underlying data as text widgets. So this is nice for debugging, but obviously not what you'd want in a real app. When we log in, we should see this object that's the data from Firestore, and then below that, we have false for the loading state. You'll notice that even though we're logged in, we're still showing both the login button and the logout button. Instead of doing that in a stateful widget, We can actually do it in a state list widget using a thing called a stream builder.
You'll also notice that it has a lot less complexity and boilerplate code than the stateful widget. The stream builder is a widget itself that takes 2 arguments. The first one is the stream to listen to, and then the second one is a function that will return some UI elements based on the state of the stream. So for our login button, we want to listen to the user observable. And then if the user's logged in, we'll show the sign out button.
streaming
programming
audio
visualization
If not, we'll show the sign in with Google button. So the builder function gives you 2 things to work with, the context and then the snapshot of the stream itself. In our case, the snapshot will be the user. So we can see if the user has data, then we know that the user is logged in.
visualization
Otherwise, we know the user is logged out. So we can actually just go and grab the material buttons that we already created, then put them into the corresponding spot in this conditional. So now whenever the stream emits a new value, it will just Automatically rerender based on this logic in the builder function. I'm gonna go ahead and wrap things up there. If this video helped you, please like and Scribe. And I'm really curious to get your feedback on this video. My plan is to make a lot more Flutter videos in the future, but it's really based on what you guys wanna see. Make sure to grab the full source code from FireShip IO.
youtube
video gaming
streaming
programming
Thanks Thanks for watching, and I will talk to you soon.
Welcome to the first ever Flutter video on this channel. Today, we'll start from scratch and build a user authentication system using Firebase Google sign in and Firestore. The UI is nothing special, but this video is important because it will show you how to handle real time streams of data from external sources and update the UI reactively. If you're new here, like and subscribe, and you can grab the full source code from FireShip IO. I'd like to start by saying that this video is intermediate level. So if you're brand new to Flutter, it might seem a little overwhelming. But don't worry because next week, I have a more gentle introduction plan that's typically for JavaScript and or TypeScript developers. We're starting from scratch, so the first thing we'll do is run Flutter create from the command line to create a new app. We can then open up the app in Versus Code, and we'll have some configuration to do for the platforms we wanna use. In this case, we'll only be setting up Android, But the iOS setup is super easy, so feel free to do that if you're on a Mac. From here, we'll jump into the Firebase console, click on the Android button, and And then we'll need to set a package ID for our project. That should be something like com, your company name followed by the app name. So io.fireship.lessnap in this case. The next thing we'll wanna do is generate a sign in certificate specifically for Google OAuth. We can generate it by copying and pasting this command. I'll link that in the full lesson and then going to the terminal and entering the command. I'm not sure if this is a problem on my end or if the command is just outdated but it gives me an error if I try to use export cert and list together. If it works for you, then that's great. But if not, you'll wanna go in here and take out the list from the command. And then when prompted for a password, type in Android in all lowercase. And finally, copy and paste the same command, but this time delete export cert from it. That should give you an SHA one certificate that you can just copy and paste in there and then click the next step, and that will give us our Google services JSON file. We can download it and save it in the Android app directory inside of our Flutter project. Now getting back to Versus Code, we'll go into that Android directory. It should look something like this and then we'll open up the build Gradle file inside of the app directory. Inside this file, you'll see the application ID. We'll wanna switch that to the application ID that we chose on Firebase. Then down at the very bottom, we will apply the plugin that's required for Google services. And lastly, we need to go up one level to the Android directory and you'll See another build Gradle file there. In this one we need to find the dependencies and then add the class path that references the Google services plug in. Then the final thing we'll do is go into the pubspec YAML and add our actual dependencies for this project. For a Firebase mobile app, you'll almost always need Firebase core and analytics. And then we'll also bring in Firestore, Firebase auth, and Google sign in is its own plugin. And lastly, I'm adding RXDart which is optional but it gives you a lot of power when working with real time streams in Firebase. And we'll see direct examples of that throughout this lesson. At this point, let's go ahead and run Flutter run just to make sure we don't have any It's in the console or in the app itself. That should give us the default Flutter app that looks something like this. From here, we're going to transform this app into a login button that reacts to the user's authentication state. In addition, this feature will save any custom data that we want to the Firestore database. For example, we might want to customize the user profile with a unique username or some other unique data or we might have additional relational data that we need to query based on the user's user ID. Okay. So now let's write some code. First, I'm going into the main Dart file and I'm just going to delete pretty much everything in here. The only thing I wanna keep is the my app widget just so we have a container to display our button. So inside the material app, you'll see a body property. And in that, we can go ahead and set up a child that is a column. And the reason I'm using a column here is because we can add multiple widgets to it, and they'll just be stacked on top of each other. So basically, what we're going to do is just flush out our UI inside this widget array. We're going to need 2 different buttons. We'll have one to sign in with Google and then one to sign out. Every material button has an on pressed event handler that we can implement to do something when the user clicks on a button. Right now it does nothing, but we'll set that up in the next step. Then we'll go ahead and set up a second material button. This one will be to log out when the user is authenticated. It's the exact same widget just with some different coloring and text. So if we run the app at this point you should see the 2 buttons up here at the top of the view. If we want to center our buttons we can actually go into the column widget and adjust the main axis this alignment to center. And that puts our buttons in the middle. Now it's time to switch gears and talk about the authentication logic. It's generally a good idea to separate your business logic from your UI or presentation logic. And that's exactly what we're going to do here by creating a new file called auth. Dart. Now Now Flutter is not very opinionated about the way you share global data or handle your state management, and you'll see a lot of examples out there that use Redux or inherited widgets. But when you're just prototyping, one of the easiest things to do is just expose a global variable. So that's what we're going to do here by creating an auth class, and then we'll go ahead and instantiate that as our auth service and just have that sit in the global name space. It's not a true singleton, but we will only instantiate it once and it will live outside of our actual widget tree. Inside the class itself, we'll start by defining some private members for Firebase and Google sign in. Then the actual values that will be available to our widgets will all be either observables or streams. And it's also important that they are multi subscription streams or hot observables. In Dart, a stream is only able to handle 1 subscription by default, but we want to share these streams in potentially many different widgets globally throughout the app. So that's an important rule to follow if you're exposing a global stream. The observable user is the user that we get from Firebase authentication, while the profile is the custom user data that we save about that user in the database. And lastly, we'll create a subject for the loading state, which is just an observable that we can push new values to manually. So these 3 streams define our state, and then we'll have our widgets listen to them and then update the UI reactively. The next thing we'll do is just go over all the methods that are available on service. Google sign in will be used when the user taps a button and it will take them to their Google account so they can log in and authenticate. Update user data will update that user's record in Firestore, and sign out will assign the user out of Firebase. The first thing we'll do is go up here to the constructor and define the user observable. So by default, Firebase has already given this to us as a stream, so we can just wrap it inside of observable. And that will change anytime the user signs in or signs out. Now in order to retrieve the user's profile from Firestore, we first need to know the value of their user ID. This is where Rx start is going to start making our life a lot easier because we can just use this switch map operator, which will listen to the value of the user observable, Then it will switch to a different observable, in this case, the observable of the Firestore data for that user. So we can just point to the user's collection, Grab the document with the corresponding user ID, grab the snapshots, and then I'm also going to map the snapshots to their actual data payload just for convenience here. When the user is not signed in, we're not going to have a user ID. So in that case, we want to return some observable data from switch map, which we can do with observable just and an empty object. So that gives us observables we can listen to in the widgets. Now we just need a way for the user to sign in. As soon as the user clicks on the Google sign in button, we're going to flip the loading state to Drew. And we can do that by simply calling add on our loading stream. Then the next thing we'll do is just follow the steps required to get the user signed in. So first, we will call the Google sign in method, and that will trigger the sign in process. Once that's completed, it will give us the user's ID token and auth token. At this point, the user will be signed in with Google but not Firebase. But we can easily sign them into Firebase by just taking the tokens and then passing them to the Google sign in method from Firebase auth. Then we'll update their user data in Firestore, which we'll implement here in the next step, and then we'll flip the loading state to false. The reason I put this in a separate method is that if you have multiple sign in options, you can reuse this code for each of them. And, basically, we're just making a reference to the same Firestore document, and then we're calling ref set data with whatever custom data we wanna put in there. I'm going to add a time stamp of the current date just so we can see that update when we sign in and sign out. And adding the merge true option will make this Structive update so it won't overwrite any existing user data in that document. And lastly, we can just call auth sign out to sign out the user. So that takes care of our business logic for authentication. Now we can get to the really cool part, which is making Flutter reactive. We'll look at 2 different ways we can make the UI update when the values in those streams change. The first one we'll look at is a stateful widget, which works very similar to a React JS component if you're familiar with React. But first, we'll go into the buttons that we defined earlier and implement their on pressed event handlers. That's as simple as calling auth service Google sign in and sign out inside of these functions. At this point, you should be able to sign in to the app with your Google account. And when you do that, you should also see the data updated in Firestore. The first thing we'll do is define a new widget called the user profile that extends stateful widget. The only thing this widget needs to do is call the create state method for the user profile state. The next step is to define the state, which is the user profile state, and it extends the state class with the user profile that we just defined. Now this widget can listen to our global streams and then set its own internal state that we can actually show in the UI. In this demo, I'm just going to be really lazy with the UI, and we'll just show the user profile and the loading state as a string. Now when you set up listeners on a stream or observable, you usually wanna make sure that the state is initialized, which you can do inside the init date life cycle hook. So all we have to do here is call the auth service profile listen. That will set up the subscription, and then that will give us the state from that subscription, and then we'll use it to call set state on the stateful widget. Set state is important, and it's built into stateful widgets, and it just tells the widget to rerender when it's called. So you should only use set state to update values on the widget. All the computation should be done outside of it. Then we can go ahead and do the exact same thing for the loading state from the auth service, And now the UI for this widget will rerender anytime the values in these streams change. Now we don't have any UI in this widget yet, so let's go ahead and add that inside of its build function. Again, I'm being super lazy with the UI here, so I'm just setting up a column that has a container. Then we'll render out the underlying data as text widgets. So this is nice for debugging, but obviously not what you'd want in a real app. When we log in, we should see this object that's the data from Firestore, and then below that, we have false for the loading state. You'll notice that even though we're logged in, we're still showing both the login button and the logout button. Instead of doing that in a stateful widget, We can actually do it in a state list widget using a thing called a stream builder. You'll also notice that it has a lot less complexity and boilerplate code than the stateful widget. The stream builder is a widget itself that takes 2 arguments. The first one is the stream to listen to, and then the second one is a function that will return some UI elements based on the state of the stream. So for our login button, we want to listen to the user observable. And then if the user's logged in, we'll show the sign out button. If not, we'll show the sign in with Google button. So the builder function gives you 2 things to work with, the context and then the snapshot of the stream itself. In our case, the snapshot will be the user. So we can see if the user has data, then we know that the user is logged in. Otherwise, we know the user is logged out. So we can actually just go and grab the material buttons that we already created, then put them into the corresponding spot in this conditional. So now whenever the stream emits a new value, it will just Automatically rerender based on this logic in the builder function. I'm gonna go ahead and wrap things up there. If this video helped you, please like and Scribe. And I'm really curious to get your feedback on this video. My plan is to make a lot more Flutter videos in the future, but it's really based on what you guys wanna see. Make sure to grab the full source code from FireShip IO. Thanks Thanks for watching, and I will talk to you soon.
Welcome
welcome
to
to
the
the
first
first
ever
ever
Flutter
flutter
video
video
on
on
this
this
channel.
channel
Today,
today
we'll
we'll
start
start
from
from
scratch
scratch
and
and
build
build
a
a
user
user
authentication
authentication
system
system
using
using
Firebase
firebase
Google
google
sign
sign
in
in
and
and
Firestore.
firestore
The
the
UI
ui
is
is
nothing
nothing
special,
special
but
but
this
this
video
video
is
is
important
important
because
because
it
it
will
will
show
show
you
you
how
how
to
to
handle
handle
real
real
time
time
streams
streams
of
of
data
data
from
from
external
external
sources
sources
and
and
update
update
the
the
UI
ui
reactively.
reactively
If
if
you're
you're
new
new
here,
here
like
like
and
and
subscribe,
subscribe
and
and
you
you
can
can
grab
grab
the
the
full
full
source
source
code
code
from
from
FireShip
fireship
IO.
io
I'd
i'd
like
like
to
to
start
start
by
by
saying
saying
that
that
this
this
video
video
is
is
intermediate
intermediate
level.
level
So
so
if
if
you're
you're
brand
brand
new
new
to
to
Flutter,
flutter
it
it
might
might
seem
seem
a
a
little
little
overwhelming.
overwhelming
But
but
don't
don't
worry
worry
because
because
next
next
week,
week
I
i
have
have
a
a
more
more
gentle
gentle
introduction
introduction
plan
plan
that's
that's
typically
typically
for
for
JavaScript
javascript
and
and
or
or
TypeScript
typescript
developers.
developers
We're
we're
starting
starting
from
from
scratch,
scratch
so
so
the
the
first
first
thing
thing
we'll
we'll
do
do
is
is
run
run
Flutter
flutter
create
create
from
from
the
the
command
command
line
line
to
to
create
create
a
a
new
new
app.
app
We
we
can
can
then
then
open
open
up
up
the
the
app
app
in
in
Versus
versus
Code,
code
and
and
we'll
we'll
have
have
some
some
configuration
configuration
to
to
do
do
for
for
the
the
platforms
platforms
we
we
wanna
wanna
use.
use
In
in
this
this
case,
case
we'll
we'll
only
only
be
be
setting
setting
up
up
Android,
android
But
but
the
the
iOS
ios
setup
setup
is
is
super
super
easy,
easy
so
so
feel
feel
free
free
to
to
do
do
that
that
if
if
you're
you're
on
on
a
a
Mac.
mac
From
from
here,
here
we'll
we'll
jump
jump
into
into
the
the
Firebase
firebase
console,
console
click
click
on
on
the
the
Android
android
button,
button
and
and
And
and
then
then
we'll
we'll
need
need
to
to
set
set
a
a
package
package
ID
id
for
for
our
our
project.
project
That
that
should
should
be
be
something
something
like
like
com,
com
your
your
company
company
name
name
followed
followed
by
by
the
the
app
app
name.
name
So
so
io.fireship.lessnap
io.fireship.lessnap
in
in
this
this
case.
case
The
the
next
next
thing
thing
we'll
we'll
wanna
wanna
do
do
is
is
generate
generate
a
a
sign
sign
in
in
certificate
certificate
specifically
specifically
for
for
Google
google
OAuth.
oauth
We
we
can
can
generate
generate
it
it
by
by
copying
copying
and
and
pasting
pasting
this
this
command.
command
I'll
i'll
link
link
that
that
in
in
the
the
full
full
lesson
lesson
and
and
then
then
going
going
to
to
the
the
terminal
terminal
and
and
entering
entering
the
the
command.
command
I'm
i'm
not
not
sure
sure
if
if
this
this
is
is
a
a
problem
problem
on
on
my
my
end
end
or
or
if
if
the
the
command
command
is
is
just
just
outdated
outdated
but
but
it
it
gives
gives
me
me
an
an
error
error
if
if
I
i
try
try
to
to
use
use
export
export
cert
cert
and
and
list
list
together.
together
If
if
it
it
works
works
for
for
you,
you
then
then
that's
that's
great.
great
But
but
if
if
not,
not
you'll
you'll
wanna
wanna
go
go
in
in
here
here
and
and
take
take
out
out
the
the
list
list
from
from
the
the
command.
command
And
and
then
then
when
when
prompted
prompted
for
for
a
a
password,
password
type
type
in
in
Android
android
in
in
all
all
lowercase.
lowercase
And
and
finally,
finally
copy
copy
and
and
paste
paste
the
the
same
same
command,
command
but
but
this
this
time
time
delete
delete
export
export
cert
cert
from
from
it.
it
That
that
should
should
give
give
you
you
an
an
SHA
sha
one
one
certificate
certificate
that
that
you
you
can
can
just
just
copy
copy
and
and
paste
paste
in
in
there
there
and
and
then
then
click
click
the
the
next
next
step,
step
and
and
that
that
will
will
give
give
us
us
our
our
Google
google
services
services
JSON
json
file.
file
We
we
can
can
download
download
it
it
and
and
save
save
it
it
in
in
the
the
Android
android
app
app
directory
directory
inside
inside
of
of
our
our
Flutter
flutter
project.
project
Now
now
getting
getting
back
back
to
to
Versus
versus
Code,
code
we'll
we'll
go
go
into
into
that
that
Android
android
directory.
directory
It
it
should
should
look
look
something
something
like
like
this
this
and
and
then
then
we'll
we'll
open
open
up
up
the
the
build
build
Gradle
gradle
file
file
inside
inside
of
of
the
the
app
app
directory.
directory
Inside
inside
this
this
file,
file
you'll
you'll
see
see
the
the
application
application
ID.
id
We'll
we'll
wanna
wanna
switch
switch
that
that
to
to
the
the
application
application
ID
id
that
that
we
we
chose
chose
on
on
Firebase.
firebase
Then
then
down
down
at
at
the
the
very
very
bottom,
bottom
we
we
will
will
apply
apply
the
the
plugin
plugin
that's
that's
required
required
for
for
Google
google
services.
services
And
and
lastly,
lastly
we
we
need
need
to
to
go
go
up
up
one
one
level
level
to
to
the
the
Android
android
directory
directory
and
and
you'll
you'll
See
see
another
another
build
build
Gradle
gradle
file
file
there.
there
In
in
this
this
one
one
we
we
need
need
to
to
find
find
the
the
dependencies
dependencies
and
and
then
then
add
add
the
the
class
class
path
path
that
that
references
references
the
the
Google
google
services
services
plug
plug
in.
in
Then
then
the
the
final
final
thing
thing
we'll
we'll
do
do
is
is
go
go
into
into
the
the
pubspec
pubspec
YAML
yaml
and
and
add
add
our
our
actual
actual
dependencies
dependencies
for
for
this
this
project.
project
For
for
a
a
Firebase
firebase
mobile
mobile
app,
app
you'll
you'll
almost
almost
always
always
need
need
Firebase
firebase
core
core
and
and
analytics.
analytics
And
and
then
then
we'll
we'll
also
also
bring
bring
in
in
Firestore,
firestore
Firebase
firebase
auth,
auth
and
and
Google
google
sign
sign
in
in
is
is
its
its
own
own
plugin.
plugin
And
and
lastly,
lastly
I'm
i'm
adding
adding
RXDart
rxdart
which
which
is
is
optional
optional
but
but
it
it
gives
gives
you
you
a
a
lot
lot
of
of
power
power
when
when
working
working
with
with
real
real
time
time
streams
streams
in
in
Firebase.
firebase
And
and
we'll
we'll
see
see
direct
direct
examples
examples
of
of
that
that
throughout
throughout
this
this
lesson.
lesson
At
at
this
this
point,
point
let's
let's
go
go
ahead
ahead
and
and
run
run
Flutter
flutter
run
run
just
just
to
to
make
make
sure
sure
we
we
don't
don't
have
have
any
any
It's
it's
in
in
the
the
console
console
or
or
in
in
the
the
app
app
itself.
itself
That
that
should
should
give
give
us
us
the
the
default
default
Flutter
flutter
app
app
that
that
looks
looks
something
something
like
like
this.
this
From
from
here,
here
we're
we're
going
going
to
to
transform
transform
this
this
app
app
into
into
a
a
login
login
button
button
that
that
reacts
reacts
to
to
the
the
user's
user's
authentication
authentication
state.
state
In
in
addition,
addition
this
this
feature
feature
will
will
save
save
any
any
custom
custom
data
data
that
that
we
we
want
want
to
to
the
the
Firestore
firestore
database.
database
For
for
example,
example
we
we
might
might
want
want
to
to
customize
customize
the
the
user
user
profile
profile
with
with
a
a
unique
unique
username
username
or
or
some
some
other
other
unique
unique
data
data
or
or
we
we
might
might
have
have
additional
additional
relational
relational
data
data
that
that
we
we
need
need
to
to
query
query
based
based
on
on
the
the
user's
user's
user
user
ID.
id
Okay.
okay
So
so
now
now
let's
let's
write
write
some
some
code.
code
First,
first
I'm
i'm
going
going
into
into
the
the
main
main
Dart
dart
file
file
and
and
I'm
i'm
just
just
going
going
to
to
delete
delete
pretty
pretty
much
much
everything
everything
in
in
here.
here
The
the
only
only
thing
thing
I
i
wanna
wanna
keep
keep
is
is
the
the
my
my
app
app
widget
widget
just
just
so
so
we
we
have
have
a
a
container
container
to
to
display
display
our
our
button.
button
So
so
inside
inside
the
the
material
material
app,
app
you'll
you'll
see
see
a
a
body
body
property.
property
And
and
in
in
that,
that
we
we
can
can
go
go
ahead
ahead
and
and
set
set
up
up
a
a
child
child
that
that
is
is
a
a
column.
column
And
and
the
the
reason
reason
I'm
i'm
using
using
a
a
column
column
here
here
is
is
because
because
we
we
can
can
add
add
multiple
multiple
widgets
widgets
to
to
it,
it
and
and
they'll
they'll
just
just
be
be
stacked
stacked
on
on
top
top
of
of
each
each
other.
other
So
so
basically,
basically
what
what
we're
we're
going
going
to
to
do
do
is
is
just
just
flush
flush
out
out
our
our
UI
ui
inside
inside
this
this
widget
widget
array.
array
We're
we're
going
going
to
to
need
need
2
2
different
different
buttons.
buttons
We'll
we'll
have
have
one
one
to
to
sign
sign
in
in
with
with
Google
google
and
and
then
then
one
one
to
to
sign
sign
out.
out
Every
every
material
material
button
button
has
has
an
an
on
on
pressed
pressed
event
event
handler
handler
that
that
we
we
can
can
implement
implement
to
to
do
do
something
something
when
when
the
the
user
user
clicks
clicks
on
on
a
a
button.
button
Right
right
now
now
it
it
does
does
nothing,
nothing
but
but
we'll
we'll
set
set
that
that
up
up
in
in
the
the
next
next
step.
step
Then
then
we'll
we'll
go
go
ahead
ahead
and
and
set
set
up
up
a
a
second
second
material
material
button.
button
This
this
one
one
will
will
be
be
to
to
log
log
out
out
when
when
the
the
user
user
is
is
authenticated.
authenticated
It's
it's
the
the
exact
exact
same
same
widget
widget
just
just
with
with
some
some
different
different
coloring
coloring
and
and
text.
text
So
so
if
if
we
we
run
run
the
the
app
app
at
at
this
this
point
point
you
you
should
should
see
see
the
the
2
2
buttons
buttons
up
up
here
here
at
at
the
the
top
top
of
of
the
the
view.
view
If
if
we
we
want
want
to
to
center
center
our
our
buttons
buttons
we
we
can
can
actually
actually
go
go
into
into
the
the
column
column
widget
widget
and
and
adjust
adjust
the
the
main
main
axis
axis
this
this
alignment
alignment
to
to
center.
center
And
and
that
that
puts
puts
our
our
buttons
buttons
in
in
the
the
middle.
middle
Now
now
it's
it's
time
time
to
to
switch
switch
gears
gears
and
and
talk
talk
about
about
the
the
authentication
authentication
logic.
logic
It's
it's
generally
generally
a
a
good
good
idea
idea
to
to
separate
separate
your
your
business
business
logic
logic
from
from
your
your
UI
ui
or
or
presentation
presentation
logic.
logic
And
and
that's
that's
exactly
exactly
what
what
we're
we're
going
going
to
to
do
do
here
here
by
by
creating
creating
a
a
new
new
file
file
called
called
auth.
auth
Dart.
dart
Now
now
Now
now
Flutter
flutter
is
is
not
not
very
very
opinionated
opinionated
about
about
the
the
way
way
you
you
share
share
global
global
data
data
or
or
handle
handle
your
your
state
state
management,
management
and
and
you'll
you'll
see
see
a
a
lot
lot
of
of
examples
examples
out
out
there
there
that
that
use
use
Redux
redux
or
or
inherited
inherited
widgets.
widgets
But
but
when
when
you're
you're
just
just
prototyping,
prototyping
one
one
of
of
the
the
easiest
easiest
things
things
to
to
do
do
is
is
just
just
expose
expose
a
a
global
global
variable.
variable
So
so
that's
that's
what
what
we're
we're
going
going
to
to
do
do
here
here
by
by
creating
creating
an
an
auth
auth
class,
class
and
and
then
then
we'll
we'll
go
go
ahead
ahead
and
and
instantiate
instantiate
that
that
as
as
our
our
auth
auth
service
service
and
and
just
just
have
have
that
that
sit
sit
in
in
the
the
global
global
name
name
space.
space
It's
it's
not
not
a
a
true
true
singleton,
singleton
but
but
we
we
will
will
only
only
instantiate
instantiate
it
it
once
once
and
and
it
it
will
will
live
live
outside
outside
of
of
our
our
actual
actual
widget
widget
tree.
tree
Inside
inside
the
the
class
class
itself,
itself
we'll
we'll
start
start
by
by
defining
defining
some
some
private
private
members
members
for
for
Firebase
firebase
and
and
Google
google
sign
sign
in.
in
Then
then
the
the
actual
actual
values
values
that
that
will
will
be
be
available
available
to
to
our
our
widgets
widgets
will
will
all
all
be
be
either
either
observables
observables
or
or
streams.
streams
And
and
it's
it's
also
also
important
important
that
that
they
they
are
are
multi
multi
subscription
subscription
streams
streams
or
or
hot
hot
observables.
observables
In
in
Dart,
dart
a
a
stream
stream
is
is
only
only
able
able
to
to
handle
handle
1
1
subscription
subscription
by
by
default,
default
but
but
we
we
want
want
to
to
share
share
these
these
streams
streams
in
in
potentially
potentially
many
many
different
different
widgets
widgets
globally
globally
throughout
throughout
the
the
app.
app
So
so
that's
that's
an
an
important
important
rule
rule
to
to
follow
follow
if
if
you're
you're
exposing
exposing
a
a
global
global
stream.
stream
The
the
observable
observable
user
user
is
is
the
the
user
user
that
that
we
we
get
get
from
from
Firebase
firebase
authentication,
authentication
while
while
the
the
profile
profile
is
is
the
the
custom
custom
user
user
data
data
that
that
we
we
save
save
about
about
that
that
user
user
in
in
the
the
database.
database
And
and
lastly,
lastly
we'll
we'll
create
create
a
a
subject
subject
for
for
the
the
loading
loading
state,
state
which
which
is
is
just
just
an
an
observable
observable
that
that
we
we
can
can
push
push
new
new
values
values
to
to
manually.
manually
So
so
these
these
3
3
streams
streams
define
define
our
our
state,
state
and
and
then
then
we'll
we'll
have
have
our
our
widgets
widgets
listen
listen
to
to
them
them
and
and
then
then
update
update
the
the
UI
ui
reactively.
reactively
The
the
next
next
thing
thing
we'll
we'll
do
do
is
is
just
just
go
go
over
over
all
all
the
the
methods
methods
that
that
are
are
available
available
on
on
service.
service
Google
google
sign
sign
in
in
will
will
be
be
used
used
when
when
the
the
user
user
taps
taps
a
a
button
button
and
and
it
it
will
will
take
take
them
them
to
to
their
their
Google
google
account
account
so
so
they
they
can
can
log
log
in
in
and
and
authenticate.
authenticate
Update
update
user
user
data
data
will
will
update
update
that
that
user's
user's
record
record
in
in
Firestore,
firestore
and
and
sign
sign
out
out
will
will
assign
assign
the
the
user
user
out
out
of
of
Firebase.
firebase
The
the
first
first
thing
thing
we'll
we'll
do
do
is
is
go
go
up
up
here
here
to
to
the
the
constructor
constructor
and
and
define
define
the
the
user
user
observable.
observable
So
so
by
by
default,
default
Firebase
firebase
has
has
already
already
given
given
this
this
to
to
us
us
as
as
a
a
stream,
stream
so
so
we
we
can
can
just
just
wrap
wrap
it
it
inside
inside
of
of
observable.
observable
And
and
that
that
will
will
change
change
anytime
anytime
the
the
user
user
signs
signs
in
in
or
or
signs
signs
out.
out
Now
now
in
in
order
order
to
to
retrieve
retrieve
the
the
user's
user's
profile
profile
from
from
Firestore,
firestore
we
we
first
first
need
need
to
to
know
know
the
the
value
value
of
of
their
their
user
user
ID.
id
This
this
is
is
where
where
Rx
rx
start
start
is
is
going
going
to
to
start
start
making
making
our
our
life
life
a
a
lot
lot
easier
easier
because
because
we
we
can
can
just
just
use
use
this
this
switch
switch
map
map
operator,
operator
which
which
will
will
listen
listen
to
to
the
the
value
value
of
of
the
the
user
user
observable,
observable
Then
then
it
it
will
will
switch
switch
to
to
a
a
different
different
observable,
observable
in
in
this
this
case,
case
the
the
observable
observable
of
of
the
the
Firestore
firestore
data
data
for
for
that
that
user.
user
So
so
we
we
can
can
just
just
point
point
to
to
the
the
user's
user's
collection,
collection
Grab
grab
the
the
document
document
with
with
the
the
corresponding
corresponding
user
user
ID,
id
grab
grab
the
the
snapshots,
snapshots
and
and
then
then
I'm
i'm
also
also
going
going
to
to
map
map
the
the
snapshots
snapshots
to
to
their
their
actual
actual
data
data
payload
payload
just
just
for
for
convenience
convenience
here.
here
When
when
the
the
user
user
is
is
not
not
signed
signed
in,
in
we're
we're
not
not
going
going
to
to
have
have
a
a
user
user
ID.
id
So
so
in
in
that
that
case,
case
we
we
want
want
to
to
return
return
some
some
observable
observable
data
data
from
from
switch
switch
map,
map
which
which
we
we
can
can
do
do
with
with
observable
observable
just
just
and
and
an
an
empty
empty
object.
object
So
so
that
that
gives
gives
us
us
observables
observables
we
we
can
can
listen
listen
to
to
in
in
the
the
widgets.
widgets
Now
now
we
we
just
just
need
need
a
a
way
way
for
for
the
the
user
user
to
to
sign
sign
in.
in
As
as
soon
soon
as
as
the
the
user
user
clicks
clicks
on
on
the
the
Google
google
sign
sign
in
in
button,
button
we're
we're
going
going
to
to
flip
flip
the
the
loading
loading
state
state
to
to
Drew.
drew
And
and
we
we
can
can
do
do
that
that
by
by
simply
simply
calling
calling
add
add
on
on
our
our
loading
loading
stream.
stream
Then
then
the
the
next
next
thing
thing
we'll
we'll
do
do
is
is
just
just
follow
follow
the
the
steps
steps
required
required
to
to
get
get
the
the
user
user
signed
signed
in.
in
So
so
first,
first
we
we
will
will
call
call
the
the
Google
google
sign
sign
in
in
method,
method
and
and
that
that
will
will
trigger
trigger
the
the
sign
sign
in
in
process.
process
Once
once
that's
that's
completed,
completed
it
it
will
will
give
give
us
us
the
the
user's
user's
ID
id
token
token
and
and
auth
auth
token.
token
At
at
this
this
point,
point
the
the
user
user
will
will
be
be
signed
signed
in
in
with
with
Google
google
but
but
not
not
Firebase.
firebase
But
but
we
we
can
can
easily
easily
sign
sign
them
them
into
into
Firebase
firebase
by
by
just
just
taking
taking
the
the
tokens
tokens
and
and
then
then
passing
passing
them
them
to
to
the
the
Google
google
sign
sign
in
in
method
method
from
from
Firebase
firebase
auth.
auth
Then
then
we'll
we'll
update
update
their
their
user
user
data
data
in
in
Firestore,
firestore
which
which
we'll
we'll
implement
implement
here
here
in
in
the
the
next
next
step,
step
and
and
then
then
we'll
we'll
flip
flip
the
the
loading
loading
state
state
to
to
false.
false
The
the
reason
reason
I
i
put
put
this
this
in
in
a
a
separate
separate
method
method
is
is
that
that
if
if
you
you
have
have
multiple
multiple
sign
sign
in
in
options,
options
you
you
can
can
reuse
reuse
this
this
code
code
for
for
each
each
of
of
them.
them
And,
and
basically,
basically
we're
we're
just
just
making
making
a
a
reference
reference
to
to
the
the
same
same
Firestore
firestore
document,
document
and
and
then
then
we're
we're
calling
calling
ref
ref
set
set
data
data
with
with
whatever
whatever
custom
custom
data
data
we
we
wanna
wanna
put
put
in
in
there.
there
I'm
i'm
going
going
to
to
add
add
a
a
time
time
stamp
stamp
of
of
the
the
current
current
date
date
just
just
so
so
we
we
can
can
see
see
that
that
update
update
when
when
we
we
sign
sign
in
in
and
and
sign
sign
out.
out
And
and
adding
adding
the
the
merge
merge
true
true
option
option
will
will
make
make
this
this
Structive
structive
update
update
so
so
it
it
won't
won't
overwrite
overwrite
any
any
existing
existing
user
user
data
data
in
in
that
that
document.
document
And
and
lastly,
lastly
we
we
can
can
just
just
call
call
auth
auth
sign
sign
out
out
to
to
sign
sign
out
out
the
the
user.
user
So
so
that
that
takes
takes
care
care
of
of
our
our
business
business
logic
logic
for
for
authentication.
authentication
Now
now
we
we
can
can
get
get
to
to
the
the
really
really
cool
cool
part,
part
which
which
is
is
making
making
Flutter
flutter
reactive.
reactive
We'll
we'll
look
look
at
at
2
2
different
different
ways
ways
we
we
can
can
make
make
the
the
UI
ui
update
update
when
when
the
the
values
values
in
in
those
those
streams
streams
change.
change
The
the
first
first
one
one
we'll
we'll
look
look
at
at
is
is
a
a
stateful
stateful
widget,
widget
which
which
works
works
very
very
similar
similar
to
to
a
a
React
react
JS
js
component
component
if
if
you're
you're
familiar
familiar
with
with
React.
react
But
but
first,
first
we'll
we'll
go
go
into
into
the
the
buttons
buttons
that
that
we
we
defined
defined
earlier
earlier
and
and
implement
implement
their
their
on
on
pressed
pressed
event
event
handlers.
handlers
That's
that's
as
as
simple
simple
as
as
calling
calling
auth
auth
service
service
Google
google
sign
sign
in
in
and
and
sign
sign
out
out
inside
inside
of
of
these
these
functions.
functions
At
at
this
this
point,
point
you
you
should
should
be
be
able
able
to
to
sign
sign
in
in
to
to
the
the
app
app
with
with
your
your
Google
google
account.
account
And
and
when
when
you
you
do
do
that,
that
you
you
should
should
also
also
see
see
the
the
data
data
updated
updated
in
in
Firestore.
firestore
The
the
first
first
thing
thing
we'll
we'll
do
do
is
is
define
define
a
a
new
new
widget
widget
called
called
the
the
user
user
profile
profile
that
that
extends
extends
stateful
stateful
widget.
widget
The
the
only
only
thing
thing
this
this
widget
widget
needs
needs
to
to
do
do
is
is
call
call
the
the
create
create
state
state
method
method
for
for
the
the
user
user
profile
profile
state.
state
The
the
next
next
step
step
is
is
to
to
define
define
the
the
state,
state
which
which
is
is
the
the
user
user
profile
profile
state,
state
and
and
it
it
extends
extends
the
the
state
state
class
class
with
with
the
the
user
user
profile
profile
that
that
we
we
just
just
defined.
defined
Now
now
this
this
widget
widget
can
can
listen
listen
to
to
our
our
global
global
streams
streams
and
and
then
then
set
set
its
its
own
own
internal
internal
state
state
that
that
we
we
can
can
actually
actually
show
show
in
in
the
the
UI.
ui
In
in
this
this
demo,
demo
I'm
i'm
just
just
going
going
to
to
be
be
really
really
lazy
lazy
with
with
the
the
UI,
ui
and
and
we'll
we'll
just
just
show
show
the
the
user
user
profile
profile
and
and
the
the
loading
loading
state
state
as
as
a
a
string.
string
Now
now
when
when
you
you
set
set
up
up
listeners
listeners
on
on
a
a
stream
stream
or
or
observable,
observable
you
you
usually
usually
wanna
wanna
make
make
sure
sure
that
that
the
the
state
state
is
is
initialized,
initialized
which
which
you
you
can
can
do
do
inside
inside
the
the
init
init
date
date
life
life
cycle
cycle
hook.
hook
So
so
all
all
we
we
have
have
to
to
do
do
here
here
is
is
call
call
the
the
auth
auth
service
service
profile
profile
listen.
listen
That
that
will
will
set
set
up
up
the
the
subscription,
subscription
and
and
then
then
that
that
will
will
give
give
us
us
the
the
state
state
from
from
that
that
subscription,
subscription
and
and
then
then
we'll
we'll
use
use
it
it
to
to
call
call
set
set
state
state
on
on
the
the
stateful
stateful
widget.
widget
Set
set
state
state
is
is
important,
important
and
and
it's
it's
built
built
into
into
stateful
stateful
widgets,
widgets
and
and
it
it
just
just
tells
tells
the
the
widget
widget
to
to
rerender
rerender
when
when
it's
it's
called.
called
So
so
you
you
should
should
only
only
use
use
set
set
state
state
to
to
update
update
values
values
on
on
the
the
widget.
widget
All
all
the
the
computation
computation
should
should
be
be
done
done
outside
outside
of
of
it.
it
Then
then
we
we
can
can
go
go
ahead
ahead
and
and
do
do
the
the
exact
exact
same
same
thing
thing
for
for
the
the
loading
loading
state
state
from
from
the
the
auth
auth
service,
service
And
and
now
now
the
the
UI
ui
for
for
this
this
widget
widget
will
will
rerender
rerender
anytime
anytime
the
the
values
values
in
in
these
these
streams
streams
change.
change
Now
now
we
we
don't
don't
have
have
any
any
UI
ui
in
in
this
this
widget
widget
yet,
yet
so
so
let's
let's
go
go
ahead
ahead
and
and
add
add
that
that
inside
inside
of
of
its
its
build
build
function.
function
Again,
again
I'm
i'm
being
being
super
super
lazy
lazy
with
with
the
the
UI
ui
here,
here
so
so
I'm
i'm
just
just
setting
setting
up
up
a
a
column
column
that
that
has
has
a
a
container.
container
Then
then
we'll
we'll
render
render
out
out
the
the
underlying
underlying
data
data
as
as
text
text
widgets.
widgets
So
so
this
this
is
is
nice
nice
for
for
debugging,
debugging
but
but
obviously
obviously
not
not
what
what
you'd
you'd
want
want
in
in
a
a
real
real
app.
app
When
when
we
we
log
log
in,
in
we
we
should
should
see
see
this
this
object
object
that's
that's
the
the
data
data
from
from
Firestore,
firestore
and
and
then
then
below
below
that,
that
we
we
have
have
false
false
for
for
the
the
loading
loading
state.
state
You'll
you'll
notice
notice
that
that
even
even
though
though
we're
we're
logged
logged
in,
in
we're
we're
still
still
showing
showing
both
both
the
the
login
login
button
button
and
and
the
the
logout
logout
button.
button
Instead
instead
of
of
doing
doing
that
that
in
in
a
a
stateful
stateful
widget,
widget
We
we
can
can
actually
actually
do
do
it
it
in
in
a
a
state
state
list
list
widget
widget
using
using
a
a
thing
thing
called
called
a
a
stream
stream
builder.
builder
You'll
you'll
also
also
notice
notice
that
that
it
it
has
has
a
a
lot
lot
less
less
complexity
complexity
and
and
boilerplate
boilerplate
code
code
than
than
the
the
stateful
stateful
widget.
widget
The
the
stream
stream
builder
builder
is
is
a
a
widget
widget
itself
itself
that
that
takes
takes
2
2
arguments.
arguments
The
the
first
first
one
one
is
is
the
the
stream
stream
to
to
listen
listen
to,
to
and
and
then
then
the
the
second
second
one
one
is
is
a
a
function
function
that
that
will
will
return
return
some
some
UI
ui
elements
elements
based
based
on
on
the
the
state
state
of
of
the
the
stream.
stream
So
so
for
for
our
our
login
login
button,
button
we
we
want
want
to
to
listen
listen
to
to
the
the
user
user
observable.
observable
And
and
then
then
if
if
the
the
user's
user's
logged
logged
in,
in
we'll
we'll
show
show
the
the
sign
sign
out
out
button.
button
If
if
not,
not
we'll
we'll
show
show
the
the
sign
sign
in
in
with
with
Google
google
button.
button
So
so
the
the
builder
builder
function
function
gives
gives
you
you
2
2
things
things
to
to
work
work
with,
with
the
the
context
context
and
and
then
then
the
the
snapshot
snapshot
of
of
the
the
stream
stream
itself.
itself
In
in
our
our
case,
case
the
the
snapshot
snapshot
will
will
be
be
the
the
user.
user
So
so
we
we
can
can
see
see
if
if
the
the
user
user
has
has
data,
data
then
then
we
we
know
know
that
that
the
the
user
user
is
is
logged
logged
in.
in
Otherwise,
otherwise
we
we
know
know
the
the
user
user
is
is
logged
logged
out.
out
So
so
we
we
can
can
actually
actually
just
just
go
go
and
and
grab
grab
the
the
material
material
buttons
buttons
that
that
we
we
already
already
created,
created
then
then
put
put
them
them
into
into
the
the
corresponding
corresponding
spot
spot
in
in
this
this
conditional.
conditional
So
so
now
now
whenever
whenever
the
the
stream
stream
emits
emits
a
a
new
new
value,
value
it
it
will
will
just
just
Automatically
automatically
rerender
rerender
based
based
on
on
this
this
logic
logic
in
in
the
the
builder
builder
function.
function
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
Scribe.
scribe
And
and
I'm
i'm
really
really
curious
curious
to
to
get
get
your
your
feedback
feedback
on
on
this
this
video.
video
My
my
plan
plan
is
is
to
to
make
make
a
a
lot
lot
more
more
Flutter
flutter
videos
videos
in
in
the
the
future,
future
but
but
it's
it's
really
really
based
based
on
on
what
what
you
you
guys
guys
wanna
wanna
see.
see
Make
make
sure
sure
to
to
grab
grab
the
the
full
full
source
source
code
code
from
from
FireShip
fireship
IO.
io
Thanks
thanks
Thanks
thanks
for
for
watching,
watching
and
and
I
i
will
will
talk
talk
to
to
you
you
soon.
soon
success
The Flutter app is designed to use as an intermediate for developers to create a sign-in certificate, generate a sign-in certificate, and add the required plugin to Flutter app. Flutter app is used to transform an app into a login button and save custom data, and code a new widget to update the UI reactively. The process of setting up a second material button and updating user data is discussed, along with the use of multiple streams to handle subscriptions and the switch map operator to update user data. The speakers also explain the process of updating the loading state and updating the loading state, and provide information on signing in and updating user data in Firwork. Viewers are encouraged to like and subscribe to their videos.
Flutter - Google SignIn from Scratch
Welcome to the first ever Flutter video on this channel. Today, we'll start from scratch and build a user authentication system using Firebase Google sign in and Firestore. The UI is nothing special, but this video is important because it will show you how to handle real time streams of data from external sources and update the UI reactively. If you're new here, like and subscribe, and you can grab the full source code from FireShip IO. I'd like to start by saying that this video is intermediate level. So if you're brand new to Flutter, it might seem a little overwhelming. But don't worry because next week, I have a more gentle introduction plan that's typically for JavaScript and or TypeScript developers. We're starting from scratch, so the first thing we'll do is run Flutter create from the command line to create a new app. We can then open up the app in Versus Code, and we'll have some configuration to do for the platforms we wanna use. In this case, we'll only be setting up Android, But the iOS setup is super easy, so feel free to do that if you're on a Mac. From here, we'll jump into the Firebase console, click on the Android button, and And then we'll need to set a package ID for our project. That should be something like com, your company name followed by the app name. So io.fireship.lessnap in this case. The next thing we'll wanna do is generate a sign in certificate specifically for Google OAuth. We can generate it by copying and pasting this command. I'll link that in the full lesson and then going to the terminal and entering the command. I'm not sure if this is a problem on my end or if the command is just outdated but it gives me an error if I try to use export cert and list together. If it works for you, then that's great. But if not, you'll wanna go in here and take out the list from the command. And then when prompted for a password, type in Android in all lowercase. And finally, copy and paste the same command, but this time delete export cert from it. That should give you an SHA one certificate that you can just copy and paste in there and then click the next step, and that will give us our Google services JSON file. We can download it and save it in the Android app directory inside of our Flutter project. Now getting back to Versus Code, we'll go into that Android directory. It should look something like this and then we'll open up the build Gradle file inside of the app directory. Inside this file, you'll see the application ID. We'll wanna switch that to the application ID that we chose on Firebase. Then down at the very bottom, we will apply the plugin that's required for Google services. And lastly, we need to go up one level to the Android directory and you'll See another build Gradle file there. In this one we need to find the dependencies and then add the class path that references the Google services plug in. Then the final thing we'll do is go into the pubspec YAML and add our actual dependencies for this project. For a Firebase mobile app, you'll almost always need Firebase core and analytics. And then we'll also bring in Firestore, Firebase auth, and Google sign in is its own plugin. And lastly, I'm adding RXDart which is optional but it gives you a lot of power when working with real time streams in Firebase. And we'll see direct examples of that throughout this lesson. At this point, let's go ahead and run Flutter run just to make sure we don't have any It's in the console or in the app itself. That should give us the default Flutter app that looks something like this. From here, we're going to transform this app into a login button that reacts to the user's authentication state. In addition, this feature will save any custom data that we want to the Firestore database. For example, we might want to customize the user profile with a unique username or some other unique data or we might have additional relational data that we need to query based on the user's user ID. Okay. So now let's write some code. First, I'm going into the main Dart file and I'm just going to delete pretty much everything in here. The only thing I wanna keep is the my app widget just so we have a container to display our button. So inside the material app, you'll see a body property. And in that, we can go ahead and set up a child that is a column. And the reason I'm using a column here is because we can add multiple widgets to it, and they'll just be stacked on top of each other. So basically, what we're going to do is just flush out our UI inside this widget array. We're going to need 2 different buttons. We'll have one to sign in with Google and then one to sign out. Every material button has an on pressed event handler that we can implement to do something when the user clicks on a button. Right now it does nothing, but we'll set that up in the next step. Then we'll go ahead and set up a second material button. This one will be to log out when the user is authenticated. It's the exact same widget just with some different coloring and text. So if we run the app at this point you should see the 2 buttons up here at the top of the view. If we want to center our buttons we can actually go into the column widget and adjust the main axis this alignment to center. And that puts our buttons in the middle. Now it's time to switch gears and talk about the authentication logic. It's generally a good idea to separate your business logic from your UI or presentation logic. And that's exactly what we're going to do here by creating a new file called auth. Dart. Now Now Flutter is not very opinionated about the way you share global data or handle your state management, and you'll see a lot of examples out there that use Redux or inherited widgets. But when you're just prototyping, one of the easiest things to do is just expose a global variable. So that's what we're going to do here by creating an auth class, and then we'll go ahead and instantiate that as our auth service and just have that sit in the global name space. It's not a true singleton, but we will only instantiate it once and it will live outside of our actual widget tree. Inside the class itself, we'll start by defining some private members for Firebase and Google sign in. Then the actual values that will be available to our widgets will all be either observables or streams. And it's also important that they are multi subscription streams or hot observables. In Dart, a stream is only able to handle 1 subscription by default, but we want to share these streams in potentially many different widgets globally throughout the app. So that's an important rule to follow if you're exposing a global stream. The observable user is the user that we get from Firebase authentication, while the profile is the custom user data that we save about that user in the database. And lastly, we'll create a subject for the loading state, which is just an observable that we can push new values to manually. So these 3 streams define our state, and then we'll have our widgets listen to them and then update the UI reactively. The next thing we'll do is just go over all the methods that are available on service. Google sign in will be used when the user taps a button and it will take them to their Google account so they can log in and authenticate. Update user data will update that user's record in Firestore, and sign out will assign the user out of Firebase. The first thing we'll do is go up here to the constructor and define the user observable. So by default, Firebase has already given this to us as a stream, so we can just wrap it inside of observable. And that will change anytime the user signs in or signs out. Now in order to retrieve the user's profile from Firestore, we first need to know the value of their user ID. This is where Rx start is going to start making our life a lot easier because we can just use this switch map operator, which will listen to the value of the user observable, Then it will switch to a different observable, in this case, the observable of the Firestore data for that user. So we can just point to the user's collection, Grab the document with the corresponding user ID, grab the snapshots, and then I'm also going to map the snapshots to their actual data payload just for convenience here. When the user is not signed in, we're not going to have a user ID. So in that case, we want to return some observable data from switch map, which we can do with observable just and an empty object. So that gives us observables we can listen to in the widgets. Now we just need a way for the user to sign in. As soon as the user clicks on the Google sign in button, we're going to flip the loading state to Drew. And we can do that by simply calling add on our loading stream. Then the next thing we'll do is just follow the steps required to get the user signed in. So first, we will call the Google sign in method, and that will trigger the sign in process. Once that's completed, it will give us the user's ID token and auth token. At this point, the user will be signed in with Google but not Firebase. But we can easily sign them into Firebase by just taking the tokens and then passing them to the Google sign in method from Firebase auth. Then we'll update their user data in Firestore, which we'll implement here in the next step, and then we'll flip the loading state to false. The reason I put this in a separate method is that if you have multiple sign in options, you can reuse this code for each of them. And, basically, we're just making a reference to the same Firestore document, and then we're calling ref set data with whatever custom data we wanna put in there. I'm going to add a time stamp of the current date just so we can see that update when we sign in and sign out. And adding the merge true option will make this Structive update so it won't overwrite any existing user data in that document. And lastly, we can just call auth sign out to sign out the user. So that takes care of our business logic for authentication. Now we can get to the really cool part, which is making Flutter reactive. We'll look at 2 different ways we can make the UI update when the values in those streams change. The first one we'll look at is a stateful widget, which works very similar to a React JS component if you're familiar with React. But first, we'll go into the buttons that we defined earlier and implement their on pressed event handlers. That's as simple as calling auth service Google sign in and sign out inside of these functions. At this point, you should be able to sign in to the app with your Google account. And when you do that, you should also see the data updated in Firestore. The first thing we'll do is define a new widget called the user profile that extends stateful widget. The only thing this widget needs to do is call the create state method for the user profile state. The next step is to define the state, which is the user profile state, and it extends the state class with the user profile that we just defined. Now this widget can listen to our global streams and then set its own internal state that we can actually show in the UI. In this demo, I'm just going to be really lazy with the UI, and we'll just show the user profile and the loading state as a string. Now when you set up listeners on a stream or observable, you usually wanna make sure that the state is initialized, which you can do inside the init date life cycle hook. So all we have to do here is call the auth service profile listen. That will set up the subscription, and then that will give us the state from that subscription, and then we'll use it to call set state on the stateful widget. Set state is important, and it's built into stateful widgets, and it just tells the widget to rerender when it's called. So you should only use set state to update values on the widget. All the computation should be done outside of it. Then we can go ahead and do the exact same thing for the loading state from the auth service, And now the UI for this widget will rerender anytime the values in these streams change. Now we don't have any UI in this widget yet, so let's go ahead and add that inside of its build function. Again, I'm being super lazy with the UI here, so I'm just setting up a column that has a container. Then we'll render out the underlying data as text widgets. So this is nice for debugging, but obviously not what you'd want in a real app. When we log in, we should see this object that's the data from Firestore, and then below that, we have false for the loading state. You'll notice that even though we're logged in, we're still showing both the login button and the logout button. Instead of doing that in a stateful widget, We can actually do it in a state list widget using a thing called a stream builder. You'll also notice that it has a lot less complexity and boilerplate code than the stateful widget. The stream builder is a widget itself that takes 2 arguments. The first one is the stream to listen to, and then the second one is a function that will return some UI elements based on the state of the stream. So for our login button, we want to listen to the user observable. And then if the user's logged in, we'll show the sign out button. If not, we'll show the sign in with Google button. So the builder function gives you 2 things to work with, the context and then the snapshot of the stream itself. In our case, the snapshot will be the user. So we can see if the user has data, then we know that the user is logged in. Otherwise, we know the user is logged out. So we can actually just go and grab the material buttons that we already created, then put them into the corresponding spot in this conditional. So now whenever the stream emits a new value, it will just Automatically rerender based on this logic in the builder function. I'm gonna go ahead and wrap things up there. If this video helped you, please like and Scribe. And I'm really curious to get your feedback on this video. My plan is to make a lot more Flutter videos in the future, but it's really based on what you guys wanna see. Make sure to grab the full source code from FireShip IO. Thanks Thanks for watching, and I will talk to you soon.
The Flutter app is designed to use as an intermediate for developers to create a sign-in certificate, generate a sign-in certificate, and add the required plugin to Flutter app. Flutter app is used to transform an app into a login button and save custom data, and code a new widget to update the UI reactively. The process of setting up a second material button and updating user data is discussed, along with the use of multiple streams to handle subscriptions and the switch map operator to update user data. The speakers also explain the process of updating the loading state and updating the loading state, and provide information on signing in and updating user data in Firwork. Viewers are encouraged to like and subscribe to their videos.