 Hello everyone! In today's video, I'll be showing you the basics of firebase authentication. I'm first going to start with the demo here. I can give the demo a random email and a random password and we can hit sign up and it's going to register and log us in with that email. And once we're logged in, the sign up buttons and the login buttons are going to be grayed out because we don't want the user to be able to log in after they are already logged in. So instead, what we can do is we can now log out and we're going to be logged out and we can try to sign up using the same email again. And it should give us an error because we shouldn't register with an email that is already registered. Instead, we can log in and we're going to be logged in like that. All right, so the first thing we want to do is go to firebase console and create a new firebase project. So that's what I'm going to do. I'm going to give the project a name. Let's click continue and we don't need google analytics so we can just disable that. Hit create project and it's going to take a while to create so I'm just going to pause the video here. And it seems like our new project is ready. I'm just going to click continue and this should bring us to our firebase console. And once we're in the firebase console, I'm going to click on authentication on the left pane and let's go and get started with this. So once you're using firebase authentication, you have access to all sorts of providers like you can sign in using Google, Facebook, GitHub and Microsoft and so many other different providers. But in today's video, we're just going to be focusing on the most basic form of authentication and that is using the email and password sign in method. So I'm going to enable this hit save. And once we're done with this, I'm just going to show you the users tab here. So the users tab will show you all of the existing users in this project, which we currently have none. And here you can create a new user by giving it an email and password. But this is not what we're going to be doing this video because we want to create new users from the react application front end. So let's come back here and let's make a connection between our firebase back and our react front end. So to do that, I'm going to go to the project overview and create a new connection by clicking on this web icon here. So this will prompt us to create a new web app, which I'm going to name react app front end. You can name this anything you want. I'm not going to set up firebase hosting. I'm just going to click register app and give it a minute or so. And it's done and it's telling us to install firebase using npm, which I'm going to do, but I'm going to use yarn instead. So I'm going to come to my app here. This is my app right now. It's basically a create react app template. I've gotten rid of all of the nonsense files that we don't need. And this is what it looks like in the browser. It looks like an empty page. I'm going to my terminal here and let's say yarn add firebase. If you're using npm, you'll be doing npm install firebase. And while this is running, I'm going to go back to my console here and copy my API key. So you'll want to be copying your own API key here. And then I'm going to come to my VS code and create a new file called firebase.js and paste in all of the code here. The first thing you're going to notice about the code is it has a big todo here that tells you to add the SDK for the specific firebase services that you want to use. So the thing about firebase is that you have so many different types of services. You can use authentication, cloud firestore, real-time database, storage, hosting functions, all sorts of things. So I'm going to be importing a single module here called firebase slash auth. Now this is the code for all stuff related to firebase authentication. And in order to perform any sorts of operations, we first have to get a handle from firebase authentication, which is what I'm going to get here. I'm going to get auth from firebase authentication. Now get auth is going to return the handle to us that we can use to perform all sorts of authentication functionalities. So I'm going to store this in a variable called auth and run get auth like that. Now that we have our authentication handle, I'm going to define a new function here called signup. It's going to take in an email and password. I'm also going to export this function so that we can use this function from other components such as app.js. I'm going to import something from firebase slash auth called create user with email and password. And this is what we're going to be running from our function called signup here. And whenever you're running any sorts of operations or functions that you're importing from firebase slash auth, you'll always want to provide the authentication handle as the first argument in these functions. I'm also going to provide the email and the password. And I'm going to return this so that we can get the status of this if it succeeded or failed in creating a new user. Now that we have exported our signup function, I'm going to go over to app.js and import that function from dot slash firebase. I'm also going to want to get the email and passwords from the user because right now if I switch to my browser tab here, you can see we have an empty canvas. So I'm going to do input placeholder equals to email. Self close this. I'm also going to do one for password. Let's save and refresh. You can see that if I type my password in here, the password is going to be displayed in plain text, which is not what I want. So I can go and do a type of password. And it should be a type of password. So that's better. And I'm also going to wrap this in its own div with an ID. Actually, I'm just going to wrap it in its own divs here. And let's indent this properly. I'm going to give this div an ID of fields because right now I have my custom CSS here. It's pretty much just some really basic and simple styling because I don't want to bog down this video series with a whole bunch of styling like using bootstrap or even materialized. So let's make our button now do button. Let's do sign up. The button is going to have an on click. I think it's going to have an on click. And then we're going to have to handle sign up. So let's go and define that function right now called handle sign up. It's not going to do anything right now. So let's go and refresh this and we can type an email. We can type password, you can sign up, but nothing's going to happen because the function right now is blank. First thing we're going to do is make this function asynchronous because sign up is going to return a promise because sign up is an API call here to the Firebase authentication API. So I'm going to just do that. Let's do await, sign up, give it an email and password. So right now the thing you're going to notice is that email and password are underlined in red because it's undefined. We're not getting the email and password from the input fields here. So how do we get the values from the input fields using React? So the thing I'm going to be using is called use ref, import use ref from react. And I'm going to give this, I'm going to make two refs here. I'm going to make const of email ref equals use ref. So use ref is something that is specific to react. It's not really a Firebase thing. So if you don't really know what use refs are, you should probably go and check that out on Google before you continue this step. So email ref and password ref equals use ref. I'm going to give these inputs a ref value. It's going to be equal to email ref. I'm going to change the bottom one here to be password ref. So now that we've assigned this input fields to refs, what I can do is I can come to my sign up here and I can do email is email ref.current.value. So I'm getting the current value of the email input ref. And also for the password, I'm going to password the current.value. And we can save this. So let me check this. This should be working. One way to find out is go to our React application here. Let's type something at gmail.com and give it a random password. Let's hit sign up. Of course, we don't get any feedback. There's no feedback whatsoever. The only way we can check that is to go to console here and refresh. And we do in fact see that something at gmail.com appears in our database. So this is a good sign. It means that our sign up is working. But the thing is right now, if I try to sign up again, you can see that it's going to crash in our faces. And this is generally not something you want to happen when your user is using your actual application because you see email is already in use. So the way we can catch these errors without the app just crashing on the user's face is of course to use the try catch technique. So we can do try. We can try to await sign up. If this doesn't work, we're going to catch the error. And you're just going to do a simple alert that says error, a generic error message here. We can fix that in the future. But right now, if I come back here, reload this and let's try something at gmail.com again. Let's try sign up. It shouldn't crash. It should just give us an error message that says error. So this is good. But another thing is that when I hit sign up, you can see that I can just spam the sign up button and it's going to like register our user multiple times. And this is not something we want happening. We want there to be like a loading state so that the sign up buttons actually disabled when we are loading and we are running the transaction between our front end and our back end server. So what better way to implement loading states than just to use the react state itself. So that's exactly what I'm going to do here, which is to import use state from react. I'm going to make a state variable here. It's called cons loading and set loading. And I'm going to set this to use state with a default value of false because we only begin without loading. And then before we even try any of this, we can try set loading to be true. I can in fact put this above the try and catch statement and put something below which says set loading of false. And now we shouldn't be able to spam our sign up button. Let's go ahead and try that in your application. Let's do something at something at gmail.com. Let's try to spam the sign up button and we can still spam the sign up button. And the reason for that is because we have the state variable of loading, but we're not using loading. You can see it's underlined in yellow and it's a bit grayed out because we have declared this variable, but we're never using and reading the value from this variable. So let's go ahead and add a disabled value here in the button element and then we'll just say loading. So if loading is true, then this button will be disabled. Let's refresh this one more time. And let's do something at gmail.com. Give it a random password. Let's try to spam now. You can see that we can no longer spam the sign up button because right after I click on sign up, it's going to gray out and it blocks you from spamming it. All right, let's try signing up with a different email this time. Let's do test at gmail.com. Let's hit sign up and this should succeed. But the thing is there is no indication whatsoever if we have succeeded in our sign up process or if you're even logged in at all because right now we're logged in as test at gmail.com, but we don't actually know that because the application is not telling us anything. So we're going to have to write the code for that in our app.js. I'm just going to say currently logged in as and then under wrap this in its own div, just the cheapest and dirtiest way to get everything to be on its own line, then we're going to have to put something here. And this is going to be the current user's email. So that's the thing that we're going to be putting in this curly braces right here, but we don't actually have that current user's information right now. So I'm going to go to firebase.js here. I'm going to import something called onauth state changed. So onauth state changed is kind of like on snapshot. If you've watched my cloud firestore videos, it's a way you can subscribe a listener to listen for updates in this change of the user's authentication state. The thing is to listen and keep track of the changes that's being made with this listener, we need to put this in a react state so that we can trigger a re-render whenever there's an update. And to keep track of this in react state, we have to put the state variable either in a react component or in a react hook. And in this case, because I want to use this hook in multiple places, I'm just going to be calling, I'm just going to be creating a custom react hook is going to be called function use auth. So this is our custom hook that I'm going to be creating. Of course, I have to export this so that we can use this in other components. And the first thing I'm going to do is of course, create a current user state variable. So current user and set current user, we want to trigger a re-render every time there's an update that's being pushed to the onauth state changed event listener. So I'm going to do use state. Of course, I have to import that from react up here. So import use state from react. And we could just do return current user. So I'm going to write the code for current user later on. But first of all, I'm going to come back to app.js here. I'm going to import use auth from Firebase. And then we're going to be putting const current user equals to use auth. So this is how we're going to get our current user. It's going to be returned to the use auth state from this custom hook right here. So we can right now we can come here and do current user dot email. The thing is right now, current user is empty because we are not setting current user. So that's what I'm going to do. I'm going to use effect here. And I'm going to import that from react, which is automatically imported. And I'm going to have an arrow function here, as well as an empty list, because we want to ever run this code only once when the component mounts. In this use effect function, I'm going to call onauth state changed. And the thing I'm going to pass in here is the authentication handle, of course, and I'm also going to have another arrow function which is in here. And I'm going to get the user from this arrow function. So user, and then I'm going to do set user set current user of user. So basically, this is what I'm going to do. I can actually just get rid of the curly braces here as well because it's just a single line statement. And this should be it. So basically, I'm going to give this onauth state changed function a return variable called unsub. And then we need to return unsub to use effect. So we are going to subscribe to a listener every time our hook is mounted. And once the hook is unmounted, or once the component is unmounted, we're going to unsubscribe from the from this hook so that we don't keep the listeners just permanently listening in the background, or even though our component is unmounted. So here, I can come back to my app.js. And then let's see useauth is not defined because I'm not spelling it correctly there. And this should work. All right. So right now we're going to be seeing currently logged in as current user dot email, which I'm going to come here and refresh. And let's see what this gives us. So current user is undefined. So the reason we're getting this error is because there is an initialization phase in which our client has to connect to the Firebase back end servers in order to retrieve our users current authentication state. And that means that we always have to start off as a logged out user. And there's a delay before we can get the user's information such as the email address from the servers, which is what we're doing in this line here current user dot email. So the simple fix is I'm just going to put a question mark here so that the current user's email will only print out if the current user is not null. If the current user is equal to null, then we will just ignore this line and it will just print out current currently logged in as so let's try that out. I'm going to refresh this and you can see there's like a delay. There's a slight delay in which this is blank and it takes like half a second for test at gmail.com to show up. All right, now that we're logged in as test at gmail.com, we want to disable the sign up button here because we don't want to allow users to register for new accounts if they're still logged in. So they have to log out first before they can create new accounts. So let's go to the code here. I'm going to add another criteria in the button disabled state which says if current user is not equal to null, then we want to disable the button right here which is working. You can see that the button right now is grayed out because we're logged in. So the thing is we can just get rid of this whole part here because of javascript syntax is just going to work the same. And with that, we are pretty much done with all of the code for the sign up functionality. So the next thing I'm going to do is make a log out button here because right now we are logged in. I'm going to make user have the ability to log out. So I'm going to do a button that says log out and it's going to have an on click. On click equals to handle log out which we are going to create up here just after handle sign up. So I'm going to collapse that. I'm going to do a sync function handle log out and because it's still an API call to log out a user. So that's why it's going to be an asynchronous function. And here I'm going to put something that we write in firebase.js which is I'm going to just collapse all of these functions here. Let's type export function log out and I'm going to move this all the way up here before the hook. So I can expand this and I can write a sign out and give it an auth handle there. So I'm going to return this. Of course I have to import that from firebase which is sign out. So sign out. So this is basically how you sign out and of course don't forget to give it the authentication handle every time you're running a function from firebase slash auth. You'll always want to put the authentication handle there and I'm going to import this log out. Let's do log out and handle log out which is log out and we don't even need to pass in the email or password here because we're just logging out the current user and I'm going to just put try actually await this. I'm also going to try and let's catch the error if there's an error you're just going to say alert error. So the app doesn't just crash on our user's face and we're going to just like give it a loading state as well. So set loading of true and at the end of this set loading false. Right now this log out button should be fully functioning. So let's go back to our browser. Let's see if we're logged in. So we're logged in as test at gmail.com I can log out and then we're now logged out. The thing is we're already logged out and we're going to try to log out again. It's just going to be we're going to disable this button if we're already logged out. So I can go ahead and give it a disable equals to loading or current user but instead of just putting the current user I'm going to put not current user because if current user is null then I want to disable the log out button. So I want to inverse this. It's going to be inverse compared to the sign up button here. So if the sign up button is disabled the log out button shouldn't be disabled and if the log out button is disabled then the sign up button shouldn't be disabled. So it's going to be opposite and now we can see that's working. I can log I can sign up with a different email right now. I'm just going to give it a random email. You can sign up. You can see the log out button is disabled right now if I hit sign up we're going to be logged in and the log out button is going to be not grayed out anymore. All right so we're actually almost done. We're done with sign up and log out. So now all that's left is to do the log in functionality which I'm going to do right now. I'm going to make a button here. I'm just going to clone the button down. I'm going to say log in instead of sign up. So log in and then on clicks we handle login. So handle login is going to be pretty similar to handle sign up which means I'm just going to clone this asynchronous function down like that and we can collapse handle sign up. So we're just focusing on handle login right here. So the set loading will still be true. There's still be a try catch but instead of await sign up I'm going to be awaiting login which is something I have to import here from firebase. slash firebase which means I have to go to my firebase.js and create a function here that says export function login. So I'm just going to clone that and collapse that. So export function login it's going to take in an email and password as well. So instead of create user with email and password I'm going to do sign in. I'm just going to sign in with email and password. So sign in with email and password which is something we have to import from firebase slash auth. So that like this and this should pretty much cover everything that we need to do to be able to implement the login function. Let's go back to firefox and let's refresh this. I'm still logged in which means I'm going to log out. I'm going to actually create a sensible account here. Let's do hello at gmail.com. Password is just going to be password one two three. Let's sign up and it's going to sign us up and we can log out and we can log in again with the email. All right so login is now officially done but before I end this video I just want to show you guys something that you might encounter when you're developing your own firebase authentication app. So first I'm going to log out of this. I'm going to clear everything here. So let's say I'm going to like sign up with a different account right now. I give it like a password of one two three four. So there are only like four characters in here and if you try to sign up like that it's going to throw you an error and this error is basically something that you can see if I just get rid of the try and catch here. So in my sign up function let's handle sign up and I'm going to get rid of the try and catch. So let me do that so let's comment that out so you can see what the error is. So I'm going to hit okay let's try to sign up like that again and you can see that the error is going to say password should be at least six characters. So if you have like a password that is weak you're going to get this error so if you just start getting random errors in your development just don't fret and just try to create a password that's more than six characters long. So with that out of the way I'm going to end this video right here. In the next videos I'm going to make how you can update your email and password in Firebase. I'm also going to show you how you can send forgot password emails to your users and also eventually we'll get to link Cloud Firestore with Firebase authentication. So hope to see you in those next videos. I'll catch you then.