2.6 Authenticating User Credentials
Now that we've completed the user registration, we need to allow them to authenticate. We'll implement our REST service's login endpoint in this lesson.
1.Introduction2 lessons, 06:25
2.User Registration and Authentication7 lessons, 1:05:20
3.Wireframing the UI3 lessons, 27:30
4.Handling Requests5 lessons, 39:24
5.Conclusion1 lesson, 01:04
2.6 Authenticating User Credentials
In this lesson we are gonna write the code for logging in a user. And thankfully, we have a very good starting point, because our register endpoint has the code for getting the email and password. And verifying that we have values there, because we need to do the same thing for our login. Because if we don't have those values, there's nothing else to do there. So, let's just copy and paste. We'll make the necessary changes. And then, we will use the user model, because it has a method called find one, and we can supply what we wanna find a user by, and that is simply the email. Now there's three things that could happen here. We could either get an error, or the user could be found or not. So, we need to handle each one of these possible outcomes. The first is an error. Now if we are getting an error here, then something went horribly wrong with the application. It could be a network error. It could be issue with the machine, that the database is on it could be the database engine itself, I mean something went horribly wrong here. So, we are gonna return a status of 500. Now let me first of all say that this might not be the best approach, because there are some security experts in some security firms that say that you shouldn't return a 500. That even though your application has catastrophically failed, that you wanna present to the user other a 404 or an okay. Because a 500 indicates something that an attacker can possibly exploit. Now I can understand that mentality. The applications that I have running in production follow that mentality, because we have security experts that have tested our websites and said you need to do this. So, we have followed that, it does make debugging very difficult. However, at the same time, we want our applications to be as secure as possible. So, you can take that information, however, you want in this particular case, we're just gonna return to 500. But we are not gonna supply the error, because the actual are could have information that a user or an attacker could use. So, instead we're just gonna pass in our own object that says some something went horribly wrong. And that would be definitely the case, if we gotta that point. Now, the next scenario, is that we don't have a user, in which case we could say that the user doesn't exist. But once again, from a security standpoint, we don't wanna give too much information. I mean, yes, we wanna tell the user themselves. You know what is going wrong so that they can fix whatever it is that caused the problem, but we can't trust every user unfortunately. So, in this particular case, what we're gonna do is return a 401, which is an unauthorized and all we are gonna say is essentially. That the username, and or password is incorrect. I miss the days that we could be 100% transparent with users, but that's just not the case, we have to protect our applications as much as possible. So, there we go. Now if we do have a user, then that means we wanna make sure that the passwords are correct. So, we are gonna use B crypt here. We're gonna use the compare method, which there are two of our versions, there is the asynchronous, which is what we are gonna use. There's also the sync version for synchronous. So, we're gonna compare the password provided by the user, with whatever is in the database. And then, we need our callback function. So, if we don't have a match here, then result is gonna be false. And we will essentially do the same thing, we will return a status of 401, and then, we will tell the user that the email and password are not correct. Otherwise, what we wanna do is create our JWT and respond with that. So, let's copy that code that we have, because it is the same exact code, so we will create the JWT, so that we can simply respond with that. So, we will send that, and there we go. The client side is gonna take that token, and then store it in the local storage, so that we can use that for any other requests that we might need to make, let's go ahead and do that. Let's go to our client app. Let's go to the HTTP file inside of utils. And we wanna modify this, so that we still go ahead and convert the response into an object. But then, we're gonna work with that object, because if we have a token, well then we wanna go ahead and store that in our local storage. So, we will check to see if we have a token, and if so, we will simply call the set item method for our local storage, and what do we call that? Let's go to our storage. And let's see auth token. There we go, that's what we need. And we will set the value to the token that we received. And then, of course after we are done with that It will simply just return OBS and we can keep going on there. So, with that in place, we should be able to close this file. And inside of our view X store, we are gonna need another action for logging in the user. So, let's just copy and paste, we will make the necessary changes. And instead of gonna this register endpoint, we will go to login, we will still pass in the same data and we will be good to go there. So, we should be done with this as well. And that means, we need to go to our views, so let's open up login. Let's open up register, because we didn't do anything inside of our login view. So, let's start by importing the ref and use store, because we're gonna need all those. And in fact, let's just copy the setup method as well, because we will need that. In fact, everything is gonna be fine except that we want to dispatch, the login action. Now from here, we wanna do something. When that action has completed, we wanna take the object that is coming from the response, and we wanna react to that. So, the first thing we need to do is check to see if we have an error, and if we do, then I guess for right now we will just alert, whatever that error is, that's gonna be just fine. Otherwise, and now let's do a return here. Otherwise, we will wanna redirect to whatever is gonna display our feeds, now because we are using the composition API, that means that we need to think a little bit differently. We don't have access to this, so we can't get to the router in that way. However, we can get the use router function from view router. That's gonna essentially do the same thing, like the use store function gives us that's gonna give us access to the router. So, we will simply call us router. And there we go, that will allow us to navigate to wherever we wanna. So, from right here we can say router. Push and we wanna go to the feeds route, which we don't have. But let's do this, we have this about view. Let's rename that, to be feeds, and then, we of course need to change our route, so that we refer to that as feeds. So, the URL is gonna be feeds, the name will be feeds. And then, when it is importing the actual view, that will be feeds as well. So, that should work as far as our login is concerned. Let's check first of all, that it does work, because if it does, then we can just copy that to our registration, because we would wanna do the same thing there. So, let's go to the browser. And let's go to the login page. And we are gonna attempt to login, so we want email@example.com, the password was password. Let's clear out everything from the network, and let's make that request, nothing happened. Do we have an error? Well, we have several. Let's make sure everything is running. Our client application is running, our server application is running. So, let's do a hard refresh, and let's attempt this once again. So, foo.com, password. And once again, let's go to the network. Let's click on login, and there we go. We can see that that worked just fine. However, let's do test, to make sure that a failed login behaves appropriately. So, let's go to our local storage, and let's just delete everything, will clear everything out of that. So, that if we go back to login, then we can type in something that does not exist, and let's attempt to login. We have our alert box, that says the username and password are incorrect. So, our login works just fine. So, let's take this portion of our login, and let's go to the register, and we will paste that in there, now we do also need access to the router. So, we will copy the necessary lines of code, so that we can access the router inside of the register view. But that is gonna give us exactly what we need, so that whenever we register, and everything is okay, then we will simply go to the feeds view. If we are logging in, we see the same thing that will take us to the feeds view. In the next lesson, we need to finish up with our authentication, so that unauthenticated users cannot access views like the feeds view.