User Authentication in MERN Stack with JWT and Bcrypt - MERN Stack Chat App with Socket.IO #9

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we'll add the user authentication functionality in our backend and then use those apis to make the login and sign up forms in our front end to work the link to the full playlist will be in the description below so i've opened our mind chat app folder over here and i'm gonna go to my back end and go to server.js file so first of all i'm gonna start by creating an end point for our users okay so we are done with these two endpoints so i think it's safe to remove them for now and we'll add another endpoint for our user so app.use and then the endpoint will be slash api slash user and now notice what i'm doing over here is instead of any get post etc i'm using app.use so why i'm using that i'm going to tell you in just a minute and i'm going to write over here user routes so i'm going to abstract all of the logic for routes related to the user inside of this user routes file so i'm gonna go to our backend and create a new file for routes and here i'm gonna create another file called user routes dot js now inside of it we're gonna write all of our routes which are related to our user so first of all i'm gonna import express and then i'm gonna create an instance of a router from express so we need to type express dot router just like this and r will be capital now we will use this router to create different different routes router dot route so there are two ways to do this if we directly want to add any get post etc we can just write like this get or post or what we can do is if you want to chain multiple requests we can write router dot route and we can provide the end point after the api slash user so slash api slash user whatever we write over here will be after that particular endpoint so let's say we write login so we can add a get request over here dot get and do some logic inside of it right and we can also chain another request after it let's say post request so stuff like that we can do something like this so for now i'm gonna say i'm gonna create one end point for login and one endpoint for registration which i'll just keep the slash so this will be dot post and inside of it i'm gonna write a controller or the logic for it basically so we'll write register user which obviously doesn't exist yet but i'm going to create this function in just a minute and also for login i'm going to keep write this the other way so that you have the both way of writing it so we can write dot post comma and provide the logic directly inside of it now we can't chain inside of this so auth user okay so both of these we need to create so for now i'm just gonna comment this out and module dot exports router now let's import this in server.js so i'm going to do that just like that okay now we need to create these two controllers so for creating the logic or controllers we we're going to create another folder over here for controllers inside of the controllers folder i'm going to create a new file for user controllers dot js now first i'm going to create the logic for this registration of the user okay so i'm going to write const register user now if there's any error in this controller we need to handle those errors so there's a package called express async handler which handles all of the errors for us automatically so let's go to the terminal and install that package first so this is going to be an async function and it's going to take a few things from our request body so request dot body i'm going to restructure name email password and picture from the body so what i'll do is i'm gonna wrap whole of this function with express async handler async handler let's import this async handler const asynch handler equals require express async handler yup just like that now what we'll do is we'll check if any of these is undefined so we're gonna throw an error like this if name email or password is undefined so pic is obviously optional if you remember in our data models we kept the pic as default if the user doesn't provide any pick it's going to take this default oh you know what i'm just going to remove this required true from here okay cool all right so we checked for the error now what we're going to do is we're going to check if the user already exists in our database or not so i'm gonna take a variable called user exists and i'm gonna query our database so i'm gonna say user so user if you don't know user is the model that we had created so const user first let me import it so require models slash user model okay so if we go inside of the user so if you remember we created these many fields name email password and pick for a user so we're going to use this model to structure our data in our database so what we're going to do is we're going to say await user dot find one so this is one of the queries that we use in mongodb as we go along in this course you can understand a lot of queries related to mongodb still i would highly recommend you to go and read about these queries on your own as well so i'm gonna search for the email if this email already exists in our database or not because if you go to the models you're gonna see that email is supposed to be unique okay i forgot to add that so unique to be true yep email is supposed to be a unique cool so if the email exists what we're gonna do we will throw the error if this exists responds dot status 400 and throw new error user already exists otherwise what we'll do we will create a new user over here with name email password and pic we're gonna create user by using user dot create so this will query our database again and create a new field for a new user now this will return all of the value of name email password pick along with the id so what i'm gonna say i'm gonna say if there's something inside of the user that means the operation successfully completed then what we'll do response dot status also one more thing i'm using this response and request variables but i forgot to take them over here so request comma response just like that so i'm going to say response dot status 201 that means success and dot json underscore id to user id user dot id name to user.name email to email user.email and pick to user.pick so we're gonna send this to our user but if this fails that means else is going to say user not found or probably failed to create the user cool now export this function so module dot exports and it's not going to be a default export so i'm just gonna export it like this register user and now import it to our user routes just like that let's start our server to see if everything is working fine or not okay looks good everything seems to be working fine up until now now what i'm gonna do when it registers a new user i wanted to create a new jwt token and send it to our user so after the registration is done when i'm sending it to our user i want a jwt token to be also sent so i'm going to say token and i'm going to create a function for it let's say generate token and i'm going to provide it a id of the user that will be a unique id so let's create this generate token function so instead of the config i'm going to create a new file for generatetoken.js so here we're going to need to install a package called jwt or json web token so npm installed json web token now let me explain to you what json web token actually is so our jwt looks something like this so jwt basically helps us to authorize the user in our backend so for example we have logged in with a user but user is trying to access a resource that is only available to him so what jwt will do user will send our jwt to the backend and backend will verify that okay this is the user that is authorized to access this particular resource so only then the user will be allowed to access that resource so this helps us a lot in authorization as you can see this jwd has been decoded with this the sub name and id i guess so yeah let's go back yes you see gwp has been installed successfully let's import it require json web token and now i'm going to create that generate token function and it's going to take the id as we were sending it from there and i'm going to return jwt dot sign i'm gonna sign a new token with that particular unique id and also we need to have a jwt secret so we're gonna add a secret over here so for that what i'm gonna do is in our dot env i'm gonna go and add a jwt secret and i'm gonna provide it some value like push okay so let's go back over here and say process dot env dot jwt underscore secret cool now the third thing that it takes is in how many days or in how much time does this token expires so i'm gonna say expires in let's say 30 days for now you can keep whatever you want and let's finally export this so module dot exports to be generate token cool let's take this and import it here okay [Music] inside of the config generate token yeah just like that let's start our server again and art and let's test our api for the first time also i forgot to mention one more important thing since we are taking the value from our front end so we're gonna need to tell our server to accept the json data so we'll go inside the server.js and write over here app.use express.json just like that that'll be enough so i'll write here cool so i guess our registration api is done let's open postman and test it out all right so in our postman i'm gonna create a new folder or new collection i mean for our talkative app now inside of it i'm going to create a new folder for authorization now this is obviously optional you can directly test it but i'm trying to keep our folder structure on point to our project so i'm gonna add a new folder for let's say authentication cool now instead of it i'm gonna add a new request for registration now let's add a new request url now for this we're gonna we can either write http and slash api slash user or we can since we are going to use this very often so let's set this as a variable click on new over here and click on environment so i'll name it okay let's add a variable called url and i'm going to give the value current value to be localized 5000 all right looks good save changes and if you go ahead and select talkative you're gonna click on i button and you're gonna see this url is over here okay let's replace this with the url now let's test this api out so what i'm gonna do i'm gonna go to the body select raw and json data since we're sending the json data and i'm gonna give a new data over here so let's give name email all right let's test this out i'm gonna send it and let's see what happens i think cannot get slash api slash user okay let's see what so far okay we are supposed to write dot post we're doing dot get so i'm gonna set post request over here now if you click on send yeah you see our new user has been successfully registered in our database now let's verify this also you can see the token also has been generated so let's go to our database and verify this so mongodb.com sign in and click on browse collections now we have a users collection as you can see and you can see our entry has been successfully added in our database awesome hit the like on this video if you have followed this tutorial up until this point i know you're feeling very good about it okay let's move on and create functionality for our login so router.post slash login let's add this and now i'm going to create this auth user function or controller in our user controllers okay so right below this i'm going to add a new function const auth user also we're going to take request comma response and wrap this whole function in the async handler great now instead of this i'm going to take two things so i'm just going to take email and password to log in our user so request dot body and below this i'm going to find our user if it's if it exists in our database or not user equals await user dot find one with the email now if user exists and one more thing we're supposed to do over here if user exists and the password that they have entered matches the password which is in our database so we are going to add that functionality over here and but let's just first write this so if these two conditions are satisfied what we're going to do we're going to just say response dot send or let's say response.json id name email pic and that's tokens that we've generated similar to what we've did above okay else what we're going to do we're going to throw an error that it's invalid id or password okay just like this so let's go on and add this match password functionality but before that i just remembered one thing that when we are storing our user in our database when we are registering our user we don't want to store the password in a plain format we want to encrypt the password and then store it in our database so let's write the logic for that first and then we'll write the logic to and decode our password okay so let's go to user model.js and i'm going to add the method for it right here so i'm gonna say user schema dot pre and save so what this basically says is before saving pre means before saving what we should do we should add a function over here this is going to be an async function and it's going to take this next because it's going to be a middleware right so i'm going to say if this dot modified so the current password if it's not modified then we're gonna say move on to the next that is don't run the the code after it otherwise what we're gonna do we're gonna generate a new password so i'm gonna says salt equals a weight b now we need to install this b crypt dependency so let's go to our terminal first and npm install bcrypt now meanwhile that's installing let's write our code so we're going to generate a new salt so how do we do that b crib dot gen salt and we're going to generate a salt of 10. the higher the number the more strong salt will be generated so 10 and what we're going to do we're going to say this dot password await be crypt and now we're going to hash it so hash this dot password with the salt okay also we need to import this bcrypt so import bcrypt equals require bcryp oops not import i mean const and let me see if this b if this is b crypt or bcrypt.js i think it's bcrypt js so i'm gonna uninstall the dependency that i have installed and i need to install bcrypt js not just bcrypt so js yup just like that okay so now what this will do is before saving the user to our database it's gonna encrypt the password all right cool now let's add the functionality for our matching the password and then we're gonna go ahead and test both of these apis so i'm gonna say and we're just gonna add the method directly to our user model here i'll do something like await user dot match password so obviously this doesn't exist yet so i'm gonna create this match password function okay so let's take this match password and let's go to the user model and right above this i'm gonna say user schema dot methods dot match password you can name it obviously anything but i'm gonna name it match password spacing function i'm gonna create another anonymous function and over here we need to take a password so let's entered password and inside of it i'm gonna verify this so return await dot bcrypt.com we're gonna compare both of the passwords so entered password with this dot password all right this should work let's go on and test it out first of all i need to export this and take this over here cool this looks good let's start our app well let's jump to postman and register another user i'm gonna say john doe john example.com and i'm gonna keep the password same let's send this you can see the user has been registered successfully let's jump to our database and i'm gonna refresh this you can see in our database this has not encrypted it this is weird let's check it out once again i'm going to delete this entry for now oh this dot is modified is the function oops my bad now it should work let's send it again and check our database yep you see the password is in the encrypted format now let's check our login as well so i'm gonna create a new request over here for login i'm gonna use our url slash api slash user slash login and this was also a post request so i'm gonna go to body let's just take this data and draw json and add the data over here i'm just gonna say email and password okay let's send this and we get an error user.match password is not a function okay let's see match password okay oh that's my bad i've used the capital u i mean i'm not taking it from directly from the model and taking this from the returned value of this particular query so it's going to be inside of this user thing so this user object dot match password now it should work so if i send this now yep you see we get back this data awesome so we're done with creating the user authentication api in our backend now there's one more thing left before we move on to the front end i'm gonna add the error handling apis if let's say if we go to some other route that doesn't exist sent so see it's sending this error cannot post something like that so let's give this a proper message so i'm gonna go to our app and sort of the server.js right below this i'm going to add two error handling functions or two error handling middlewares so app.use first will be for not found and the other will be for normal error handlers okay let's go on and create both of these so i'm going to get a new folder over here for or just let's say middleware create a new file over here for error middleware.js and in here i'm gonna quickly add the code for that and then i'm gonna explain you so first function will be for not found in which we're gonna what we're gonna do is while we are creating a middleware we take three things request response and then this next so that after this logic is completed we can move to the next logic so what we're gonna do is const error equals new error we're gonna take the new error and if the in the server.js if all of these url doesn't exist it's going to fall on to this particular thing not found then we're going to say not found and the url and we'll send the error message and then next and then if even after that it continues to throw us some other error we're gonna take this error handler and handle this error we're gonna say status code whatever the status code is we're gonna return that status code and then a json with error dot message and if it's in production then let's keep then we're gonna keep it null otherwise we're gonna provide error dot stack message it's not that much important everyone has a different way of handling the errors so i chose to handle error like this you can read more about how to handle errors in express.js apps so let's import both of these things okay i'm gonna say import oops i mean const require dot slash middleware slash error middleware and i'm going to say not found comma error handler cool okay before moving to front end i made a mistake over here it's not going to be user it's going to be app.use okay so what i'm going to do is now i'm going to open another terminal and switch to our front end by cd front end and start our app by typing npm start and make sure your back end is also running because we're going to need that let's close this up and go to our front end folder inside of our home page so instead of the home page we have login and sign up and inside other components we have our login and signup components so let's create the functionality for sign up component first all right here it is here's our login and sign up forms so i'm going to go to the sign up and you can see we have all of these fields over here so let's go back to the code and name email password confirm password set pick etcetera etcetera so first of all what i'm gonna do is so when we're entering the data in our fields this is updating all of these states right but we have not yet added the functionality for adding the picture so for adding the picture we're going to use something called cloudineary let's go to the browser and search cloudinerry and let's go to this site cloudnary.com and log in if you don't have an account create an account so i'm going to quickly log in all right so we're logged in successfully into our app now here i'm gonna go to this settings icon now go to upload and scroll down and here you're gonna see a function for up enabling unsigned uploading so i've already enabled it so after you enabled that thing just click on add upload preset and here give a name for your app let's say i'm gonna give the chat app and save this cool now you have created your app in cloudinary let's go back to the dashboard and click on this more button and you're gonna see that you have this api base url and just click on over here and take this particular url copy this up and that is all you done with it now let's go back to our app where we have this form control okay in the post details we are sending this file and now let's create the functionality for it so we have this post details function for uploading the picture so first of all while the picture is being uploaded i'm going to create a new state for the loading by default will be false so here i'm gonna say set loading when the upload starts to true and then i'm gonna check if the pick is undefined so if it's undefined we're gonna pop up an error so how we're gonna pop up the error we're gonna use something called toast from chakra ui so if we go back to the browser and go to chakra ui let's search toast so if you click on show toast you're gonna see we get something like this so we'll add this into our app and how to add this we just need to import toast from chakra ui react and then create a toast variable with this hook and we're good to go awesome let's take this line and i'm gonna add it right over here and import the use use toast okay let's manually import it oh let's take this line cool inside of it i'm gonna add it toast title will be please select an image status will be warning so we have a bunch of different statuses like error info success warning for how long it's gonna be on the screen so it's duration is five thousand is closable yep true position will be bottom awesome and after that we're going to return it we're not going to move forward if the pick is undefined spx okay not pick now after this i'm going to say if pix dot type i'm gonna check if it's an image or not image slash jpeg or if it's a png then we're gonna move forward i'm going to create a new form data and we'll say data dot append first thing that we need to add to uh upload pick to clarinery we need to add a file field which will contain the pic and then we need to add the upload preset field which is gonna be chat what was the name let me it was chat dash app okay chat dash app then we'll add the name of our project so cloud underscore name which was i think roadside coder let me check that again if you go to the dashboard yep it's the roadside coder it's going to be a string and finally after that we're going to fetch we're going to make the api call to that particular url which was this one this particular url so i'm going to copy it up and paste it over here comma we're going to provide it some configurations which will be method will be post request and body oops body will have this form data just like this now whatever the response that we get we're gonna convert into that into json and then we're gonna take that json and we're gonna set our pick state this pick state so set pic to data dot url dot to string this pick state so i'm gonna say set pic data dot url to string and set loading to false because rpg has been successfully uploaded and if any error occurs i'm gonna say console.log error and set loading to false as well now if any of these are not images we're gonna throw error that way as well so else i'm gonna show a toast please select an image and it's gonna be a warning and set loading to false then as well so yep this is how we're gonna upload our image now let's take this loading state and what i'm gonna do i'm going to add it to our button so button so that we can see the loading happening anywhere it's loading will be loading i think it's it will be is loading yep it is loading to loading let's check this out first i'm gonna go to us our app and let's add a picture i'm gonna add this picture yep you see the loading right over there let's see what do we get i think we get an error or something let's upload again i'm gonna refresh this let's try to upload okay okay we get an error cannot read properties of undefined to string okay let's check this out let's see this chat app is okay this chat app needs to be unsigned so click on edit click on unsigned and we're gonna save this now we should be good to go awesome let's try to upload this pic again awesome we get this pick successfully okay let's see we have something called url yep let's take this url and try to go yep we get this url so awesome we have this url successfully now let's try to upload this to our mongodb database so next thing what's left is when we click on this button we should run this submit handler function and start the submit handler what we're gonna do is first of all this will be an async function obviously and inside of it i'm gonna first check the first of all let's set the loading to true main thing okay loading is true now we're gonna check if all of the fields exist i mean all of the fields are filled by user or not so i'm gonna say if name email password or confirm password doesn't have anything so i'm gonna say i mean any of these field doesn't have anything so i'm gonna say please fill all the fields and just display a toast and return it otherwise i'm gonna check if both of the passwords match or not if the password is not equal to confirm password then again we're gonna throw a toast and then we're gonna return it otherwise we're gonna make our api request to store this into our database so i'm gonna add a try catch block let me just close this the data that we're gonna send will be application json right so we need to set the headers for our request so const config headers content type now you need to type exactly as i am typing over here application slash json just like this and after that we're gonna say const const data and we're going to make an api request so axios dot post and we need to import the axios have i installed axios yep i have installed it so import axios from axios okay so axios dot post request and first of all which api endpoint slash api slash user and then we're gonna provide it the name email password and pick and then provide the configuration that we had created up over here okay now let's take this data and store it into our local storage but before that i'm gonna give a toast that registration is successful just like this registration successful status will be success after that i'm gonna say local storage dot set item i'm gonna name it user info json.stringify data and set the loading to false um set loading to false and if the user has been successfully logged in we're gonna push him to the chats page so history dot push and obviously it is history i haven't uh explained about this yet so wait a minute okay so history hook history will be imported from a hook called use history from react autodom so i'm going to say const history equals use history all right and this use history will be important from react after dom or i mean to say like this awesome let's go back down there now inside of the catch if any error occurs what we're gonna do we're just gonna display a toast that error occurred and give the description of the error and set loading to false awesome so i think our work is done here let's test it out refresh this app and then i'm gonna enter let's say jane doe jane [Music] let's upload a picture okay so let's try to sign up so uncaught in promise um okay i think it's related to the chat page and not the login page so i believe that that's working so let's test our database let's check our database if it works or not oh yeah it's working you see jane at example.com and awesome so our front end is working so let's go on and create this same functionality for our login as well so i'm going to clear our local storage first let's clear this up yep let's go to login.js and here also you can see we have email and password states so this is going to be fairly simple inside the submit handler we just need to add the code for it so i'm going to quickly add the code and explain you what's going to happen okay so here it's exactly same as what i did in signup.js so this function will be an async function and we need to add the loading state as well and this for this toast we need to add let's take all of these three things because we're gonna need those there as well and i'm gonna import them here okay so toast is here and history as well const history equals use history okay awesome let's check it out so instead of some submit handler we're just setting the loading to true we're checking if the email or password doesn't exist or i mean are not filled any of those so we're gonna say please fill all the fields awesome then we're making the request to slash api slash user slash login as we already have seen in our backend we're providing the email and password if it's successful we're sending login successful storing it and in our local storage and setting the loading to false and then pushing it to the chats page otherwise we're gonna throw an error and set the loading to false and i think this should work so i forgot to add over here is loading to loading i'm going to say jane at example.com and password let's start login okay we are pushed the chats page and awesome our login is working as well so ignore this error this error is occurring because we you know remove this slash api slash chat endpoint from our back end and to make this gets get guest user credential functional what we need to do we need to go over here on click it's going to set the email and password so to set the email password in the input i need to also add value i need to make it control password and similarly we're gonna add this to our email as well email yeah now if we click on that it's gonna set the guest email example and password awesome so obviously you need to create this guest credentials in our sign up only then this will work but this is helpful when you're applying for an interview so that you're not wasting the recruiters time alright so this was the complete user authentication in our mind stack application if you like this video hit the like button down below and if you want to access the complete playlist to this smart stack chat app click the first link in the description below and also subscribe to the channel for more such awesome videos and i will see you in the next video bye bye
Info
Channel: RoadsideCoder
Views: 86,720
Rating: undefined out of 5
Keywords: user authentication react js, user authentication node js, user authentication mern stack, login and signup in react js, login and signup in react, login and signup page in reactjs, node js login and sign up, MERN Stack Tutorial, MERN Stack Project, mern, mern stack, mern tutorial, mongo db, Mern Stack with Redux, authentication react js node js, react node express mongodb, JWT, jsonwebtoken, node.js + mongodb user authentication & authorization with jwt, MERN chat app
Id: nvjYCK9oDRU
Channel Id: undefined
Length: 40min 1sec (2401 seconds)
Published: Mon Nov 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.