#107 Logging in a User | Authentication & Authorization | A Complete NODE JS Course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this lecture we are going to implement the functionality of logging in the user based on a given password and email address and just like we learned earlier logging in a user simply means to sign a Json web token and send it back to the client but in this case we will only issue a token if the user exists in the database and the password provided for that user is correct so let's go ahead and let's Implement that login functionality again here in the auth controller.js I am going to create another function so we also want to export it so we will say exports.login and let's go ahead and let's create that function and this function is going to receive the request the response and the next function again we want to make this function as a sync okay and we are going to wrap this function within this async error Handler so that if there is any rejected promise that will be handled by this async error Handler now here when we will call this login Handler at that time we are going to make a post request and with that post request in the request body we are going to send the user's email ID and the password so from the request body we want to read the email ID and the password which the user has provided for logging in so let's go ahead and let's create a variable let's call it email and to read the email from the request body we can say request dot body Dot email okay so email will be the property name then in the same way let's go ahead and let's create another variable let's call it password and again we are going to read this password from request body so request dot body dot password now here instead of doing it like this we can also use object destructuring syntax so for that we can use this const keyword then for the object restructuring we use a set of curly braces in there we specify the variable names so variable name is here going to be email and password and then we can de-structure the object object here is request.body so basically this request dot body it is going to store the object and in that object we will have an email field and the password field so we can also do it like this and this is called as object restructuring syntax but let me go ahead and let me comment it here so you can use either of these two approaches now once we have read the email and password from the request body we want to check if this email and password actually exists in the request body or not so for example here we are trying to read the email and password but in the request body if the email and password is not there in that case this email and password will be assigned with the value undefined because in the request body there is no email and password so before proceeding further first we need to check if the user has provided the email ID and password for logging in or not right so let's write an if statement here and there let's check if in the request body we have this email and we have this password or not or instead of end here we will use or operator because both email and password should be there if any one of these two is missing in the request body in that case we want to throw an error so here we are going to create an instance of our custom error class so here I will call it error and let's go ahead and let's instantiate our custom error class now this custom error class it is present inside this utils folder and in there we have this custom errors.js right so we also need to import that file here so let's call it custom error and here let's use this require function and there let's specify the path of the custom error class so it is one folder up it is in the utils folder and in there we have our custom error class okay now to the Constructor of this custom error class we need to pass an error message and here let's simply say please provide email ID and password for logging in and let's also provide the status code so status code is going to be 400 that means bad request because the user has not provided email ID and password for logging in so in that case it is going to be a bad request and for that the status code is 400. and now all we have to do is we have to return from here after calling the next function and here we will pass our custom error so we know that when we pass this error to this next function it will skip all other middlewares which is there in the middle base stack and it will call the global error handling middleware right we have learned that whenever we pass an argument to this next function it will always call a global error handling middleware and that's what we are doing here if the request body does not contain an email or a password in that case we are simply calling the global error handling middleware now just to test it out let's go ahead and let's create a new route for that let's go to this routes folder and in there we have our auth router.js there just like we are creating a route for the sign up let's go ahead and let's create a route for login so I will copy this line let's paste it here and here we are going to call it as slash login okay and there when a user makes a request to this URL a post request to this URL we are going to call the login function the login route Handler function let's save the changes now here we have this error route dot post requires a callback function but got an object that's because this function here this login function currently it is not returning anything so by default it will return undefined so what we will do is we will return some response from here for that let's say response Dot status and here let's set the status 200 let's specify the Json data and in there let's pass an object and there let's set the status to success because this code will be executed only if this if statement condition is false okay that means if there is an email and password in the request body and then let's send the token also with this so for now let's send an empty string from here okay let's save the changes again so the server has started TV connection is successful and now we don't have any error let's go to postman and let me copy this URL from here let's open a new tab and let's make a post request to login route okay and since we are making a post request let's also specify body there I will select Raw and the body type is going to be Json so here I am going to specify an object in that object I will have an email field okay let's say email is ABC at gmail.com and let's also specify a password and let's say password is Maybe pass one two three four something like this so if I make a request here in that case we should get a valid response so status is success and token is an empty string just like we have specified here but let's say if the password is not there and now if I make a request we get this error message please provide email ID and password for logging in in the same way if I don't specify the email here and if I make a request we should get the same response please provide email ID and password for logging in and if I remove both then also we should get this response okay so let me get back both email ID and password all right let's go back to vs code so this functionality is working all right so if the email ID and password is present in the request body the next thing which we need to do is we need to check if with that email ID there is any user in the database right so let's go ahead and let's do that let's also provide a comment here all right now how are we going to check if the user with that given email if that user exists in the database or not let's see that for that let's just go ahead and let's first create a variable let's call it user and then on the user model we are going to use a method called find one so basically we want to filter a user a single user using this find one method and for filtering we need to pass an object and in there we need to specify the field Name by which we want to filter the user here I want to filter the user using email okay and this email is the field name for the document so this user document is going to have an email field and to that email field we want to search for only those users whose email field matches the value of this email variable okay this email variable which we are reading from the request body so let's pass it here now as you already know in es6 if the property name is same as a variable name then we don't need to specify it explicitly we can simply say email like this now this fine one it is going to run asynchronously so here we need to wait for the result for that we will use this await keyword and that's why we made this function as a sync so here we will basically get the user with that given email ID and that will be assigned to this user variable so for testing what I will also do is here I will also pass that user in the response okay so let's save the changes let's go to Mongoose and in there Let me refresh this collection and here we have three users maybe let's go ahead and let's test with this user so I'll copy this email ID let's go back to postman and there let's specify the email ID as John gmail.com because using this email ID only we are going to check if with that email ID any user is existing in the database or not and for that for that user the password was test one two three four right so let's click on the send button again let's make a post request to this URL and you see we are getting that user back okay so this user variable here that is assigned with that user object because we are searching for that user using its email ID so it has returned that user and we are signing it to this user variable now very important thing to note here is that if you see when we are requesting for a user we can also see his password and that is a high security risk because later when we will Implement a route for getting all the users from the database in the response we will also get their encrypted password which we do not want to do to avoid any security risks for that what we are going to do is whenever a get request is made to get all the users in the response we will not return this password for any user and for that all we have to do is we have to go to user model so here we have our user model and there on this password field we are going to set Select Property to false okay let's see if the changes now let's go back to postman and now let's make a request so now we should not get password in the response so as you can see now in the response we don't have the password okay now if I go back to vs code and if you go to our authcontroller.js so here we need password right because once we have got the user based on his email ID we also want to compare the password which the user has provided for logging in with the password which is saved in the database okay so in the response we don't want to show the password but here we need the password because then only we will be able to compare the password provided here provided by the client basically this password which you are providing and we can compare it with the password which we will get for that user from the database the encrypted password so for that all we have to do is we can add a select statement here so we can say select which is a function and there we can specify the name of the field so for that we can use plus and the name of the field is password let's go back to Postman let's make a request again and now we are getting this password so here we are getting the password that's okay because here in the response we are not going to send this user in the response this is just for demo purpose but later when we will make a route for getting all the users from the database and displayed in the UI that time we don't want to show the user's password that time we don't want to send the user's password in the response and that's why in the model we have set the select to false I hope you got the point all right let's close this so now the next thing which we need to do is we have the user in the database now we need to verify if the password provided by the user that means the password which we are reading from the request body if it matches the password in the database for that user okay so for this password we have passed test1234 and for this user so if I go back to compass for this user in the database and encrypted password is saved so we need to compare if that password that test1234 if it matches the password which is saved in the database now in this case it will not match because test1234 is not equal to that encrypted password so here what we need to do is somehow we need to compare the password which we are receiving in the request body with the encrypted password saved in the database and to do that we are again going to use the B grip Library so what I'm going to do is let me open this user model again and here we are going to create a function and this function will be responsible for comparing the password which we are receiving in the request body with the password saved in the database and here what we are going to do is we are going to create an instance method an instance method is basically available on all documents of a given collection in this case since we are creating it on user model this method will be available on all documents of the user collection and we will be able to access this method on any instance of the user model okay so here we are going to create that method using this user schema on that we are going to use this method so when we want to create an instance method we need to use this method and on that we are going to create a method called compare password in DB you can name this method anything I am just simply calling it compare password in DB because we want to compare the password which the user has provided with the password which is saved in the database okay and let's go ahead and let's create a function and this function is also going to be async and I will explain why okay and this function will receive two arguments the first argument will be the password which is provided by the user in the request body and the second argument will be the password which is saved in the database so I will call it as password DB and from this function we want to return a Boolean value true or false so if the password matches then we want to return true but if the passwords are different then we want to return false but how are we going to compare these two passwords because in the database the password is encrypted and in the request body we are receiving a plain password we are not receiving an encrypted password right so for that again we are going to use this Big Crypt library and on that we have a function called compare and this compare function will compare the password which the user has provided that means this password with the password which is saved for the document in the DB so this password DB and this function runs asynchronously so we want to wait for this compare function to return a result promise okay so here let's avoid for it okay if the passwords are same it is going to return true but if they are different it is going to return false so we are waiting for that result and then once we have the result we will simply return it from here let's save this file and let's go back to our authcontroller.js and there let's call that function so this user here it is an instance of user model right so basically it is going to store a user document and that's why since it is an instance of user document on this user we can call that function so the function name is compare password in DB let me just go back to usermodel.js and let me copy this function name this method name from here and let me use it here okay and to this we need to pass the password provided by the user we are storing it inside this password variable let's pass it here and to get the password which is saved in the database on this user object we can access that password and again since this function is an async function we need to wait for it result so let's use this await keyword and let's go ahead and let's store that result in a variable and let's click on it is match so here we have the user okay so if the user is present this user will have a user document assigned to it a user object assigned to it otherwise it will be undefined in the same way this is match will be true if the password for that user matches otherwise it will be false so now what we are going to do is we are going to check if the user exists and the password for that user is matching then only we want to proceed further for that let's go ahead and let's write another if statement and in there we will check if the user exists so on this user I will use this not operator so if the user does not exist or if the user exists and the password does not match so I will use this is match here so if the password does not match in that case we want to throw another error okay so here again I will create a new variable I will call it error and here I'm going to create an instance of this custom error class there let's specify the error message and there let's say incorrect email or password and then let's say the status code is going to be 400 that means unauthorized okay and let's go ahead and let's call the next function and there let's pass this error object and let's also return from here okay after calling this next function we want to return from here so this next function if there is an error it will call the global error handling middleware and there that error will be handled now here in this code we have one problem and the problem is let's say this fine one method does not return any user so let's say we don't have any user with the provided email in that case this user will be undefined and in the next line in order to check if the password matches or not on this user object we are trying to call a function but since this user is undefined on that undefined when we try to access a function it will throw an exception so at this line if the user does not exist we will get an exception so instead of doing it here I will comment this line from here and I will copy this line and instead of ismatch I will simply pass that function here and let's wrap this away and this one within a parenthesis okay so all our checks are complete that means we have checked if the request body contains the email and password or not we have also read the user from the database and we're also checking if the password for that user matches the password provided during the login so all those checks are already done finally if all these checks are passed after that we want to login the user and to log in the user we are simply going to send a token back to the client so what we can do is we can simply copy this logic from here and we can use it here but instead of doing it like that what I'm going to do is I'm going to create a function which you can reuse at multiple places so here let's call it maybe sign token you can give it any name and this function it is going to receive the user ID okay and then what I will do is I will simply copy this code from here and I'll paste it here and here we don't need to create any variable we will simply return that token from here and now let's go ahead and let's use this function here and there we need to pass the user ID so we can say new user dot underscore ID okay and we also need to change it here so here we don't have any new user object so this ID we want to assign it with this ID value okay now as you already know in es6 if the property name matches the variable name which we are assigning to it then we don't need to specify it explicitly we can simply keep it like this okay now let's go to our login function and Here Also let's create a token so after all these checks we are going to create a variable let's call it token and let's call the signed token function and again we need to pass the user ID from here so here we have our user object from that user object we are going to extract the underscore ID field value and then we will pass it as ID okay and then this token will be automatically assigned to this token variable so here I will remove this okay since the property name matches the variable name it will be automatically assigned to this property with this let's save all our changes and let's go ahead and let's test this implementation so let's go to postman there first let me go ahead and let me provide an invalid password that means a wrong password okay and let's make a post request so here we have this error and it says user dot compare password in DB is not a function why is that let's check that let's go back to vs code so here we have our function and we are defining it in the user model all right this should be methods okay let's see if the changes again let's go back to postman and let's make a request again and now you see incorrect email or password because we have provided an incorrect password but if I change to 3 4 and now if I make a request now we are getting that user back with the signed token so when we receive this token in the response for the user's client that means the user is signed in if I provide a wrong email let's say john1 gmail.com with this email we don't have any user in the database so if I make a request in this case also we should receive this error message incorrect email or password but if I say John gmail.com and then if I make a request in that case the user should be signed in and we should receive that sign in token so now here in the response we don't want to send the user object so I'll go back to vs code and from the response basically from here I will remove that user object because when the user is signed in we don't want to send that user back in the response all right so this is all from this lecture in this lecture we learned how we can login a user by sending a signed token back to the user's client when the user tries to log into the application now you might be wondering how these signed tokens will help a user logging into the application or signing up to an application Well for now just keep in mind that with JWT this is how the authentication and authorization work the authentication and authorization works by using Json web tokens if the client has a valid Json web token that means the client is logged into the application otherwise he is not logged into the application and you will understand it better when we will start implementing the UI and there when we will have a login page and when the user will enter his user credentials and try to log in at that time these Concepts will become clear for now you just need to remember that if the client has a valid Json web token that means the client is logged into that application so this is all from this lecture if you have any questions then feel free to ask it thank you for listening and have a great day
Info
Channel: procademy
Views: 4,962
Rating: undefined out of 5
Keywords: authentication, authorization, express, mongoose, mongodb, node js, node js tutorial, complete node js course
Id: hoki6PNu82c
Channel Id: undefined
Length: 26min 38sec (1598 seconds)
Published: Fri May 12 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.