‫Now it's time to turn our attention
‫to one of the most fundamental parts
‫of building web applications
‫and that is user authentication and authorization.
‫So at the very beginning we said that
‫users actually need to be logged into the application
‫in order to use it.
‫And so now we're going to use Supabase
‫to implement this super important part of this
‫and of most other web applications.
‫We will also use Supabase
‫to sign up users in the first place,
‫to update their data and password
‫and even to upload a user avatar.
‫So this is really, really exciting stuff
‫that we use in the real world all the time.
‫And so let's now get to it
‫and we're gonna start by implementing the login form.
‫So we already have the login page and the login route,
‫but then we don't have any real content here.
‫And so now we need that form
‫where the user can input their email or their username
‫and their passwords.
‫So we actually already have most of that stuff done.
‫So here inside our features folder in authentication
‫we already have the login form.
‫And so let's move here to the pages, so to the login page.
‫And then here
‫let's basically import that login form component.
‫So login form like this and nice,
‫so this already looks like something,
‫make this a bit smaller.
‫And then maybe let's also place the company's logo here
‫and also some tile there.
‫So for that we can use
‫the logo component that we already have
‫and also the heading component.
‫And let's try an h3 here
‫and then log in to your account.
‫All right.
‫Now here, maybe we need some other type of heading.
‫So let's try to create an h4, so that doesn't exist yet.
‫And so let's come here
‫and then let's just copy paste this part
‫and create an h4.
‫So let's make it slightly bigger here
‫a bit more font weight
‫and also text align to the center and beautiful.
‫So that's looking really nice I think.
‫And so with this, we finished the login page
‫and so let's now come check out our login form.
‫So here we already have two pieces of state
‫because here we simply have these two inputs
‫which are controlled elements.
‫Then here we also have the form row vertical.
‫So this component that was already in your starter files
‫and which is very similar to the form row
‫that we built ourselves earlier.
‫So it's just the difference that here
‫the styling is a lot simpler.
‫Then here we have the standard stuff
‫for controlled elements
‫and then here we also have this auto complete prop,
‫which is basically used by password managers
‫to make login forms work a little bit better.
‫So this has nothing to do with React,
‫it's again just for password managers now, right?
‫And so this is the JSX basically that we need for a form
‫and then we can now start working on the handle submit.
‫But before we can do that,
‫let's actually finally head over to Supabase
‫and create our very first user here.
‫Now, remember how I mentioned earlier
‫that the users are not a normal table right here
‫but instead we come to the authentication tab
‫and then here is where we have basically
‫a table with our users.
‫Now, before we create a new user here
‫let's first come to the providers here.
‫And so here you can actually enable
‫all kinds of different providers
‫where by default we have the email provider activated.
‫So basically this allows users to sign up
‫using a password and an email.
‫Now what I want you to do here is to
‫deactivate this confirm email.
‫So for now, we don't need this part
‫because for development
‫this is going to be a bit easier,
‫but here you can really use all kinds of
‫third party services very easily,
‫all integrated into Supabase.
‫So you can have login with Apple or with GitHub
‫and here you just have to set up
‫a few things from your GitHub account.
‫And then with that
‫you can start accepting logins from GitHub.
‫So this is really, really cool,
‫but I'm not gonna go into that
‫because you can always go read the documentation
‫for those parts.
‫Here in this application
‫we will just use the very simple
‫and standard email authentication.
‫All right, so let's come back here to our users
‫and let's add a new user.
‫So here I will just use jonas@example.com
‫but of course you can use any email that you want.
‫And then here as a password, I will just use pass.
‫So P-A-S-S 0987.
‫And again, you can just create any password that you want.
‫So then let's create our user.
‫And then all we have to do is to
‫connect this entire thing with our front end.
‫All right, so let's then again come here
‫to our API documentation.
‫And then here, let's select authentication.
‫So here to explain a little bit
‫how authentication works here.
‫And basically behind the scenes
‫this is using the JWT technology
‫which I'm not gonna go into here.
‫So you can check all of that out if you want
‫in my Node JS course
‫where we basically do this here from scratch.
‫But anyway, what really matters here is actually
‫the user management part.
‫So here we can see how to sign up users,
‫how to log them in with email password
‫and in other ways as well.
‫We can also then use OAuth.
‫We can get the currently logged in user
‫and we can even do a password reset flow
‫and then updating and logging out.
‫So we will use some of them here later.
‫But for now, let's grab this one right here.
‫So we already have the user
‫so we will do user sign up a bit later.
‫And for now, let's just take this part right here.
‫So copying that.
‫And so now we can as always create a new service.
‫So let's call this one here apiAuth.js.
‫And then here, let's start with a function called login.
‫So then let's paste that in here.
‫And of course it needs to be an async function
‫and we need to import our Supabase client.
‫So this Supabase here as always is the Supabase client.
‫So this one right here that we have created earlier
‫in this Supabase file, remember that.
‫But anyway, of course here we don't want to
‫hard code these values,
‫but this function should receive them as inputs.
‫So let's actually paste in an object here
‫containing email and password.
‫So in modern front end development
‫it's pretty common to not pass
‫in multiple arguments into a function, but just one object.
‫So here we then immediately de-structure that
‫and then here we just create a new object
‫with email and password.
‫All right.
‫Then as always here, let's say if there is an error
‫then just throw a new error.
‫And this time let's use the error.message.
‫Then let's also return the data
‫and maybe for now also log it to the console.
‫So, basically on our Supabase client
‫we can use the Auth sub module.
‫And so then on here we can call all kinds of methods.
‫And the most basic one is exactly the sign in with password.
‫And so this then accepts an object
‫which contains exactly the email
‫and the user's password.
‫Now, right?
‫And so now we can go use this function to log that user
‫that we created initially in.
‫Now, in order to do this, we will again use React Query,
‫but for now, just to see if this actually works
‫let's call this function here directly
‫inside our login form.
‫So right here, this is just a regular form here
‫so we need to start by preventing default
‫and then also we need to make sure that email
‫and passwords actually exist.
‫So if there is no email
‫or no password, then just return.
‫But otherwise, let's call our login function
‫that we just created
‫and paste in that object with email and password.
‫So let's go try this out.
‫So this doesn't need to be so big.
‫And here let's see if we then get something in our console.
‫So let's use that email that I had earlier
‫and then the password of PASS0987, let's click log in
‫and then let's wait if something actually happens.
‫And indeed now here we got our data back
‫from authentication.
‫So we have this active session now with this access token.
‫And so maybe you recognize
‫that this is really just a JWT token.
‫We have a refresh token even.
‫And so that's the stuff about the session.
‫And we have the user itself.
‫So we have when they were created, we have their email
‫and very importantly
‫we have this role here of authenticated,
‫which means that indeed the user is now authenticated.
‫And so from now on, on all the next requests
‫Supabase will automatically send this data to the server
‫to basically let Supabase know
‫that we are currently authenticated.
‫So Supabase, I believe stores this data in local storage.
‫So let's check.
‫And yeah, so here is the access token
‫that we just saw earlier with the same refresh token
‫and with the user object itself as well.
‫Now right, now maybe this changes in the future in some way.
‫Ah, well now I deleted it.
‫So let's get that again actually because we will need it
‫inside that local storage in the future.
‫So not sure if this is the data that just came back,
‫but yeah, so now we have this data
‫back in our local storage.
‫Great.
‫Now of course, once this is done
‫we then want to redirect the user
‫to the homepage of the application,
‫which in our case is gonna be the dashboard.
‫And we also want to show some indicator here
‫that login is actually happening right now.
‫And so for all that it's best to again use React Query.
‫So let's create inside authentication here
‫a new custom hook called useLogin.js.
‫And then here, let's get rid of this part.
‫And also let's actually grab this email address from here.
‫And temporarily while we are developing
‫I will just place them here as default values
‫so that we don't have to always type it by hand.
‫Now, right?
‫And so now here, let's create that function.
‫So use log in
‫and then here we will use a mutation actually
‫to handle this login.
‫So it's a mutation
‫because actually something changes on the server.
‫So basically a user gets authenticated
‫and also it's gonna be a lot easier
‫to then handle the success
‫and error states if this is a mutation.
‫So that's really how this should be done.
‫So here we need that mutation function.
‫And so that will then of course also receive the email
‫and password as an object
‫that we immediately de-structure here.
‫And then this is where we actually call the login function
‫that we created earlier.
‫So again, we paste in email and password.
‫And so while this is actually exactly the same
‫so we could just rename this here to credentials or so
‫but let's just leave it like this.
‫It's a bit more explicit.
‫But anyway, here, let's now have our on success handler.
‫So not unsettled, but this one here.
‫And so what we want to do for now at least
‫is to then navigate to the dashboard.
‫So let's grab the navigate function.
‫And then as I was saying, we go to the dashboard.
‫Now, right.
‫Now, this here of course returns something.
‫So as always, the mutate function and the is loading state
‫among many other things that we could also use.
‫And so here, let's rename this one to login.
‫And then we actually have a problem
‫where this conflicts with this function.
‫So just as before, let's rename this as loginApi.
‫So here then this is gonna be called loginApi.
‫And the function that we actually get
‫and return is the one called login.
‫So login and is loading will be returned.
‫And actually let's also create an on error handler.
‫And here let's actually receive the error object
‫which will be whatever error is returned here
‫from the mutation function.
‫And so that's then going to be this one right here
‫with this error message.
‫And so here, let's then just log this to the console.
‫So just to know that this is our own one.
‫And then let's also add a toast.error
‫saying that the provided email or password are incorrect.
‫And finally,
‫here we can also log the new user to the console
‫because remember that here in the on success handler
‫we can actually get the data that was received
‫from the function as an input.
‫So let's maybe even call that user and not just data.
‫And then let's log that to the console as well.
‫All right, so I think we are done here,
‫but let's just leave it all open
‫and then we can get that in here.
‫So the login and is loading state from use login like this.
‫And so here basically we now do exactly what we had before,
‫login with email and password.
‫Great.
‫Now next up, let's then also quickly use
‫these is loading states.
‫So just to disable this is loading
‫and then we need this on all of them.
‫So here as well and here as well.
‫And now as a final nice touch
‫we actually have a really small spinner somewhere here.
‫So spinner.
‫Yeah, this spinner mini.
‫So this is going to look really cool.
‫So here, let's say if it's not loading
‫then just return the text that we had earlier.
‫So log in, but otherwise here then
‫let's bring in that spinner.
‫And actually it's called spinner mini.
‫Well, for some reason that's not importing.
‫So let's import this one
‫and then reload them or rename them actually everywhere.
‫Okay, and with this, I believe we are all set.
‫So let's reload here
‫and then see what happens here with the spinner.
‫Nice and beautiful.
‫So that seems to have worked just fine.
‫So we got our new user logged into the console even twice
‫and we were redirected here to the page's dashboard.
‫Great.
‫So log in is indeed working.
‫Let's get rid of these console.logs.
‫And then let's also try it with a wrong password.
‫So let's go back here, let's reload,
‫add something more here.
‫And then here we get provided email
‫and password are incorrect.
‫And here we then get this error,
‫which is the actual error from Supabase,
‫which says invalid login credentials.
‫So we could actually even use
‫this error message here for a toast,
‫but the one that we wrote is also fine
‫but now let's use, paste the correct one again
‫and there we are in our application.
‫Now the problem with this is that at this point
‫the only thing that is happening is that
‫we get the user object from Supabase
‫but that doesn't mean that a user that is not logged in
‫cannot access our application.
‫So anyone can still basically open up any of these pages
‫even if they are not authenticated.
‫And we can easily prove that by
‫coming again to the application part
‫then deleting this really here from local storage.
‫So now there's nothing here
‫about the authentication anymore,
‫but still the user, if they reload the page
‫they can still get access to all of this.
‫And so this is where the second part
‫of this entire flow comes into place,
‫which is authorization.
‫So basically only authorizing
‫the authenticated users into our application.