MERN Stack Advanced Authentication Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Can you share the repo link?

👍︎︎ 2 👤︎︎ u/bloodarator 📅︎︎ Jan 08 2021 🗫︎ replies
Captions
hey what is up everyone and welcome back to another video in today's video we are going to be building an advanced learnstack application that handles authentication all the way from the user registering creating tokens saving tokens in local storage in the browser protecting routes and having the ability to reset your password with sending emails to the client and so forth so this is going to be a really big video or project and i really hope you enjoy so let's demo what we will be building today so first off i have my mongodb instance running in the background so i'm not using mongodb atlas i'm just using the local setup if you don't have mongodb locally set up i will link a video at the top where you can go and view how to do that okay so basically what i'm going to do here is i'm first going to register a user and i'm going to register a user with one of my emails so we are able to view everything so let's start i'm gonna say lloyd lloyd jvrainsberg gmail.com and then the password i'm just gonna place one two three four five six one two three four five six and if i were to type these passwords incorrectly so i'm gonna just add it like this and say register it says passwords do not match it clears both of the passwords and then um the error message disappears so just gonna do this right now and register it's gonna register me in the database you can see here we have an authentication token with our json web token being saved and we have access to some private routes or anything that you want to not have the unlocked in user be able to view so if i were to log out we can see that the auth token is going to be disa it's going to disappear and it's going to redirect us to login so if i were to log in now with that same account so lawyer jv rainsberg gmail.com and then password is one two three four five six and i log in i am able to view it here and everything the same so if i also here type in anything incorrectly we have form validation and um everything from that sort so say i forgot my password and i would like to reset my password i can just click on this reset password link and here it asks me to provide email address that i used in this application so i'm going to say jvrains lloydjberensberg gmail.com and then i'm going to press send now this is going to go to our back end and send us an email so i'm going to go to gmail i'm going to open up here and then we can see i got a email from the full stack junkie password reset request so here it says please go to this link to reset your password i can copy this or click directly on it and it will open or redirect me to our applications um reset password page here i'm able to type in the new password so i'm just going to type in here one two one two three four five seven one two three four five seven and then reset it's gonna say password reset success and then give you a link to log back in okay so if i click here and i were to go and use my old password now so the one through six so rainsberg gmail.com one two three four five six and log in it's going to say invalid credentials which is correct and if i use the newly created password now one two three four five and then seven and log in we can see we have access to that route so this is a pretty advanced video it has everything you need to get your website secure and up and running so without further ado let's get started okay so i'm back here inside of my folder i just created a folder on my desktop called advanced node auth and the first thing i would like to do is just go and set up our folder structure for this project so i'm going to make a directory for my front and i'm going to call it client so in my command line and i'm using visual studio code i would highly recommend that um and just to get started if you haven't watched my video where i explain the workflow of how this type of authentication work i would also link that video up and you can go and watch that okay so let's start i'm gonna make dir for make directory and then i'm gonna make a client folder it should pop up here okay great and i'm gonna cd into that client let's actually not do that yet so first off in our root directory so not in the client i want to say npm and net dash y so it will create us a package.json and then just fill out everything for us and then i want to create a server.js file so i can say touch server.js it will create us a server.js file okay so if i confuse if i talk if i confuse files and folders with one another just stick with me bear with me um it's hard enough explaining and coding at the same time okay so in my package.json i'm just going to set the main to instead of index.js to server.js okay so let's build out the rest okay so i'm going to need the following folders i'm going to need controllers i'm going to need a route i'm going to need models i'm going to need middleware i'm going to need you tools and then i think the last one is config okay so i'm going to create all of that okay nice and quick and then for did i spell this incorrectly yes you tolls so it's nice and green okay so the next thing i would like to do is create our front-end build to get that up and running so i'm going to go into my vs code terminal and here i'm just going to cd into the client folder and i'm going to run npx create react dash app create dash react dash app and then just um full stop and this would create it in that client folder i'm gonna run this and while that is running i'm gonna go back in here and i'm going to start installing um the one package two packages we need one is a dev dependency and the other one is our server so i'm gonna say npm i express so this is back in our root directory so not in the client install express awesome and then once the client is done installing and the the boilerplate is set up for our react app i'm going to set up a git ignore so um let's create that file so touch in our directory dot git ignore and then yeah that should create it there you go okay so in here we're going to place our um every folder we do not want to track in our git repository we don't have a git repository yet but we'll do that as soon as the front end build is done while we're waiting for that we can actually go into our server folder and create our basic express um front end our basic express server boilerplate so we can say cons express equals require express we can say initialize that into an app variable so express and then we can say cons port the sport will be equal to whatever is in the process.env.port variable else if there is no such variable we just want the port to run on 5000. and then we would like to go to app.listen and set this equal to that port and once that is listening on that port we want to console.log backticks server running on port and then we place the port variable in here okay so this is the basic boilerplate to get this up and running and we can actually test this by just saying node in our root directory you can say node server.js and it prints out running on port 5000 so this is all working really nicely okay so if you don't know what i did here i would suggest going looking at some beginner express videos so that you understand what is happening here okay the next thing i want to do is actually set up this process.env [Music] setup so that what we're going to need for that so in our root directory um we want to install a package called dot env so we can say npm dot env npm i dot env this will install the dot env package and we are able to require it at the top of our server file so this is important that it should be at the top so we can say require dot env and then we run the function config on this package and to this config function we pass an object with the path field and we set this path equal to dot slash config dot env so we don't have this config.env folder yet a file yet so let's quickly create that in our root directory we can say touch and just call it config.env and save it should pop up down here great stuff okay so in here i'm just going to create in my config file i'm just going to create a port variable and set this equal to 5000 and save and save this so now this process.env will be loaded from our config folder up here file up here okay so with that done this looks almost done with our file setup i just want to clear in so in our frontend folder so in our client folder we want to run the following command rm dash rf and then the dot git so we want to remove the git repo the repository and we want to create it in our root directory so let's go into our root directory if you're getting confused with me switching between these two terminals just let me know in the comments i think this is just easier and quicker and it's very good practice to learn how to work with terminal okay so in our root directory i want to do the following i want to say git init and this will create a master branch and in here in this git ignore we now want to ignore all of the node modules and the config dot env file so let's do that so in our client you can see this is grayed out because of this git ignore so let's copy everything in this git ignore so copy and let's paste it in our root directory git ignore okay we're going to change a few things here first here at the top with the node modules we remove this slash from there and put it at the front and then we can just okay we actually didn't have to remove that at the front so if we go back we can add it like this and then just copy it back down and instead of having the slash at the front we put the slash at the end and then down here where all of the envs are we can say config dot env and save this okay so if we save this and now delete the git ignore in our client folder so we can say delete now all of the node modules and config should be grayed out so the node modules inside of our client is grayed out node modules inside of our root or our back end is grayed out and then the config is grayed out so this is all done so yeah this this looks all complete for me now we have the server set up and everything yeah okay this is great okay so the next thing we're going to do is we're going to start building um our route logic and we're going to be testing it with postman so let's do that next okay so let's start off in the controllers folder basically what we're going to do here is just going to create the end route functions for all of our routes and then we'll go and create the routes and then we'll connect the routes to our server.js file so in our controllers folder we can create a auth.js file and in here we're just going to create that functions so i can say export exports and then the function dot the function name the first function is going to be register and this function is going to have access to the request response and next so we can say request request response and next the next is very important as we're going to use that for error handling later so first off we can just say res.send and say this is register route just like that and save we can actually copy this now and paste it down here and we can name this login it will have access to request response next as well and here we'll just send back login route for now then we can copy this again and paste and change this register to forgot password so this is the function name forgot password and this is the forgot password route and the last route for the authentication will be the reset password so reset password and here we can say reset password route so we can save this now and this exports will export it as named exports so i'll show you what that means in just a second so we can close this up and go into our routes folder and create a auth.js file and in here we're going to do the following first off we have to bring in express because we're going to be routing to our controllers so we can say const express equals require express then instead of using the the app that we have in the server.js here we can create a router and set this router equal to the express.router function just like this then the important thing to do here is export that router variable okay in in here now we can create our different routes to route to that different controllers so i'm going to say router dot route and we're going to route to the slash login or let's first start with the slash register and this is going to be a post request so if you haven't seen this type of syntax yet this is almost the exact same as doing router dot post and then saying register like this and then passing in the functions in here you can do it like this if you'd like i just like i just prefer doing it like this because it's just separate it makes it easier to read and then all of the functions and middleware will be passed in here so at the post we want to bring in that register controller so let's import that so we can say const and then we're going to destructure from the require and here we're going to require inside of the controllers the off file and here we want to bring in the register function so now we can pass in here the register function so this route if we hit this route it will and it's a post request we will run the register controller function so i'm going to copy this once again and then bring it down here and instead of going to register we're going to go to login and now we have to bring in the login function so we can say log in and just add it down here under login okay and do this for all two of the other routes so the next route is forgot password and this will also be a post request as we'll be sending something in the body and this will be the forgot password function and you can see it automatically imported for me as well at the top and then the last route is going to be the reset password route so it's going to be reset password and if you remember from my explanation it's going to be slash and then some reset token that we are going to create so in the forgot password we're going to create a reset password token so here we're going to expect reset token and then we want to add the reset password controller function so everything is brought in correctly and we can save this now the last thing we need to do to get these routes working is connect them up to our server.js so let's close this up go to our server.js and in here just below the app declaration we can say app.use express.json and this is just a piece of middleware that will allow us to get data from the body so the request.body okay now we want to connect our route so we can say app dot use and then we want to redirect anything that goes to api slash auth we want to redirect that to require and then in here we can navigate to the routes folder and then the auth file so basically what happens here whenever a request comes in this piece of middleware catches it and checks if it's to api or something then it will be redirected to the auth router okay and if we save this now and get our server running so let's actually create our script to run our server and we actually don't have nodemon installed yet so let's quickly do that so in our root directory we're going to say npm i dash capital letter d node mon this will just help restarting our server when we change anything okay so let's set up that nodemon script in our package.json here under the scripts our first script is always the start script and the start script will basically just run node server.js and then the next script we want to create for our nodemon is server we'll call it server and here we want to run nodemon server.js so if we save this and we close this up and go to our root directory in the command line and say npm run that server script we should see nodemon throwing us an error here so let's check this out um oh oh here okay so we did something wrong in our process.env so this looks like a silly mistake um in our process.env this shouldn't have a semicolon over there so we can save this and i think we should restart our server now let's try that again cross our fingers okay awesome and it's working so this is great now we can test this in postman so i'm going to go into postman if you don't know what postman is it's just a awesome tool that helps us simulate a front end it helps us make requests um to our back ends okay so i'm just going to close this up you should have um an empty empty browser headless browser and here we can say http colon slash local host 5000 slash api slash auth and then slash register and we want to test out these routes so this should be a post request so if we send this we should get back register route this is great so that means it's working we can go to login route also a post request we can send and this is working the next one is forgot for god password and we can this is also a post so we can send this forgot password route and then the reset password and then the reset passwords get some token so we can send that and this should be a put request okay so now that i've seen this there should actually be a put request so we did not add it as a put request in here so let's go to our routes and change this reset password to a put request we can now save this and go to postman and check this out send and we can see reset password route so this is great all of our routes are working we're able to hit them the next thing i want to do is create our user model and then we can start building on the logic of the controller routes okay so let's do that next okay so i'm just going to close all of these up for now we don't need them and in our models folder i'm going to create a capital letter u users.js file this is just convention for models and here i'm going to import mongoose so we actually don't have mongoose installed yet so let's quickly do that i'm going to stop my server and i'm going to say in the root directory i'm going to say npm i mongoose so mongoose is going to help us create schemas validate schemas a lot of awesome things we can do with mongoose and i'm going to show you a few of them in this video so let's bring in mongoose so we can say cons mongoose equals require mongoose and then let's create our user schema so we can say user schema is equal to new mongoose dot schema and this function takes in an object in in here is where we define our json schema so we can say username we need a username for a user and then we pass an object and this object takes in a type and this type is going to be of string it's going to be required and in here we can pass a array the first value is true the second value is a string that contains the error message please provide a username just like that the next field is the email field it's going to be of type string it's also going to be required and the array true you can sit here please provide a user or email and then the next thing is this email is going to be unique so we set unique equals to true and then we want to match so this is a nice mongoose feature match we want to match it by some regular expression so you can just go on google and type in regular expression for email and you'll find basically this same one i'm just going to copy and paste it in here so this is how the regular expression looks for checking if it is a valid email and then after the match we can add a error message so please provide a valid email okay the next thing we need to do is have a password field so we say password this is going to be of type string as well and it's going to be required with the array set to true sorry about all of these pop-ups and we can say please add a password the next property we can set is the minimum length the min length and we can set that equal to six characters and then we can add a select property here so the select property just means whenever we query for a user do we want to return the password as well and then we're going to set this to false because we don't want the password to be sent back as well unless we explicitly tell ask the query for it okay so that's also a pretty nice feature the next fields to fields are the reset token and the reset expire so we can say reset password token and we're going to set this equal to a type of string and then the reset password expire we're going to set this equal to a type of date so here we can create the the user now so we can say user model is equal to mongoose dot model and pass it the user string and then the user schema just like this then we have to export this so we can say module dot exports is equal to that user model so now we have access to this user model in wherever we're going to use it so we're going to use this mainly in our controller controllers off over here so now we're done with the model let's start with our auth controller so the first thing we need to do here is register a user and in order to register a user we have to think about what we're going to do so first let's bring in the the user model so we can say const user equals require from the models folder we want to require the user so we're going to need a few things from the body when this route is hit so let's extract from the body request dot body and remember we set up this piece of middleware in our server which is important to extract things from our body app.use express.json okay now here we can pass in the username we're going to receive the email we're going to receive and the password we're going to receive okay now we're going to be working with our database so we have to change this function into asynchronous function and we're going to use the try catch block to catch any errors when working with asynchronous code so this is going to look as follow firstly what we're going to need to do is actually just straight up create the user so we can say cons user is equal to a weight and then we take the user model and on that user model we call create and for this create we pass the user model or the created user model which is the username the email and the password now you might ask me shouldn't we hash the password that is correct we should and we're going to do that as a piece of middleware before we save this user okay and once this is done we can just respond restart status of 201 and then return a json object that has success set to true and then we can just respond with the user for now so we can set user equals to user we can actually with ea6 we can just do it like this so we can just see the user being logged and if there is an error i just want to restart status with 500 for now we'll create our own custom error handler in just a second just want to get this up and working and in here we can pass another object with success equals to false and then the error should be equal to that error dot message so we can save this and let's go and test this out so we actually first have to do the encrypt the encryption of the password so how will we do this well let me show you a neat little trick i learned okay so i'm going to close this auth and i'm going to go into the models and right below where we created our users schema just below the user schema we can run a few pieces of middleware thanks to mongoose for pre-saving or post saving so we can say user schema dot pre and this pre will run pre sum function you can say aggregate delete one in init insert many remove we want to run this before it gets saved so here we can pass a function that we want it to run so this is going to be asynchronous function and it's important to use the function declaration with the function keyword and not with arrow functions so in here we want to check a few things first so first we want to check if the password is modified so if if not this dot is modified and then we select the field so the password field so this function will run and check if the password we are passing in so in this function we actually need the next um piece of middleware and if so this will basically just check that if the password we're sending in is not modified it won't rehash it it would just just save save the current password so in here we can just call next and then to actually hash this password we need a package called bcrypt bcup.js so let's quickly install that we can say npm i be crypt js okay great so now we can bring in bcub js from up here we can say const bcrypt just gonna call it bcrypt and require decrypt js and the first thing we need to do with bcrypt is create a salt so we can say consult is equal to a weight because this returns a promise we can say be crypt dot gen salt and gensol takes in a number and we can set that number equal to 10 the higher the number the more secure but 10 should be fine the next thing we want to do is actually change the password that was sent to us so this syntax is a bit tricky if you don't understand that this keyword but just type what i'm doing here so this dot password is equal to a weight bcrypt dot hash and we pass it this dot password and we give it the salt we just generated so it would save the new password in the password field that was passed in and then it would save the document so if i go back to my controller this object is where this keyword lives in so this.password refers to this password field over here so we're setting that password field equal to the hast version of that password and then we can save it so then all we have to do is call next and then it will save so this is pretty neat so you don't have to bloat your controller function with the hashing functionality you can just do it right here if we save this and let's check it out go to postman now have your server running first so we can say npm run server connected mongodb okay we actually haven't connected mongodb yet so let's quickly do that first okay so this is pretty easy in our config folder we have to go and create a db file db.js file and in here we bring in mongoose so we can say cons const mongoose is equal to require mongoose then we create a function called connectdb and this function is going to be asynchronous function this function um we'll do the following we can add a try catch but i'm not going to do a try catch because we're going to have our own unhandled arrow rejection piece of middleware to catch this so here all we can do is say a weight mongoose.connect and then we pass in the mongoose uri so here you can see uri and then some options so the uri i'm going to add to our config file so in here we can say underscore uri and set this equal to mongodb it should be colon backslash backslash localhost it's actually 2707 so this is if you are working in your local environment so i'm going to call the database here [Music] node auth and save this so if you are working with a mongodb atlas cluster you should just add the clusters connection string in here and it should work exactly the same so that is all for the packets of json the process.env folder and in here we can now say process dot env dot underscore uri and then we need to pass a few options first option is new url new url parser and set this to true then we need use create index and set this to true then we need use unified topology and set this to true and then use find and modify and set this equal to 2 as well so once we're done passing in the objects the object with all of the settings we can console.log down here and say mongodb connected just like that now we need to export this function so you can say module dot exports equals connect db so we actually had to do the connection first but it doesn't really matter i hope you're still following me we first need to connect the database before we can actually use this model because now it's just connecting to nothing so here we connect to the database we have to bring this function into our server.js file so let's go to our server.js file and let's bring in that function so you can say connectdb equals require and then in the config folder slash config folder we can navigate into that db file and this is important that the require of the dot env package should be right at the top because now everything else below this has access to this process.env syntax so just below where we create it i can say connect db and here we can say run that function connect db just like this and save and the important thing to do here if we actually go and check it should connect to mongodb but now if there were something to be wrong with our mongodb string so let's say we do this and save and check this again it's actually going to crash the server so we don't want the server to crash like this we want to handle it in a nice way so in order to do this i'm just going to switch okay leave that like that for now but down here we're going to add this app.listen to a server variable and on this server variable we're going to do the following we're going to say process process dot on and on unhandled rejection so anywhere where there's unhandled rejections we want to run this function this function has access to the error variable and then some promise so here we can say console.log and here we want to log that error so we can say logged error and set that equal because these are backticks so we can add the error variable in here and the next thing we want to do is take that server variable we created and call the close function on it so we are able to stop the server nicely without any crashes so here we can say process dot exit and we want to exit with a status code of one so if we were to save this now and go back to our terminal we can see it doesn't have this entire ugly um crash stack we can only see the error being logged and here we can see parse error invalid connection string so this just looks and reads much easier than whatever we had up here so yo you can still see it up here but it's less overwhelming okay so let's go and change our string back to the correct one just save it like this and now we can save and everything should work perfectly fine mongodb connected okay great now we can go back to our register route in postman and test it out so we can go to slash api slash auth and then the register route there should be a post request we want to set all of the headers to application json so the content type should be application json content type and this should be application json right over here then we can go to the body tab choose the raw and in the raw we add an adjacent object where we pass in the fields so the first one is the username and i'm just going to set this equal to test user the next one is the email i'm going to set this equal to test user gmail.com and then the next thing is the password so here we pass in our string password which is going to be one two three four five six and now if i were to save it we should receive a json string back that says success and then the user so let's send this and we get a json string that says success and then we get the user and in here you can see the generated user id test user email and then we have our hashed password so that piece of where we created in the user model over here is pretty neat so right here so this is pretty nice so it first checked if we are doing something with the password if it didn't change it just continues because we don't want to run the rehash on the actual hashed password that would just not be really good so we just continue and here we hash the password and save it to the model before it gets saved okay so the next thing we want to do is handle the the login so let's go back to the controller auth controller and in here we want to handle the login so what do we need for the login first off we need to get things from the body as well so we can say request dot body and what do we need here we need an email address and then a password and it's important because we are logging in and not registering we first have to check that we have the username the email and password provided so we'll check this on the front end as well but it's also good practice to just check it on the backend so we can say if not email or not password then we want to throw an arrow so here we can say rest.status respond dot status of 4 400 which is a bad request and put a piece of json's object here with success set to false and then we can add an error message here to say please provide email and password just like that and if that is not the case now we want to actually go and check this user inside of the database see if this user actually exists in our database so what is the logic for that so firstly what we need to do is once again use a try catch and set this function equal to asynchronous because we're going to make a database request then we're going to do the following we're going to say const user is equal to a weight and then the user model dot find one and this find one allows us to find one user by its email address because the email address should be unique so we first check if this user exists and what we want to do is we want to select the password so we say select and then pass in a piece of string with a plus sign and we add the password field so this will return us a user with its email id and everything we saw and the password because we want to compare the password now so we're gonna first check if we did not get a user back then we want to res dot status 404 for user not found and then return adjacent string of success set to false and then an error where we say invalid credentials just like that the next thing we want to do is actually compare the password and see that it matches so now the user typed in the correct email we found the email in the in the in the database now we want to compare the password that was sent in with it so we can create a const is match variable here and here we want to check if the user's variable the user password matches so once again we're going to go into our user model and create a method the nice thing about mongoose is we are able to create methods on our created user so this user over here we are able to run a method and i'm going to run the method compare password and then just pass it in a password so let's go in there and down here we can create the following just below here we can say user schema dot methods and then the method name which we're going to call match passwords and we set this equal to asynchronous function once again important to use the function keyword and this function is going to receive a password from the user the password we extracted from the body up here it's going to receive that string password and compare it to the one in the database so here all we want to do is return await bcrypt dot compare and this bcup.compare takes in the password we want to compare it to so this password over here and then the this keyword this and we want to compare it to the this.password so what this basically means is we are going to compare whatever this method is running against so this method will run against some user schema or some user model and you remember here here we got the user model so we said user.find1 and it returns us that user model and now we can run this method on this user so we can say await user dot match passwords and this match passwords takes in the password that we got from the body so we can say right over there match password and if we save this and go back here and actually save this now this this password refers to whatever the password is that we selected from the user up here i really hope this makes sense so we are getting the user from the database and we are populating the password field now we're running against that user so against the encrypted password we received we run the match password method inside of our models folder okay so i hope this makes sense okay so and if the password match it will return true or false to the is match and here we can run an if statement to check if is match is not true we want to res dot status once again or 404 with a json object or success set to false and then an error field that says invalid credentials just like that the next thing we want to do if we check both the email and the password we want to respond with a token for this user to log in so it should be exactly the same as up here for now i'm not going to respond with a token i'm just going to respond with that actual user we'll do the json web token in just a second so here we can just respond and i'm going to set token here to just some gibberish string okay and save this actually should be 200 not a 201 and now if you were to go and try out this route this should work first for the error let's just say status of 500 and a json object of success equals to false and then an error set to the error dot message okay so let's try this out get off it's everything is still running fine so let's go to postman and we actually created a user now so let's create a new tab i'm going to copy this url up here and just paste it down here this should be a post as well to the login route and in here the headers should be content type application json and then in the body we choose raw and here we have to provide an email field which we're going to set equal to test user gmail.com and then we need to provide the password field and this is going to be one two three four five six and if we send this now we get success false error match password is not a function so i actually mistyped that so this should be match passwords cap plural and save this and let's try this again send and then we get success true with the token so let's leave one of these out so we don't pass a password so we should get an error there as well false please provide email and password okay so this is the error messages are logging nicely so we're going to create our own custom error handler so everywhere we respond we're going to have a a custom made response and error handler okay so we've done the register and login route which are the two most important the next routes i want to the next things i want to work on is the actual error handlers so we can have nice error feedback our own custom error feedback so let's do that in the next part okay so let's start with the error handling firstly i'm going to go into the utils folder and create a error response dot js file and in here we're just going to create a class so you can say class error response extends the error clause and this clause is going to have a constructor function this function will construct a function will receive some message so whenever we create a new object of the type area response it should get a message and then a status code this message we're gonna set to the super so the actual error message we're gonna set it to message and this dot status code of this class or object we're going to set this equal to status code so this is all we need to do here and then we can say module dot exports is equal to error response and save that so that's all we're going to do in here this is just to create some blueprint for our error response message so if you want to add other things in here you can add it to the constructor function and the construction arguments up there so we can close that up and in our middleware is where we're going to create our error handler so this is a piece of middleware we're going to add right at the bottom of our application which will catch all errors we pass to the next variable so this is important if you know how express works whenever we call next and we pass it some error it automatically gets sent to the error handler middleware so let's create that piece of middleware we can say error.js and this error.js is basically just going to use that error response we created and require out of the utils slash utils slash error response and we're going to have a function here error handler and this error handler is going to do a few things we can do all of our error checking error code checking custom messages everything we can do in here so i'm just going to walk through it really quickly i'm not going to explain everything here so if you're unsure about a few things you can just console.log and see what it actually logged i played around in this for a little while to get this working but it's nice to have because once you get the setup you can basically build out any error message you like okay so we can say here the parameters is error it should always be error first it's important and then request and response and then next so in here let's create an error variable and we're going to spread the error we get up here from the parameters in this error variable and on this new newly created error variable we want to say dot message and set that equal to the error.message next thing we want to do is check let's just add a space there if the error code is equal to eleven thousand or em yeah eleven thousand we want because in mongoose this means duplicate arrow key so we want to create a message and set this equal to duplicate field value entered and we can say error is equal to new error response so we want to have the structured error response and if you remember the first thing this error response takes is a message and a status code so we're going to pass it the message we just created and then the status code for this is going to be 400 which is a bad request the next arrow we want to check for is if the error.name is equal to validation error so in mongoose we get validation errors so whenever it's a validation error we usually get an object of a lot of nested objects so we want to take that object and create an array from it and then add the messages to the message variable so we can say const message is equal to object.values so this takes an object and takes all of its values and add it and creates an array of it so we want to get the values of the dot errors field and then we want to map over this array and then we want to print out for each value of this array we will want to print out or add the value dot message to our message variable over here so if this is if you don't understand this just go and console.log each one of these things out so you can see what it actually builds up to and here we can say error is equal to new error response and set that equal to message and then 400 as well because it's another bad request the next thing we want to do is res.status so all of our responses will come from the error handler so here we can se set the status code is equal to the error dot status code so the area we created either here or here or here we're going to check the status code if there is no status quo set it's obviously a server error so you can just add it to 500 500 and then the json object we want to return is going to look as follow we're going to have a success of false because it's obviously the error handler and the next thing we want to add is the error message so we can set error field equal to the error dot message or if there's no message added so if there's any other errors besides these two that we're actually creating so this is the nice thing you can start building your own things in here if there's no error message there then it's obviously a server error okay and save this and then we can actually export this module dot exports is equal to error handler just like this okay and in order to see the error we actually can go console.log and we can log the area so this is where i built this these two from so if you start dissecting what error you get you can look at the error code error name and you can see what the error actually has so here the arrow has the errors field and so forth so this is a pretty nice way and this is a pretty robust way of doing it okay so now let's bring this error handler into our server.js so at the top i'm going to say error handler and set this equal to require and then into the middleware metal where and then the error file and this is important where we should place it it should be the last piece of metal where so here's a piece of middleware here's a piece of middleware here we get the port here we run the service so right below here i'm gonna say error handler should be lost piece of middleware okay so we say app.use and we pass in the error handler just like that nothing else just like that and we can save okay so this looks fine okay so let's test this out so let's quickly check what it says app.use requires a middleware function so let's check what i did wrong oh i exported incorrectly export x module dot exports okay so that's my fault and then we do not need to run it as a function here we can just pass in the function because it will redirect everything to that function so let's run that again and it's working so let's test it out so remember in here we're going to log the error but we'll be returning our own custom arrow so in our auth instead of using the this error over here we can now just say next and this next is going to be equal pass it the error just like this and let's do this at the login as well so everywhere in the login where we want to return an error so over here we return an error over here we return an arrow and over here and then down here instead of creating our own arrows here we can just bring in the error response so we can say const error response is equal to require into the utils and then the error response so hopefully you'll see the the the benefit of doing it like this and the register we only pass it to the next so it get handled from there here inside of our routes we have custom so we can actually return with the next and then in here we can say new error response and set it equal to some message and this message is please provide an email and password so it just gives us if you have a big application a big api you have um a better robust way of doing it instead of repeating this thing the whole time so this is handled in one place okay so we can actually copy this oh it needs a status code remember it needs a status code so in here right after the message we give it a status code of 400 which is a bad request and then here we can do it again we can return next error response and then this should be invalid credentials like that and this is a 404 for user not found or bad uh yeah user not found and then when the passwords do not match invalid credentials again and then just 404 with the same okay this should actually not be 404 it should be 401 for um unauthorized yeah that that looks fine okay if we save this now check it out is everything still running fine go to postman now we can test it out by pressing login and we can say please provide a password so the the the errors are working and in here we can see the area is being logged so this is the error response please provide email and password this is one we created because it's from the error response we created okay so i'm just going to remove that console.log so we don't have a big messy console the whole time and i'm gonna clear this out okay so we've got that all working so next up let's do the json web token and the authentication middleware or the protect middleware okay so let's start with the actual token token part okay so let's start with register here we don't return the user we're going to return some token here as well for our front end okay so now you can see that this response and this piece of response are exactly the same the status code just changed from 200 to 201 so i'm going to actually refactor this into a function and i'm going to call this function send token so i'm going to say const syn token so right at the bottom of this file and this function will have access to the user we just created because we're going to need the email and the id then we need the status code and then the response cycle so in here in here all we're going to do is say cons token is equal and then once again we're going to go into the user model and create another method that would generate a token for us so everything related to the user model stays inside of the user model file so let's create that so we're gonna once again say user schema dot methods and give it a name of get signed token and this function is going to use json web token and return us assigned token so in order to use json web token we should actually first install it so let's go back to our root directory and say npm i json web token once this is done installed we can require it at the top of our folder file so up here we can say cons jwt equals require json web token just like that now we can use that to say the following we can return directly from this method we can say jwt dot sign and this sign takes in a few things it takes in some payload it takes in a secret and then some options so the payload we're going to pass it is just an object that contains a id field and this id field is going to be equal to this dot underscore id so once again this refers to the method this refers to the the object we are calling this on so we are calling it on the user's object so we're gonna say user.getsigned token so on this user we get which is brought in from up here we have access to the this dot underscore id so i hope this makes sense okay so the next thing we need to do is pass in some secret i'm going to create a secret inside of the process.env so i can say process dot env dot jwt underscore secret and the next thing is object of options and the options i want to pass in here is expires in and the expires in i'm also going to set equal to process.env.jwt underscore expire if we save this and go to our terminal i want to actually generate a random digit for our secret so we can say node and just go into the repel and here we can require the crypto package and we can run on this package we can run random bytes and for the function we pass in let's say 35 a string of 35 and we want to say to string because it's going to return a buffer and the two string should be of type hex and if we save we get this randomly generated string okay so i'm going to use this as my json web token secret i'm going to copy i'm going to go into my dot env and here i'm going to create two new environment variables the first one is json jwt secret and set that equal not the string version but just that token so we have a nice long secure token you can place anything in here i just like doing it like this because it's pretty much secure next thing is jw2 underscore expire expire is it expires or expire i can't remember what we said um expire okay and here we're going to set this equal to 10 minutes so you can show 10 minutes in this fashion so if we save this close this file okay this should return us exactly what we want process.nv and once again this has access to the process.env because we use this model in the auth folder which is down which is below the initiation of the the package okay so let's test it this out now so we're actually gonna get the token so we can say and what did i call it get signed token get signed token just like this save okay so it should return us the token now so we can say res dot status is equal to the status code that was passed in and then here we can say json and set success equals to true and then we pass in the token we just generated so it just keeps our controller functions nice and clean so now we're going to use this send token function all the way up here so everywhere we return with a token so we can say send token so it's just a little bit of refactor and the send token takes in a user so we can pass in the user up here and it takes in a status code so this is going to be to one and then we can add it a response so we pass in the response variable up there okay so we can copy this and do it exact same for the login login route we check everything here check everything and down here we want to return but instead of 200 we have a 201 now we can save this and go check it out in postman and make sure that everything works so we can exit out of the ripple and then restart our server let's check if we have evers no errors okay so let's try this out so now if i were to log in again with the user we already created the password was one two three four six and let's see send and here we got it we got success and we got the token that was generated so this is a nice way of handling it if i were to go to register and test this out now and create a new user let's say test to user it's actually unnecessarily long but it's okay and let's say test two let's try this out this should send us a a json web token as well so we can say send and we get adjacent web token returned so we got the token set up we got the routes register and login setup we've got the authentication and the authorization checking to see everything is filled in we have our own custom error handler the next thing i want to do is actually start building the protected route so we can use the piece of middleware to check the the um the json web token so let's quickly do that in the user model we can close that up for now i believe and then the area we can close up and in this middleware i'm going to create a auth.js i actually like to call this protect but i'm going to call it auth because you can place a lot of authentication pieces of middleware in here so what this off piece of middleware is going to do it's going to check for a json web token in the headers so here we're going to import jwt equals jwt and we're going to need the user model so we can say const user is equals to require and then in the user model models folder we get the user so we want to export a function called protect and then here this function is going to be asynchronous function that has access to the request response and next and in here we want to create a token variable then we check if the request.headers dot authorization exist and the request dot header headers dot authorization dot starts with so this is javascript function and we can say starts with starts with and then bearer because if you know anything about this we're going to add bearer in front of our token to show that this is an authentication bearing token or header and if that check resolves to true we want to set the token variable equal to the request dot headers dot authorization dot authorization and then we want to split on this variable or this token or this piece of string we get from the header we want to split on the space because this is going to look like this if i were to go here it's going to be bearer and then the json web token will be in here so it's going to have the space so we want to split on the space and then take the second part because this is going to be in the first part of the array and this is going to be in the second part of the array and we want to set the token in here okay so now we got the token and now we check if not token so if there was no token found inside of this header so the header was actually there but the token you know we didn't get anything from the token so say someone just added bearer in a header and an authorization header we actually have to check that there is a token so we can check if there is no token we want to return with our error response handler so let's bring that in const error response equals require into the util utils slash error response and once again we add the next so the error handler will catch this and we say error response is equal to not authorized to access this route authorized to access this route and the status code of 401 for unauthorized so here you can once again see the reuse of our custom error handler which is really nice the next thing you want to do is add a try catch block and in the strike catch we're going to decode the token we just got so we can say const decoded is equal to json web token or jwt dot verify so what verify does is it actually decrypts the token as well and we get token we pass in the token we got and we say process dot env dot jwt underscore secret because it's going to decrypt or verify based off of our secret next thing we want to do is say const user and we're going to find a user so we're going to say await user.find1 and we're going to find one by id okay so we can actually say find by id not update just find by id like this so find by id and where are we going to get this id well in the in the token so when we actually created the token you remember we saved the user id in there so here was the payload of the token we added the underscore id of that user in the token so now we're going to search by the decoded dot id so if we don't find a user so if no user was found then this token is obviously not valid so we can say return next new error response and we pass no user found with this id and we pass 404 for not found okay and the next thing we want to do when we get to the end of the validation of this middleware we can say request.user so on the request object we want to set that user so that user we got got here we want to add it to the request.user which we are going to be using in our other routes to do different things and then we want to call next on the middleware to continue to the next piece of controller in the in the route so here we can say return so if something were to go wrong in the strike catch we want to return next with the new error response and this is going to log not authorized so something went wrong here so you're not authorized to access this route and a 401 status code for not authorized okay so we can save this and this is the entire protect function now we can use this in protected routes so we can just add this piece of middleware in protected routes and it would first check if the user actually has a token so let's actually create a new route in our routes file so we can say private.js and we can just create a basic route that is going to check for a user so we can say here const express equals require express oh express and then we want the router variable and set this equal to express.router excuse me the next thing we want to do is create that route so we can say router.route and this is just going to go to slash because we're not going to have any other routes but you'll have more routes in here if you have like private routes you want to protect and in here we can say a get request to some controller function so we'll create that controller function in just a second let's just export this so module.exports is equal to the router so we save this so this is not even connected to our server.js but let's first create the controller so in the controllers folder we can create a private.js file and in here it's just going to do something really really simple we're just going to export get private data let's say and set this equal to a function that has request response and next and all we're going to do here is say rest.status of 200 and a json object of success which is true and then data on this route is going to be you got access to the private data in this route very simple the idea is not behind that route it's just how to protect that so now we can bring that controller in we can say get protected okay actually get private data equals to require and then into the controller's folder we get the private file and we pass in that controller function if we save this and go to our server to connect up this route we can go over here where we add the api auth and just copy this down i just press shift alt and down arrow and here instead of going to api auth we go to api private and the require route is also just routes slash private if you were to save this now and check our application no errors but i want to show you we're not protecting the route yet so let's go to api auth private make a get request and we can remove all of this from here and we can send it says you got access to this private route so how do we protect this route well it's really simple from here all we have to do is import that protect middleware so we can say const equals require from the middleware we can check the auth file and here we can bring in the protect piece of metalware and just add it in front of this route so we can say protect and it should protect our right now and the reason for this is if we don't pass a json web token what is going to happen it's never going to call next so in here if something went wrong it never calls next for us to continue to the next route it just calls next to send us to an error page so here if i were to send now it's just going to hang let's go to our cannot find model module jwt so let's see what i did wrong here this is in the auth js private route okay let's see let's see so this is auth and we're using json web token and we actually okay this is not json web token it should be json web token like this okay and if we save this and try again okay it should actually work now and send we can see not authorized to access this route so now we are actually protecting this route and in order to get access to this route we're first going to have to log in so let's log into a user and get a token log in with this user test user one send and we get a token back let's copy this token and now we're gonna add this token to our headers and we're going to set an authorization header and set it equal to barrier like this and space and then add that token now if you were to send it is success true and you've got access to this route so it actually checked and authorized us for this right now so we've got that all set up and done the next thing i want to do is going to start building the forgot password and reset password what we're going to need to do there is connect with sendgrid and load mailer and set emails and so forth so i hope you're still with me i know this is a long video but i'm doing it for you guys and the more you learn the better so let's continue to do that next okay so let's go to our routes all throughout here i'm just gonna this is the middleware server we don't need anything in here anymore so we're going to go into the controller's auth and then just close everything here that we don't need we're done with the register we're done with the login now we're going to start working with the forgot password and the reset password so if we think about what is going to be needed in the forgot password if you remember from the previous video we're going to get the email from the body and then request.body and here we're going to have a try catch once again so this is going to be a synchronous function because we're going to check does this user actually exist in our database so you can say user dot await user dot find one and we're going to find by that email so we check if this user exists so if this user does not exist we want to return next sorry new error response and no [Music] email could not be synced just like that because you don't want to tell the user or anyone that this email does not exist in the database or it does exist in the database this is just a form of brute force security so we just um stop this a little bit so here we can say 404 on the status code and then the next thing you want to do is actually create or generate this token so we can say const reset token is equal to something on this user we found so once again we're going to go into the user model and basically what we're going to do here is generate that token that hash token so down below we can create another method called user schema dot methods and we can call this method get reset password token this function is going to do the following we're going gonna generate a reset token with the package crypto so the same one we used for the json web token um secret so we can say const crypto is equal to require crypto and then down here in the function we can say const reset token is equal to crypto dot random bytes and we're going to set this equal to 20 random bytes and do string and hex okay so now here this should be a dot to string okay so now here we have our reset token now we want to hash this token and save the hash version in here so how do we do this well it's easy we say this dot reset password token which will refer to whatever object we are running this on so the user we're going to say user dot what did we call this git reset password token get reset password token on this user we're going to add that field so reset password token and we're going to set this equal to crypto in order to hash this we say crypto dot create hash create hash and this create hash takes in the type of algorithm so s h a five two five six this all comes from the documentation so update and we want to update it with the reset token next thing is digest and to hex okay so now we created the reset password token hash and we added it to that object we haven't actually saved it to the database yet so this is just creating it and adding it to that object and here we can return with the reset token so what happened here is we added a new field to this user and we returned the reset token so now what we can do in the auth route is we can actually save this user now so we can say await user.save and this will save the newly created field so the reset password token field to the database okay so one thing we actually did not do here here is we um we didn't add the reset password expiration so this we did not add so we actually have to do it in this function here as well so let's go down here and say this dot reset password expire and set this equal to date dot now and we want to do the following calculation so we want to set it into the future so for 10 minutes so in order to get 10 minutes you plus 10 or and then times 60 times one thousand so this gives us one minute and then times ten is ten minutes and then just uh multiply um just add it to the date the current date now so we get the date into the future okay so we can save this and then go to auth.js and here we save it and the reason now you can see why we added this check if the password is modified because now we are saving the user once again but we did not do anything to the password we just added these two fields so this is what this helps check so it doesn't go in crazy and say oh there's no password whatever okay so the next thing we want to do here is go and we save the user now we want to create the usage the reset url so we can say cons reset url is equal to backticks and we can http localhost and here we point towards our front end so whatever domain your front end is running on you want to add that here so you can actually put this in environment variables and then get it from there so here we can say 3000 slash password reset and then slash and then add that token so reset token the token we got from up here now we have the actual link we're going to email to the um the client and then the next thing you want a message so we can say message we want to send to this client and this is going to look as follow backticks once again and in the backticks the nice thing is we can embed html so we can say h1 you have requested a new a password reset and then just close the h1 we don't have emit here so that's pretty bad but you can create nice templates with pug and then just um put the pug template in here instead of doing it like this but i'm not going to do that now please go to this link to reset your password okay and then next thing we want a h href a h tag a tag and set the href equal to the reset url so once they click on this link we want to take them there and then another important property to add here is click tracking and set this equal to off and the reason for this is when we use our emailing service which was is sendgrid and they add a weird looking link it takes you to the same route but um they reroute it through them and we don't want that so we just say click tracking and set it to off and here we embed our reset url once again so this is what the client will see and this is where we'll redirect you so these they'll see the same thing and then close the h the the a tag now we want to send our email so we're going to actually use a try catch here so let's try catch inside of our dry catch but yeah we can do that and then here we're gonna send our email so we first have to create a email sender and to do this we're going to use node mailer and send grid so [Music] let's actually go into our utils and create a send email dot js file and in here we're going to import node mailer so let's quickly first download node mailer if you don't know what node mailer is just go to node mailer npm this is basically just the email smt relay server it allows you to send emails through gmail or any other email provider we're going to be using syngrid so you can say npmi node mailer just like that okay so now we can import that so we can say const node mailer is equal to require node mailer and create our send email function so this email function is going to be pretty dynamic so you can use this across your application not just for password resets so here you can say options gets passed in it's going to be an object and first we create our transporter so we can say const transporter is equal to nodemailer dot create transporter and this function takes in an object we're going to set a few properties the first one is service and we're going to get the servers from process dot env dot email underscore service so this is if you want to use a different email service you can just change it in the environment variables so the next field is auth and auth takes in an object which has a user field which takes the process dot env dot email underscore username the next one is password for just pass process dot env dot email underscore password so we have not set any of these things yet we'll do that now we're first going to set up a send grid account excuse me it's first going to set up a same grid account and then we're going to do that okay so the next thing in this function we want to create is const mail options and this is an object that has a from field it has a to field a subject and a html so this is just like any other email you'll send the from is going to be process dot env dot email underscore from so you can set your email or whatever um a business email you want to send from and then option dot 2 so whatever we get from the option it's going to send to that email and then subject we're going to get options dot subject and then the html here is going to be options dot text okay just add a comma here then we can say transporter so the transporter we just created and we can call send mail on it and this mail takes in the mail options we created it takes in a function which has an error or some info about the email that we just sent and here we can say if the error if there is an error just console.log that area for us else if there's no error then we have a successful email being sent so we can say console.log the info so that we can just see what is logged here then we need to export this function so you can say module.exports and set this equal to send email okay so we're done with creating the send email now we have to go and add all of these environment variables and in order to do that we're gonna first have to go to send grid create an account and then we'll go from there so let's quickly do that okay so here i'm on the sendgrid.com website the first thing you're going to need to do is actually sign sign up for start for free it's going to ask you for your email address you're going to have to do a few verifications for your email it's just going to have to check that it is an actual email you're entering because this entire software or this entire service is forwarding emails based off of an actual email so this is a really nice um service i really recommend this they have different price to your pricing tiers so if you go to pricing you can see that you get a hundred free emails a day um for zero uh zero cost and after that you can scale up to a massive amount of emails and then the price will adjust from there so for for a thou for 100 000 emails a day or a month you can pay thirty dollars which is not bad um so for a basic website getting more than a hundred emails a day for start is probably not going to happen so here it is for free and once you've signed in and logged in and then you will be able to see this dashboard so i have seen send a few requests obviously because i've tested this out okay so in order to start we're going to go to our dashboard profile on the side and you're going to go to setup guide and on the setup guide we're gonna click on send your first email the send your first email gives us two options build a send using marketing campaign or integrate using a web api or smt b relay so we're going to use this smtp relay simple mail transfer protocol okay so we click on that and here we have an option to use the web api so if you haven't checked out my video on using cengrid i actually use this wave api it's pretty nice pretty simple but we're not going to be using that today we're going to be using node mailer so we're just going to click here and say choose here it's going to ask us for an api key name and i'm just going to call it node advanced underscore auth just like that and say create key and here we can see our details we can see the username is api key so if you remember from our code here we have the email username which is apr key and the password which is this really really long string here okay and then the port and everything um and the server and everything will be set up if we add for node mailer we can just say send grid here and it would pick it up by its automatically so let's copy this api key go to our process.env and here we can say email underscore let's first do that in order so we first have the service copy that paste that in here and set this equal to send grid just like this just like this all my words are disappearing i've been talking for a really long time now email and then we can say username is equal to api key the next thing is the email underscore password and this is important that you create your own account and do this on your own because i'm going to disable this after the video so this is not going to work afterwards and this is important that you copy this here because whenever you say i have updated my settings and go to next you won't be able to see this key again so it's important to copy it here and then just paste it right in there we can save what do we need we got password and then the from so email from this should be the same email you verified um when setting up your sendgrid account so this was the fullstack junkie at gmail.com so it's important this email should be the one you verified for your sendgrid account okay what do we need more let's see let's see i think that's that's it okay that is it okay so now we can go i've updated my settings and click next verify and send an email from your application using your code just integrated if that runs without error click verify integration so let's keep this tab open and let's continue here so we can config save the config file and in our user i believe we're not going to do anything here anymore yeah i think i think we're done here and in here is where we're going to send our actual email now so this is going to be pretty the exciting part so we can say wait send email so we first have to bring in that function at the top so we can say const send email and go into the utils folder utils and then the send email file so we can run that function and then we have to provide a few options to that function so this options is going to be a object the to is going to be the user.email so why do i say the user.email well we got the user by checking if it's email exist and then we actually extracted that user from the database so now we have access to user.email the subject is going to be password reset request or whatever you like here and then the text i'm going to set that equal to the message the message we just created here you can actually name this html or whatever it doesn't really matter okay and the next thing we want to do is say res.status and we want to respond over 200 and then json object with success equals to true and then the data of email synced just like that and if there were to be an arrow here this is important if there were to be an error we want to take the user and set the reset password token we created and set it equal to undefined because we don't want that to stick around anymore the next thing is on the user request password expire we want to set that to expire we want to set that to undefined as well now once we've done editing this user we want to save it again so we can say await user dot save and then when we're done we want to return with next and a new error response so now you can start seeing that this custom error handler really saved us in the beginning it was kind of oh why do we have to do this but now we kind of see the the nice thing about it so we can say email could not be sent so the exact same we added up here email could not be sent and then a status code of 500 because this is a server error this time but we still add it here and then down in the last catch we just want to return with the next and pass in that area and save this so we're done with setting up our forgot password now we can actually go and test it out in postman so i'm gonna restart my server run server let's see if we have any errors doesn't look like it this is great okay so let's go to postman and let's make a post request to http slash localhost 5000 slash api slash auth slash forgot password and this forgot password is going to have content type of application json content type of application json and then we go to the body tab raw and then in here we have to provide the email that actually exists in our database so the important thing here is it should be an actual email so we can test it out and currently we don't have a real email in this database so let's first actually register a real email so we can say register and in here i want to add my lloydjv rainsberg at gmail.com let's see if that's correct jb raynesburg it's multicore my password is that and username i'm just going to set this to lloyd and now we can send this it should create it successfully and it did now we can go to the reset or forgot password route and add that lloyd jvrainsberg gmail.com and let's send cross our fingers success true data email was sent so let's go into my emails and check gmail.com let's see if it was sent and here we got another email we got the previous one when i was demoing the project but here you got a new email you can see it's the same time as now and we got the reset password link so this is great the last route we should build on now is the actual uh reset password so this is pretty simple so let's quickly do that now okay so we can close this one up here and basically all we're going to do here if you remember from the video where i explained this process we're going to recreate the reset token reset token and we're going to recreate it by saying crypto dot create hash and we're going to reset this based off of the the reset token we got from the request params so if we remember in our routes here we have this reset token in the param so when we make a request to this route reset password we send the created token in there as well so if i actually go to my database and i say show dbs and i say use what did i call it um node underscore auth and i say db.users.find and i pretty print them we can see that there is this reset password expiration and respec reset password token being logged or being added to this user so now we have to go and recreate this token based off of the token we get in the url so um in order to do that we're gonna say reset password token and we should actually bring in the crypto module so we can say const crypto is equal to require crypto and in order to recreate this we do the following we give it a create hash and the sha 256 dot update and we pass in the request.params dot reset token and then digest with hex okay so now we have recreated that password now we have to search for a user that has this same token in their document so we can say try catch once again and this is going to be asynchronous function because we're going to work with the database and in here we say const user equals a weight user.find one and we want to find the following parameters where the reset password what did we call it so let's go into the model reset password token so where the reset password token is equal to the reset password token so they have the same name so we can leave it like that and where the reset password expired has the following query so in mongodb we can say greater than so we want to check where this exposed date is greater than it currently is now so this ensures us that the token is still valid so that the expiration date that is saved under the user is still greater than the actual time now and once we got that we can check if there is no user we want to return with next and a new error response and add invalid reset token so they know it expired and 404 for bad request not 404 400 sorry and then once we pass this so it's actually there we got a user we want to take that user and set the password equal to the request dot body dot password so now we're going to send the new password and here we want to just set the request reset password token equal to undefined because we already used it now so we don't want the user to reuse it again so we're just going to clear this out the same goes for the expiration date expire just like that and then you guessed it we have to say await user.save and now it's going to resave the password and hash it because in the user model this part is going to pick up that it was modified okay so then we just want to return rest.status 201 dot json and we want to have a success of true and the data of password password reset success and that is that and then if there's an error next dot error make sure i edit the next uh i did okay so that is done with this route and we're basically done with the api now so let's actually test it out now we save this is there any errors no errors looks like it so let's go let's go try this um that email that previous email i got let's actually try that so you can say gmail.com let's actually try this email this uh string i got here so i'm just going to copy this part because that's the important part i'm going to copy that i'm going to go to postman and i'm going to create a new tab and make a put request to http localhost 5000 slash api slash auth slash reset password and then i paste in that created reset token and in the headers this is going to take in content type application json on the body we go to raw and now we have to pass in a password field whatever we would like to reset this password to so i previously had if you remember one two three four five six so i want to change this to one two three four five seven and send let's hope this works invalid reset token okay so obviously ten minutes has gone by so let's actually try and resend this email so i'm gonna send it again email sent okay so i'm just gonna go here and refresh we should get three now great stuff so it's working let's get the new token i'm gonna copy this token go back to postman paste that token in here just like this and then i'm going to reset the password so let's see send and it still gives us invalid token okay so that is not correct because it is an actual valid token this is weird am i doing it to the right route localized 5000 api reset password and then the token so obviously missing something let's go let's actually open this and i'm going to copy it from here let's try that again paste it in here and send password reset success okay so i obviously missed something okay so this worked now sorry about that and now we can go back to login and try logging in with our new password so we can say login i'm going to remove the username and i'm going to try and log in with the old password and send invalid credentials now i'm going to add the new password and say send and boom we're logged in okay so our entire api is done now we have the entire authentication workflow set up and done we have the protected route where we're sending emails and all of those nice jazz so i'm gonna do a quick run through of the client this is probably the easiest part of this entire application and i'm gonna be pasting most of the style sheets in the client so that i don't bore you with that so let's do that next okay so let's go to our react application over here and all i'm going to do is going to the source and i'm just going to clean out some of the things we don't need we don't need the app.css app.test.js we don't need that index.css will keep index.js local at svg can go and then the setup test can go as well and then in our index.js we want to just clean this up i hit it when it does that and index.css we can actually clear everything out here i'm just going to paste a few styles in there in just a second i'm going to change this app function to a functional com error function like this i'm going to remove everything from the body here and then i'm just going to say react app save this we can remove the app.css as well as the logo.svg so we can save that okay so this all seems to be fine okay so let's just run this and see if it works so in our um vs code terminal we're in the client so we can say npm start to just see what it gives us you can actually close this up now it's just going to give us a react app that just says react app or app component react app there you go okay so let's start with creating our folder structure in here so we're gonna have a components folder and in the components folder we're gonna have two subfolders we're gonna have routing which is going to contain our private route component and the next one is going to be screens and let me start by adding the css of the index.html these are just a few styles i'm not going to bore you with this if you want to see more css um things just let me know in the comments down below but i'm going to save this i'm going to close this up then i'm going to go into my app.js and we here we're going to start building our application so first things first we're going to need to install a few things the things we're going to need to install are as follow we can say npmr and react that's router. and then we're going to need axios so these are the only two things we're going to need in here so you can install that and remember this is in the client directory okay so access is just going to be to make requests to our back end and get this set up okay so we got that done and then one thing i want to change in my package.json is just add a proxy so we can say proxy this is important to do this so that we don't get the cross origin error so you can say http slash one so localhost you can just say one you can actually just say localhost but i like typing it out like this just looks fancier just kidding and then the r and then the port we're running on is 5000 we can save this now it will anything that has axios request will be routed to there if it doesn't have its own specified okay but in the app.js i'm going to do this really quickly we have to import the browser router the route and the switch so we can say import from react router dom and here we can import browser router and as router we can import switch and the route and in here we're going to build our router so we can build our router and in the router this should actually be the top most component and in here we're going to have the div of app so turn it like this and then in here we have switch which is going to have different route components so the first route component is going to be our exact path of login and it will load a component called login screen so we don't have that yet so next one is going to be the register and the register screen the next one is the forgot password password and then we're gonna name it forgot password screen just make this smaller and then the last one is going to be the reset password if you remember from our email we sent when we created the actual reset url let me just take you back there we created the front end link so we said http slash local as 3000 which react app is running on 3000 then you have password reset so this should be the same this should actually be password reset because it's going to route us to that and then some reset token just like this and then this is going to take us to the reset password screen if we save this we don't have any of these screens yet but let's first create our private route so in our components let's go to the routing and here i'm gonna call this private route dot js and this private route is going to look as follows i'm just going to run the component snippet rafce creates us a error component we can remove this we want to import from react router dom the redirect and the route and here we want to go to from react dash router storm and we're going to build out our component so first off we can actually do the return like this and this should be a route and in here is where all of the magic happens so we want to first off spread everything we get from this route so we bring that in here so as props we can say component and set the component equal to a component class or component object and then re rest so we spread all of the things that we pass in the route and the next thing we want to do is render and this render takes in a function and this function will do the following this function receives some props and this function will check is there something in our local storage so we can say get item and we're going to name it auth token and we want to check if we do find this in our local storage then we want to return with a component so whatever component we passed in in here so remember we say component so whatever we pass in here we want to render that now so we can spread the props and if this is not the case and we did not find the token in there we just want to redirect to slash login this will kind of block the entire process of that user visiting this route so this is the entire private route it's pretty simple we use react router dom we create a route we check if there's something in the local storage you can actually make this a function and say is logged in and if it is um you render the component that it is supposed to render i'll just redirect to the login page okay so we're done with that so we can actually import it here so routing um import private route from component slash routings less private route and right at the top we can say private route and this will receive the following things we can say exact path because this will be spread into this component and just the home route so you have to be logged in before you can visit the home route and the component it should render is the private screen route so we don't have any of these screens yet so we're going to do that in just a second so let's actually import them already so screens and then we'll go create them import private route from the component slash screens and then the private route screen or the private screen sorry not private route is private screen this should be private screen as well okay so now we can just copy this down for all of the other so it's one two three four one two three four and let's just copy that login screen it's going to be login screen login screen in the register screen it's going to be register screen register screen let's do that for all of the rest forgot password screen and then reset password screen okay so now we brought all of them in now i actually have to go and create them so i'm going to close up this auth i'm going to go into screens and create these files so the first one is private screen dot js we're gonna need a private screen dot css as well the next one is login hit it when it does that the next one is login screen dot js and we're going to create a login screen dot css as well register screen dot js register screen register screen dot css register screen dot css okay i'm just gonna close these up for now i don't want them to open like this okay we need the forgot password screen forgot password screen dot js and then the forgot password screen dot css and then the last one is reset password screen dot js and then reset password screen dot css okay that is done so first off um i'm just going to paste in all of the styles so let's start with the login screen or the register screen css registerscreen.css the styles are going to be of the following you can just go into the github repo and copy them this is how the styles look like very simple you can save go into the login screen dot css gonna copy all of it from here paste it in here it looks very much similar to the register save that let's go into the forgot password screen i'm gonna copy that going to forgot password paste that in here save that and the private screen i don't think this really has much css yeah it actually doesn't have any css so that's pretty cool um yeah we can actually delete this file not gonna need any css there and then the reset password is going to look like this we can save that so now all of our css should have styles in okay great i'm not going to focus on the styles here so let's start building i'm going to start building the reset or let's go to register login and private okay so the register screen is going to have the following structure we're going to import use state from react then we're going to import axios from axios we're going to import the link component from react router dom from react router dom and then we want to import the css so we can say import register css now we want to create our functional component so we can say register screen is equal to functional component and right at the bottom we can say export default and then the register screen component and in here we're going to be building first off let's get the jsx ready the jsx is going to be the dev with a class name of register screen and then we're gonna have a form which is going to have a class name of register dash screen underscore underscore form and in here we're going to have h3 with a class name of register register screen underscore underscore title and we're just going to say register over here next thing we need is a div with a class name or form control it's a form group sorry form group these styles are in the index.css you can see it's over here because it's universal styles for the login and the register we can just reuse that and in here we want to have a label the label should be for name and we can add here username then we want to input input which is of type text it's going to have a field of required a property of required it's going to have an id of name so that it matches the label it's going to have a placeholder of enter username then we're going to have a value which we're going to set equal to username and this username value we're going to add state in just a second so we'll do that now then we have a onchange where we're going to call the unchange function and this unchanged function is going to call it set username and we're going to set it to equal to e dot target dot value and the e should be passed in over here and that should be that so let's actually create that piece of state so we actually have to return this entire blob over here so let's do that we say return and then just wrap these in there now we can bring in that piece of state so we can say const username and set username is equal to use state and set that to empty string okay so that should be satisfied okay the next thing we need is the email form group so i'm just going to copy this form group copy this and paste it in here this is going to be email and for email and the text the type is going to be email required to name email enter email address or let's just say enter email this value is going to be email and the set email so let's create that piece of state as well copy this down email set email okay this looks fine everything looks fine there then we need to get two more copy this paste it this is going to be for password this type is going to be password required and then the id of password enter password the password variable or state we're going to create that now and then set password let's create that piece of variable or state password and then set password i've said that so many times now okay and then the last form group is going to be for the confirm password and let's set the label to con firm confirm password we can add the confirm password here and in the id down here it's still a password still required and here we can just say confirm password this is going to have its own piece of state confirm password and then set confirm password like that we can save and we can go and create that piece of state did i actually name it correctly down here capital p okay and then confirm password okay so we're done with setting up the state and two-way binding so let's just add the button down here we can add a button it's going to be of type submit it's going to have a class name of btn btn dash primary and in here we're just going to say register and just below the form or just below this button we're actually going to have a span that says already have an account question mark and then we want to add a link component to link it to the login page so we can say login and then to the slash login route this should have a class name oops clause name of register the screen underscore underscore subtext we can save this now and this actually should all be fine now we can create the logic for when we have this on submit so we can say on submit and we can say register and blur okay so the register handler is going to look as follow we're going to do all of the http connection there so const register handler is equal it's going to have an e so we can say e dot prevent default because it's a form event and in here we can create our config variable for our axios so config it's going to have a header and set the header equals to content dash type of application slash json and then if we want to check if the password is not equal to the confirm password then we know there's an error so then we want to create an error so in order to create an error we actually have to create an error piece of state so here we can say error and set area once we can come in here we can say password set password and set that back to nothing the same for confirm password so confirm set that to nothing and here we want to run a set timeout to remove the arrow after five seconds so it doesn't just stay there the whole time so after five thousand milliseconds and here we want to set error to nothing okay so we haven't set the error yet but we want to return with that error so we can say return set error and here we want to say passwords do not match just like this okay great next thing we want to do is in a try catch so this function is actually going to be asynchronous because we're going to be doing axios request now so in here we're going to say const we're going to destructure the data from the axios request and we're going to set a weight axios dot post remember it's a post request to register to slash api off slash register and in here we have to pass in a few things we need to pass in an object containing the username the email and the password and it's important that these are named the same that you already structuring in your api and then we just want to pass the config object once we sent this we will receive something back and that something is going to be our token so we want to set item in the local storage so localstorage.set item we want to set auth token that because that is what we're going to be looking for in our routes and we're going to set it equal to data dot token because remember in the api we send back a token and once that is done we can go to history dot push and to just the home route we should actually bring in push in the in the props of this function so up here we can say history just like that then we redirect and everything went well if there was an error we're gonna do the same thing we're gonna say error is equal to error dot response because on axios it first gives us error then a response then the data and then the error we created we created the error field on any area so it will be logged here then we want to say set timeout and run a function again after five seconds that is able to reset the error and set it back to nothing if we save this our register um should be done everything is done why is it logging here we never actually use that okay it's because we want to display it so just below the the heading over here we're gonna do a ternary opera or a check we check if there is an error in the state then we want to create a span and log that error so this just means it's kind of like a shortcut to internally and operator always takes the last two values so it checks that both is true and then it returns the last one so we wanted to return this one and we're going to give this a class name of error dot message or error dash message we save this now now everything in our register should be fine i'm actually going to copy this entire register component copy this and go into my login screen and paste it in here because this should be very similar we're just going to have less fields so in here we bring in use state again we have axios we have react router dom but in here we we need to bring in the login screens css okay and we're gonna change this to login screen and save okay so let's just quickly change up a few things here first off we're gonna have a use effect okay so we're not going to have this confirmed password and we're not going to have a username what we're well going to have is a use effect and we're gonna check here and the reason we just do this is because um we want to actually check that the user can't um get to this route if he he or she is already logged in we should actually do this in the register as well so i'll just copy it in there as well use effect so what i mean by this is once the user is logged in we don't want them to come to the login or register page once they're already logged in so that wouldn't make sense okay so this use effect is going to look as follow we're going to say if localhost oh localhost if localstorage.getitem has a auth token in it then we just want to redirect so once again we bring in history over here so we can just say history dot push to that route and on that route we'll we also check that it is a valid token so this is just a nice way of handling this redirect so history we put in the dependency array and then we have instead of the register handler we're going to have the login handler and in here we once again prevent default we have the config we don't have to do this check over here we straight up going to go to the try catch we are not going to have a username passed in and we're going to go to slash login the rest of it stays the same yeah the rest of this is is the same we're going to copy this and add this to the form handler down here and everywhere where it says register screen we have to change that to login screen so i'm just going to select one and ctrl d and change this to login screen and in here i'm just going to change this to log in as well let's see the error error should be the same username we don't need this form group over here anymore oops and these should stay the same we still need the email still need a password we don't need this form group down here anymore okay and the button should say login not register and then these class names should be login subtext and this should actually say don't have an account do not do not have an account and then this should link to register and here we can just say register and save this should be the end of this route you can actually copy this piece here copy and go to the register screen and then paste that in here as well just bring in use effect as well use effect and save login is done register is done let's do the private route now the private screen private screen is going to be very simple um i'm going to paste the login here again oh this is actually not that okay let's just do it from scratch we can say import we're gonna bring in use state and use effect effect oops from react and let's say import axios because here we want to fetch the data for this private route so axios and import the styles we don't need styles for this so we can say const private screen is equals to props and we're going to destructure the history out of the props and then we're gonna do the following jsx so we can return this piece of jsx and we can say exports default export default private screen okay so let's create the jsx this is really simple first off we're going to check if there is an error then we want to do something else we want to do something else so let's actually create those pieces of state so the first piece of state is going to be const error and set error equal to use state const private data and set this equal to set private data use state i hope i'm not going too fast for you guys i just feel like this is not what you guys are here for and this is a pretty advanced one so yeah okay so in here the use effect we're going to do the following things we're going to check if there's nothing in the local storage dot get items get item if there's no auth token in there we want to immediately redirect because you're not allowed to view this we can say history dot push and go to the login route so you can't come here if you're not logged in and once you get to this page and you are logged in we want to fetch private data so this will make axios request that's why it's asynchronous it's going to make axios request to our backend so we can say config equals the header and set this to content type application slash json i don't think you actually need to do this but i think it's only when you use fetch but i you only need to pass in here the authorization token so let's pass that in here that authorization remember from postman when we did this now we can say bearer is equal and then local storage dot get item and then that auth token just like that okay so now we'll have this config in here headers not header and here we want to add a try catch when we do our access request so we can say const destructure the data once again and here we want to await axios dot get and we want to go to api slash private and we want to send the config in the header so we want to set the headers and send that along if this is done we set private data which we actually have we did set private data and we want to set that equal to the data dot data so remember on our object we return or json return return we had a data field which says you have access to this data so now we want to add that here then we want to say local storage if there was an error we want to remove item so if there was an error worth requesting over here then we know it's an invalid token so we can say auth and just remove that token we can set the error to you are not authorized please log in just like that and we can actually redirect them if you if we'd like but i just left it like this and then once we're done creating this function we actually want to call this function so you can't directly call the function from outside so you can't add this function outside of the use effect it has to be inside and then we can call it here and then in the dependency array we just want to add the history okay so that is the use effect when the page first gets loaded so once the page get loaded we want to check if there is an error then we want to respond with the span of class name error that's message and we want to add the error in there else if that's not the case we want to return with a fragment because between these fragments i'm going to add a div with style i'm just going to hard copy the styles in here gr background of green and a color over white and then in here i just want to add whatever we got from the private data in our state so if i save this it's going to reformat it nicely for us and then i want to add a log out button so in here we have a logout button that says log out and this is going to be on click so whenever we click on this we want to have a log out handler and this logout handler will create here so we can say cons logout handler is equal to the following okay we want to remove the local storage so remove item the auth token we want to remove and then we just want to redirect so history.push oops and then redirect to slash login okay so this should work save that all of this should be fine we did export it yeah this looks fine okay so we're done with this route okay the next route we want to do is we've got the register private login forgot password so let's quickly do the forgot password and then we're almost done almost almost done just stay with me guys um i'm actually going to yeah let me copy this route i'm going to copy this route and or this component i'm going to paste it in here i'm going to walk you through this so first off we have use state and axios then we bring in the css then we have our component we export the component down here so we have our three pieces of state so we first get the email then we check if there's an error and then we have a success so if we forgot password and we send the email and we get a success then we want this to show then we got the forgot password handler so let me go to the jsx so we have a container which is forgot password screen we have a form with our on submit handler with the forgot password handler and then in this screen we have a title forgot password we have an error if there is an error then the arrow gets loaded we have success if there's success in the state and then the success gets loaded then we have a div here which is a form group that basically just asks you for your email and then we have input with the email and two-way binding then we have a submit button which submits the email to submit this form and this sub this form handler is what we're going to look at now this form handler has event asynchronous as well because we're going to work with axios then we're going to prevent default on this um on this form we're going to create the the config should be headers i believe not really sure hey there's all header i think both works and config then we can try catch in here in the first part of the try we get the data from axios post and then we make a api auth to the forgot password route we send in the email in the body and we have the header config once that is once that is sent back we get the set success in the state and here we just set the success equal to whatever we return from our api which is email is sent email was sent and then we'll just show that success over there if there's an error we do the same we set the error in our error state we reset the email and after five seconds we clear that error so that is it for the pass forgot password screen so i'm going to save this i'm going to close this up going to go into the reset password screen and i'm also going to copy this one in as well because this video is getting a little bit long and this is kind of repetitive and if you read through this you kind of understand what it does once again we bring in link use state and axios and then the style sheet here we create i see we're not actually using this history so we can actually remove that so here we create our password because we're gonna need we're gonna receive two passwords from the user on this page the first one is the normal password and then the confirm password we have those pieces of state then we have the error and success okay let's go down and check the jsx it's rendering we have a dev container again once again a form with a reset password handler which will make our request to our back end then we have a h3 with reset password the error being logged if there's an error and the success being logged if there is a success and then we just added a link to the success message so that you're able to click and redirect to the login to to login after you reset your password you can actually do let the pa let the the application redirect directly to the login page once the reset is successful but i like to do it like this okay and then we have the form groups once again for the normal password and then the confirm password and a reset button okay so let's go check what this reset password handler does in here we prevent default for the form again we have our content headers um our headers reset then we check if these two passwords do not match we remove them we clear their state and then we set a password and return we don't want to do anything else further if they do not match so that's why we return then in the try catch we make our access request to api auth password reset and here is where we get the token so we destructure from our props the match prop and on this match we can say match dot params dot reset token so if you remember from our app.js here we said we're going to get a reset token in our params so that is what it's basically destructuring it's getting that and then it's adding it to our con adding it to our backend route password reset so this is how we connect those two again then we just pass in the new password and then the headers we console that log the data to see if anything happened here we can actually remove this we don't have to console.log anything and here we set the success equal to data.success we catch the error if there was any and this is the same as previously so we can save this now and our applications should be done so in order to test this out we have to run both the front end and the back in at the same time but let's first actually test out the front end to see if everything looks fine so we can say npm start in the front end folder let's cross our fingers and hope everything works no error seems to be logged let's check it out okay nothing here so let's go to slash login okay this is great so i think i actually do have an auth token in here let's see application i don't have an auth token so it's actually pretty strange it should redirect me over here let's see why it is not doing that okay so in our components routing private route it should redirect to slash login okay so in our screens private screen we check if there is no item in the local storage.get item or token then history.push back here okay so why isn't it doing this this part it's actually supposed to redirect me here so in our app.js let's check this out private route exact path in the component should be private screen okay so let's just see everything is loading nicely this is the login screen we can go to the register screen i see it doesn't have the forgot password over here so let's quickly add that in so inside of our login screen we're gonna do the following we're actually gonna add some tab indexes here as well so the login screen the first tab is the username or the email so you can say tab index and set this equals to one and then the tab index for the password is is two then the button tab index is three and save that and in here our password label we actually want to add a link so i want to add a link tag that can link us to the forgot password route forgot password just like this and here we can say forgot password with question mark and this link should actually have a class name as well you can give it a class name of login dot dash screen underscore underscore forgot password and then we give it a tab index here of four so if we save this and go back we're able to tab through in the specific order see it goes it skips the forgot password then it goes past it then here and then there so that's what that tab index does so now we can click here and view the forgot password and the next thing we need to do is figure out why is it not redirecting us this is pretty strange because this is exactly how i coded it so i'm obviously missing something small so in here somewhere you know what this should be a direct be like this because this means it returns this it shouldn't be curly braces i will add something in the video to show you to fix this before we get to this point but yeah i think this should work now so let's try it out let's go to just slash and we get redirected oh my goodness thank goodness okay so this works so now we can actually test it out because the back end is running as well we can see the back end is running over here so let's test it out by logging in we already have a created user so let's try it out lloydjvensburg gmail.com and the password was one two three four five seven let's log in and voila it works yeah thank goodness i was starting to worry a little bit there okay so this works if you press log out it should redirect us if i try and go back in keeps redirecting us okay so if i go to register create a new user um actually let's yeah let's test it out test test at example.com password12345 one two three four let's send passwords do not match one two three four five one two three four five register password is shorter than the maximum length allowed of six six five six and register and then we made it in so this is great okay so the login and register is working let's test the forgot password so i'm going to go to my gmail i'm going to delete all of these over here and let's try the forgot password i'm going to enter my loya jv rinsberg gmail.com and i'm gonna send email email send success so this is great let's go to our inbox and refresh till we see something this is awesome yeah we see this okay now we have localhost we can click here this should redirect us boom this is so cool i love this now we can reset the password we can say one two three four five six again one two three four five six it previously was one two three four five seven so let's reset password and let's see let's see what's going on here fail to load resources four or four okay so let's see the error network tab uh it's actually not gonna show us this let's see what the what it logged down here it doesn't log anything here which is pretty strange reset password let's see let's see okay so we do send the password and are we making a put request here that's the big question reset password we are making a put request here that is correct okay oh i was so excited there for a moment everything is going to work flawlessly and this token that most likely expire because we okay so it's it's something is breaking when we request so http local is password reset what did we call it here i i promise you i i named the route differently password reset and in my back end we can go to let's just close all of this up in my back end in the controller's auth or in the routes we have reset password i knew it i knew it okay so this should be reset password and then in our screen over here i'll reset password screen this should redirect to reset password let's save that let's try again okay this is going to work this is going to work now let's refresh this okay and let's say one two three four five six one two three four five six and send password reset success yes okay this is great let's try and log in let's try the login let jvrainsberg gmail.com gmail.com one two three four five six and login boom and it all works oh my goodness i'm so glad sorry about a little bit of bugs here and there i'm going to actually leave this in the video because this just shows you that not everything happens perfectly sometimes you have to do a little bit of debugging to find out what what went wrong and yeah i really really hope you guys enjoyed this video i know it's really a long video again but um i'm hoping you guys like the long content where you actually create something that's valuable and that's worth your time and if there's some point in the video that you did not follow please let me know in the description down below and if you did like this video please smash that like button subscribe put on your bell notification for whenever i post another video and then that is it for this video i'll see you guys in the next one cheers
Info
Channel: The Full Stack Junkie
Views: 48,886
Rating: 4.9823618 out of 5
Keywords: mern stack authentication, mern stack authentication and authorization, mern stack tutorial, nodejs authentication, reactjs authentication, jsonwebtoken nodejs, sendgrid, nodemailer, password reset nodejs, mern reset password, full stack authenitcation, the full stack junkie, mern project tutorial, reactjs, nodejs, javascript, web development, authenitcation api, advance nodejs concepts, nodejs error handling, how does authentication work in mern stack, forgot password nodejs
Id: YocRq-KesCM
Channel Id: undefined
Length: 168min 26sec (10106 seconds)
Published: Thu Jan 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.