JWT Authentication with Node Crash Course - 2021

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody welcome back to the channel and welcome to a brand new crash course in this crash course we are going to cover authentication with json web tokens in this crash course we are going to be building a simple api where we can use json web tokens to authenticate our users and authorize certain routes so if you ever get lost when creating this api you could go to my github page to just look at it as a reference even though we will be building it from scratch this github page can be found at heartblade7 which is my github username and then over here jwt crash course at the moment of recording it is private but it will be public once the video is published so you can take a look at that whenever it is that you need so before we kind of dive deep into the api let's talk a little bit about what authentication even is and then later on in the video we'll talk about what json web tokens is doing to essentially allow us to authenticate so let's look at a quick diagram that really describes what authentication is so essentially authentication is the process of validating whether the user are who they say they are for instance if you decide to sign up sign in to instagram you provide something like an email and a password authentication is the process saying that hey this is the correct user this right here is the correct user so if you provide an email of like a latheharb at hotmail.com and a password of password well authentication of the pr is the process of saying yes this is the correct user so this is authentication now once you are authenticated you probably are going to make a bunch of requests within the application now some of these requests even though you are authenticated you might not be authorized to do for instance again let's go back to our instagram example so let's say i am signed into instagram we went through the authentication process and i'm signed in and i go to a bunch of instagram pages let's say this instagram page is a public page well at this point i am authorized to basically make this request and get the data so i am authorized to this but let's say this is a private account over here and i'm not following this account well at this point even though i am authenticated i am not authorized to make this specific request and get this data back because well i'm not authorized because i shouldn't be seeing these pictures i'm not following that individual over here maybe i am maybe this is a a private account but i am following that individual in this case i am authorized to actually request the data for this particular account and over here this is kind of a similar situation maybe over here again private accounts and not following i'm not authorized to see this data i'm not authorized to make this request over here you can probably imagine this is maybe a public account and i'm able to see this so that right there is authentication and that right there is authorization in this crash course we will be covering both and we're going to be using that with json web tokens so let's actually go ahead and start coding out right away in the next section okay so let's go ahead and set up our project now before we actually go ahead and start coding we need to install a few things if you don't have them already the first thing that you absolutely need is to have node installed so if you don't have node installed just go to this url right over here and just install this version where it says recommended for most users this is a lot this is going to allow us to have node and npm which is needed because we are building a node express api so make sure you have node installed the installation process is very very easy now the next thing that we need to have installed is postman postman over here is a way that we can actually test out our api we're going to be making a bunch of post requests to our api and there's really no way we can test it out in the browser and that's why we are going to use postman to test out certain routes the absolute last thing that you need is some sort of text editor i am using vs code which is by far the most popular text editor out there but you can use a bunch of text editors whatever it is that you prefer so once you have all these installed and once you have your text editor open create a directory where you want your project to be housed so i have over here jwt that's where i wanted to basically my project to be housed and then i opened this vs code text editor at this particular project now in here we're going to do a little bit of setup to set up our node express application so the first thing that we want to do is we want to open up the terminal so let me quickly just zoom in here so we want to open up the terminal and we want to initialize a new node project and to do that we do npm init npm init dash y to create a package.json file so give that a quick second and we should have a package.json file in no time let's just wait a little bit longer and just there we go we have our package.json now the next thing that we want to do is we want to create just an index.js file this is basically where our express application is going to be up and running so we'll we'll do that a little bit later in a second now the next step that we want to do is we want to install a dependency known as nodemon nodemod is a dependency that allows us to auto reload our node application because if we ever make a change in a node application we actually have to restart the server to actually see it whereas nodemon detects these changes and automatically reloads our server so it's very important that we install this so we can install this globally by doing npm install node one and then with the dash g flag which allows us to install it globally now i already have this installed and you can check if you have it installed by doing nodemon version dash v and over here i get a version if you get an error that means you don't have this installed now over here in the package.json let's create a start script so we're going to say start and then this is going to be nodemon and then index.js so essentially we're saying that hey we want to run this index.js file and if any changes occurs in this index.js file then go ahead and auto reload our application all right so that is that now let's set up a simple express app so let's go ahead and let's do a little bit of installation so let's do npm install express and let's go ahead and do that now once that is installed we should be able to see it in our package.json as a dependency so let's do that it should be relatively quick and there we go we do see it and we also see our node modules okay so now we have our express app let's do a little bit of just manual express setup so over here we're gonna do const or sorry we're gonna yeah we're gonna do const express and we're gonna require in basically that express library that we just installed and then we're going to basically create an ex express instance so over here we can just do express app and then we can do something like app.listen and then over here this takes in a callback and a port number in the beginning so this port number is going to be 5 000. and over here the callback is just going to be for logging purposes we can basically say um now running on port 5000 so let's go ahead and let's save this so this is basically really all we need to create an express api so let's go ahead and let us do an npm run start which is going to run the nodemon index.js script right over here so let's go over here and let's run that and we should see a log very very quickly saying hey you are now running on port 5000 so let's just wait up a little bit and there we go this is exactly what we get now if we were to ever make a change like add an explanation mark we don't have to restart our server nodeman automatically restarts it and over here we have the explanation mark now just to do another quick test let's just do an api dot get at the slash route and then over here we have a wreck and res this is just basic express if you are taking this crash course hopefully you know a little bit of express uh because this this is mostly on authentication but this is how an uh a route looks like in express so let's just do a quick res dot send so we can basically send something to the browser hi i am working let's go ahead and let's save this and now let us go to localhost let's go to localhost 5000 at the slash route and we should see here hi i am working so there we go we have our express application set up now in the next section let's go ahead and let's start making some routes for authentication starting with the log or sorry starting with the sign up route okay so let's go about creating the sign up route now the sign up brow it has quite a bit of logic associated with it and this diagram kind of has a flowchart of all the logic that needs to be implemented inside of our sign up brow so the first thing that we have to do is we have to get the email and password that the user provides us with so with every single request especially with the sign up request they're going to provide us with the email and the password and we have to somehow get that in our server now once we get it we need to validate it we actually have to validate whether the email is actually an email and whether the password fits whatever criteria that we set for instance let's say our user provides an email that looks a little something like this so let's go ahead and they provide us an email like this well this is not a valid email and we don't want to store any user that provides us with an email like this inside of our database so what we have to do is we have to validate hey is this actually an email is there you know a bunch of text in the act and then another text in the dot com or whatever is this an actual valid email so that's one thing that we have to do also we have to validate the password so let's say they do provide us with a valid email something like lathe hotmail.com but then they provide us with a password like let's increase the text here they provide us with the password of t well this is a terrible password and we probably want to have some rules where we can essentially say hey the password has to be at least six characters or greater so that way we can actually validate the password as well so let's say we throw some sort of error and then the person says you know what i'll change this to um uh lebron james lebron james this is going to be our new password and this over here would pass this validation right over here now the next step is to do a little bit of more validation the next step is to check hey is this email already inside of our database did a person already use this email to sign up for an account because if there is a user with this email we don't want to go ahead and create this user again this can cause a lot of conflicts so what we can do is we can essentially get this user and check hey is this user already in our database and then if it is then what we can say is we can say hey our user already exists with this email or if it isn't then we can move on to the next step so this is just another validation uh step right over here so the next step is to go ahead and do something known as hashing the password and we're going to talk about this in great detail when we get to it so do not worry but essentially hashing the password is just changing the password in some way we never want to store the exact same password inside of our database because this is very very unsafe if a malicious user gets access to our database well now they have access to a bunch of credentials so we essentially want to protect this by changing this password in some way and this is known as hashing our password we're changing it in some way so over here we can change it to maybe something like this over here and then once we change that then we can go ahead and save that inside of our database so we can go ahead and save it to our database and then what we can do is we can send our user something known as a json web token now i'm not going to explain this in great detail right now i will once we get to it so do not worry but essentially a json web token is a way that we can identify our users so once the user signs up or logs in we send them that json web token and then for each each request afterwards they're going to send us the json web token that we provided them with and then essentially we use that json web token to figure out the identity of the user and see if they have access to a particular request or not so this is the flow that we are going to take and let's actually start with it in the next section okay so let's go about creating user validation inside of our sign up route now to do that first we have to go ahead and create this sign up route now we can go ahead and do this inside of the index.js we can do something like app dot post and then over here we can do something like sign up but if we do it this way we're going to have a bunch of different routes inside of our index.js and things could just get a little bit messy so why not instead just group all of the all of the routes that are associated with authentication into its own file and then i can just basically export that file into this index.js so that this index.js can use those routes and we can actually do that in in express application which is terrific so to do this let's go ahead and let's just create a folder where we're housing all of our routes now inside of this routes folder let's create an auth.js file in here we're going to have all of our routes that are associated with authentication now in the next step is after we create these routes we want to basically import them into the index.js so that index.js can use them now to do this we can use the router method that express houses so we can go ahead and do something like const router and we can require in express so we can require in express and then use the dot router method now essentially now what we can do is we can do a modules dot export and we can export this particular router so let's go ahead and let's save this and now that we have exported this router we can go into our app.js and we can basically import that in so we can do something like you know const auth is equal to require and we require that particular route so routes slash off now to use it in this particular application we would just say app.use and then we would specify a path that all of the uh authenticated routes all of the routes in this particular file file will follow and that's we're going to say that this is the slash off path and then over here we specify well what we want to use we want to use this right over here the auth that we just imported so let's go ahead and let's save this unless over here let's create a route to do this we would use router let's just do a quick slash get this is just going to go to the root directory now over here we're going to do a quick wreck res and we're going to send res dot send we're going to send off route working so this author out is working now if we go to over here we go to our browser and now what we want to do is we want to basically test if this is working now remember this is slash off it's just slashed on its own but because over here we've specified slash off this all the routes are going to start off with slash off and then we can append whatever other routes that we want in or whatever path that we want want in so we have to do slash auth to basically see this route so over here we see auth route working now if i were to change this to something like slash test or slash sign up then you would have to do slash test to see this particular route over here if i go back to slash auth it says hey we can't get that so right now everything is working fine let's actually go about creating the actual sign up route so over here instead of slash test let's do slash sign up and instead of a get request let's do a post request because this is a post request so now let's go ahead and save this and now if we go back to our browser well none of this is going to work if you do slash auth even slash sign up this isn't going to work and the reason for this is because we can only do get requests inside of our browser to test a post request we actually have to go to postman and to do this what we can do is we can create a new collection where we can basically test all of our routes i'm going to call this jwt and then we're going to create a new request now this request is going to be is going to contain this url over here localhost 5000 slash auth slash sign up now over here is specifying what the request name is so we can basically say sign up so we can save this and now we can basically click on it we can actually append e sign up route and we can change this to a post request so now we can send this and you can see that the auth route is working all right so what is the first step that we have to take well the first step that we have to take is we have to get the user the user's email and password that is the absolute first step now that is the responsibility of the client if the client is making some sort of request to a particular endpoint the signup route in particular it is going to have to append some data within it containing the password and the username that the user provided now this typically is going to be stored in the rec dot body so right over here the rec dot body the request body so over here what we can do is basically access the password and the email from the rec dot body and let's actually go ahead and let's console.log this password unless console.log this email so we're going to console.log this password and this email let's go over here to our actual node app and so if i were to make a request to this you can see we get a little bit of an error so i wonder why that is so saying okay well you cannot okay so you cannot get password from rectal body because it is undefined now the reason why the rectal body is undefined is because inside of our index.js we have to basically allow for express to use json inside of the erectile body and this is very very easy to do all we really have to say is app.use and then you just say express dot json and this is basically a method right over here so if we save this and now if we go back and we send off this request everything seems to be working fine however at this point it is undefined undefined and the reason for this is because the client didn't specify any of the username or passwords in the wreck in the basically request body so over here to do this in postman what we can do is we can go over here to the body we can go to raw and we're going to specify some json data now this json data is going to be well an email and so this email is going to be hardblath hotmail.com and then we are going to do a password of password so let's go ahead and let's send off this request everything seems to be working fine but over here you can see that we actually get back our email and our password so over here if we go over here we have completed this step right over here we are able to get the email and the password from the user now the next step is to validate that email and password for instance you know i could i could have very very easily provided you with something like this just haarp and very very easily provided you with something with like this or just like p or it can even provided you provide you with absolutely nothing if i send this off well i get this data back i get harp and then well nothing and we have to basically validate if this is a valid password or email now we can do this from scratch inside of our sign a brow we can do something like you know if the password.length so if the password.length is uh less than six then we can return some sort of error now um now essentially this is kind of where it gets tedious especially for the email we're gonna have to do some pretty complex validations for email to figure out hey is there an at right over here is there a dot right over here this kind of gets complicated and very cumbersome and we're in a sense reinventing the wheel there's many packages and libraries out there that do this exact same thing and one very common uh library that is out there that does this is something known as express validator this express validator is a library that allows us to validate certain things in our application so we're going to use expressvalidator to do this now to to basically use validator we first have to install it as an npm dependency so we can do npm install express validator let's do a quick installation and right now you should have express validator inside of your package.json along with express so let's go ahead and let's go to our auth directory and what we're going to do is we are going to import something from express validator so we're going to require in something from expressvalidator and this is going to be a check so basically the thing that we're going to get is something known as a check and this is basically going to be a method that allows us to check if certain things follow a certain rules that we've specified now to use expressvalidator we use it as a middleware that we append in between the route and the final call that we are trying to make now over here in this middleware we specify an array now this is exactly how expressvalidator is going to be used if you want to learn a little bit more about expressvalidator you can just basically go to express valley day tour and this is a mpm package just right npm uh right over here so this is a very very popular npm package actually this might not be here actually let's see here npm uh let's actually just go ahead and let's just copy i'm sure that's not the mpm package let's go over here let's just copy express validator and let's go over here so if you want to learn more about expressvalidator let's just press this this is exactly how we would use expressvalidator so you can either get body or check i'm using check for instance and then right here in between the route and the final call we're going to have a an array that basically contains all of the checks that we want to make so let's go ahead and let's do that so over here what we're going to do first is we're going to check if the email so we're going to check if the email is an email and essentially we can do these checks by appending a bunch of methods after the particular check so we're going to check if the email is an email so that is the first check that we're going to do and this has a bunch of validations to really check if the email that we provided is an email now let's also do another one now to do another check we basically specify a comma right over here saying that hey we're done with this and then we can basically say that we want to check this time the password and we want to check hey is the password is its length so over here is length and then is its length does it have a min value of six so that right there is how we can basically append this now over here we can add multiple validations by basically appending multiple methods we can basically do you know is lowercase for some reason or is uh whatever you know there's multiple different things that you can probably read right over here you know is a day is it whatever so this is how we essentially use express validator but i'm gonna have basically just these two requests or two validations right over here so that is the first step now the second step is we want to basically tell it okay where we can get where express validator can get access to this email and password because it can only get access to it from the rec.body well to do this we use another method known as validation results right over here and basically right below right here what we can do is basically we can say something like const errors is equal to validation results and then we pass in the wreck and what this is basically going to do is it's going to look inside of the erectile body and it's going to look for basically the email and the password and it's going to see if it follows these particular particular specifications or requirements that we have specified now if they don't what what it is going to do is it's going to return an array of errors so it's going to return an array of errors so we're basically storing it right here inside of this error variable now essentially what we can do now is we can do something like this if the errors so if the errors and we can basically check if this is an empty array or this actually contains a little bit of errors and we can do this with is empty with the is empty method so we can basically say you know if the errors is empty well this is good then we actually want to continue that the validation is is great like they provided us with a real email and a real password however essentially if if maybe this is not empty and we can basically specify the uh if it uh basically the the not condition by having this explanation mark right over here we can say if this is not empty then what we want to do is we want to return essentially a res dot status we want to basically throw an error so res dot status of 400 and then we can basically say dot json because then we want to send back some data and then the errors can basically be well errors dot array so errors dot array so remember this is an array essentially over here what we can do is we can basically get this array by using the errors dot array method so that is basically this now right here we have set up a little bit of validation we've actually pretty much set up our password and email validation so right now theoretically if we pass in a password and email or password or email that doesn't meet the criterias that we've met we should throw this error over here however if we do pass a valid password and email we should basically get this you know res dot send auth route working let's actually say you know validation pass because this is really what is happening validation passed or passed so let's go ahead and save this and let's give this a quick test so right over here this is completely not valid so we can go ahead and we can send this and you can see the errors that we get so let's go over here you can see here that we have essentially uh an error here you can say this is an invalid value email whatever now however the only issue that we're facing is is this is kind of not as descriptive as we want right here invalid value is not descriptive at all you know this is not a message that we particularly want to send back to our users instead what we can do over here after as the second parameter to the check we can basically specify a a a message so over here we can say please uh provide a valid email so please provide a valid email then over here please provide a password that is greater than five characters so greater than five characters so now if we go ahead and we send off this exact same request you can see that this is the message that we get which is a lot more descriptive so over here please provide a valid email please provide a password that is greater than five characters and i misspelled please so let's go ahead and let's do that so there we go now we have our validations now let's say i do provide a valid email but an invalid password so we can go ahead and now we only get one error but however we still didn't go to this step right over here because we still got an error now if i provided maybe a password of this size still have that error if we provide a password of this size well now we get the validation passed now i also misspelled past because it should be tasked like this all right there we go so this works perfectly fine but now the next step of validation is making sure that this email hasn't already been used inside of our application an account with this particular email hasn't already been used and we actually to do this we actually have to check our database now in this crash course i don't want to go ahead and set up a database because this is a crash course on authentication and if i set up a database like a sql database or a mongodb database it kind of becomes really a crash course about how we can start setting up these databases and storing this data so i don't want to go about doing that instead i want to simulate what a database is ultimately trying to do and i'm going to do that by just creating a db.js file and over here i'm just going to do simply const users and over here i'm going to have an array of objects so this is basically going to be our database and our users are going to contain information like well email so let's do lathe at hotmail.com latehar.hotmail.com and let's say my password is one two three four five six seven eight nine so this is how we're going to basically store our data and this is not unlike how actual databases store our data so you're not really missing out by not using a database so let's actually go ahead and let's just export this out so we're going to export users out and now what we're going to do is we are going to go ahead and just import this over here we can basically treat this like an orm of sort so let's go ahead and let's just require it in sometimes they say import i really mean require i'm just used to either working in a react application or working with typescript that allows for imports with babel um but when i say import require it means the same thing so let's go ahead and let's uh this is from our database so we're gonna move into that directory and so now what we can basically do is now we actually have to validate if that user already exists in our database right now we only have one user inside of our database latharb hotmail.com so let's just write a quick note you know validated the uh input now we need to validate if user it already exists validate if user doesn't already or validate if user yeah it doesn't already exists my doesn't is terrible today uh if user doesn't already exist so to do this this is very very simple this is a very easy process we essentially what we do is we basically say hey let the user equal to the users you know from our database we can basically say dot use the dot find method and this is basically going to iterate through every single user inside of our database and what we're going to do is we're going to have some sort of a check here so over here we can basically pass in user we can say you know if the user dot email is equal to the email provided return that particular user and store it as this variable right over here so store it as this variable over here now if there is no match this variable is going to be undefined if there is a match it is going to be that particular user object so essentially what we can say is you know we want this to be undefined so we can basically say if user is undefined so if the user does not exist well uh actually no we we want to check if the user exists so if the user exists now what we can basically do is we can throw an error and we want this error to look exactly the same as the error that we get when we basically uh that the error that we get when um we send back basically uh there that we get from expressvalidator we want this format to be the same we don't want to be inconsistent so what we can do is we can basically copy and paste this and then now what we can do is we can do a res dot status of 400. you can use more specific ones like unauthorized routes but i can't remember them off the top of my head uh but i'm so i'm just going to use 400 throughout if it's not a server error i'll use 500. okay so now we can basically do this and we can basically pass in an error that looks like this and we don't really need the value we don't need any of these really we just need to provide a valid message something like this user already exists this user already exists so there we go now what we can do basically is let's actually go ahead and let's do this let's make this a valid user and this validation passed because harblath at homemail.com doesn't already exist but if i were to use lathe hard hotmail.com which is a user that does exist inside of our database and i were to make this request i get this error message right over here saying that this user already exists now if i were to again change the email then we get the validation passed so over here we have completely accomplished these two steps these two validation steps the next step is after we validated our user we want to go ahead and hash our password so let's actually talk about that in the next section all right so now that we have completed these three steps we are now moving on to this step right over here hashing the password so why in the world do we want to go about hashing the password all right so now that we have completed the user validation we are now in this step over here where we hash the password so let's talk a little bit about what hashing the password even means and why we even want to do it so i have a few diagrams to kind of explain this now let's say we get a bunch of emails and passwords there's different ways that we can actually store them in our database one way is we can literally store them as plain text so right over here we have our database and over here we have the email and then we have the corresponding password and over here essentially we're storing the password exactly how the user gave it to us so over here we have password and then over here we have one password two password four password five corresponding to each respective email now this is probably not a good idea and you probably know why if some sort of malicious user some sort of hacker or malicious user within the company itself has access to this database well now they have access to a bunch of different credentials and so now they can go into our software application and log in to whatever account that they want to or basically what they can do is we can maybe get this password and start logging into other software applications because people use the same password more often than not so this is not a great idea for security reasons again we don't want to store this in plain text so another way we can go about is encrypting our password so over here a user can provide us with a password we can have some sort of key over here and using this key we can encrypt this password into kind of this like jumble that doesn't really mean much to us and then when we need to when we need to basically uh get access to this particular password what we can do is we can use this key again and we can in or decrypt it back to the original password so over here essentially we have this kind of encryption we can use this key and then we can get this password back right over here now this again is a better approach but it is not ideal and the reason for this is if a malicious user if a malicious user gets access to our database and our encryption key then well it is pretty much the same as storing our passwords in plain text they basically have access to every single password in here because they can just decrypt it with this key right over here now this does add another layer of security because now the user needs to get access to the database and the key but it is still not ideal and again the reason for this is because if the user gets access to both well the passwords are well compromised they're all there and this could lead to a lot of issues so what's the other solution well another solution is we can go ahead and hash our password and that is the solution that we are going to take and hashing is basically a one step thing right over here it's a one way process we have a password and then we hash it to some mumbo jumbo there's an algorithm that does this however you can't you can't basically decrypt this back into the original password this is a one way process and there's a lot of hash functions that do this now essentially how hash functions work is you give it a password and then it hashes it to well a particular particular set of strings corresponding to that password now however the only issue is well if i if i provide it with a password that is exactly the same that hashed version of the password is going to be exactly the same as well so over here is going to be completely identical so this is kind of problematic as well and the reason for this is because what hackers or malicious users can do is they can basically get a bunch of passwords that are very very common maybe like password or i love you or very very very common passwords and get their corresponding hashes and essentially they can just do a brute force approach where they can say okay does this hash correspond to this particular password does this hash correspond to this password does this hash correspond to this password and you know with the technology that we have right now this can be a very very fast process and if you have a weak very common password well your password could be compromised so essentially what we can do instead to kind of circumvent this is for each password we can append an arbitrary random number amount of strings so for instance let's say a user provides us with a very very weak password right over here let's say this password is um let's say this password that's a weak common password let's just say i love you i heard i heard this was a very common password and the reason why i'm saying this is because i love you my audience right over here so this is a very common password very very weak uh you know this is probably the top of the list of any sort of dictionary hash or basically some sort of the hash password and then the password itself dictionary so this is a very very common password so what we can do to kind of circumvent this is append or prepend a random group of strings so it can be something like you know this and so essentially now we have basically this right over here and this is well not a very common password so then what we can do is we can go about hashing this and then this is going to make it very very difficult for any sort of brute force thing to occur some sort of brute force attack to happen because now well i love you is a very very common password but i'm sure i love u7 hash star h w is not a common password and this is why we want to append this string or prepend this string to this password and these are known in the hashing world as salts so that is exactly what we're doing so let's go about and implement this mechanism right over here because this mechanism is the most secure now if you you want optimal security you can actually implement a combination of mechanisms you can go ahead and you can hash you can hash this over here so you can get basically the hashed version so you can add a salt you can go ahead and hash it and then maybe you can use a little bit of encryption so now the user what they have to do is you have to first get access to the database and then they have to get the encryption key and then after they get the encryption key they have to go through this whole brute force to figure out exactly what this password is supposed to be so that's a combination that you can do we are not going to do that we're just going to mainly work on this over here hashing our password so let's go about doing that right now so let's go to over here so now we've done our validations so now we want to hash our password now to do this we want to use a library that allows us to hash our password because there's a bunch of hashing functions that we can use there's very common ones like bcrypt uh there's argon and there's a very few ones but but the most popular one in my mind is something known as bcrypt so let's go be crypt right over here i always misspell b crypt right here so this is a very very common library for hashing our password you can see here very very popular so let's go about using this one right now so let's do npm install and we want to install bcrypt i always miss small b crypts let me see there we go npm install b-curve so this is going to be our hashing function so once that is installed and this might take a little bit of time we can basically get it so we can basically say bcrypt so we can basically require that in so we can say constant bcrypt from bcrypt and now what we can do is we want to go ahead and hash our password so we can say something like well let our hashed password not hard password hashed password so we're going to say let our hash password equal to b crypt dot hash so bcrypt.hash and the first parameter that we're going to provide is the password the plain text password that we are trying to hash this is the password that the user provided and then the second parameter is a number symbolizing the amount of salt that we want to basically add to this hash remember the more salt we add the more salt let's go back to our diagram the more salt we add over here the more uh the more safe our the more secure our password is you know the less likely a hacker can actually breach this password over here and actually you know decode it into the correct password uh because you know this is this is um uh you know the more the more things we add the more things we append the less likely the password is going to be breached however the more we append the longer our algorithm is going to take to eventually decode once we provide it with the right password so there's kind of a fine line that we want to do we could add like a thousand but then our password is going to take forever to be created and be forever to be uh kind of decrypted back to what it is supposed to be uh so kind of a common convention is just to say the number 10. so this this basically allows for a good amount of security without compromising how long it is going to take to hash the password and just bring it back to its original form now this over here is an asynchronous uh asynchronous call over here and the reason for this is because this does take quite a bit of time hashing over password takes a little bit of time so what we can do is we can basically call this over here our function async and then what we can do here is we can basically await it so let's go about and console.log our hashed password at this point so let's hash our password console.log our password and let's go to postman and let's just make a request so it passed and then if we go to our terminal you can see our hashed password and this is the password that we want to save inside of our database so now what we can do essentially is basically save this into our database so to do this all we really have to do is do something like user dot or users.push and then we can basically push an object where the email is the email that is provided we won't hash this or anything even though that might not be a bad idea so we have the email now because the key and the value are exactly the same we can just provide email and javascript essentially interprets it as email is the key and email is the value and over here we can say that the password is the hashed password so now we are saving this to our database so let's actually go about and let's make this request so let's make this request so we made this request once now let's try to make this request again it actually fails it says hey this user is already created because we created this user and it has been appended inside of our database let's actually create a route where we can get all of our users so let's go over here let's do a app dot or sorry a router rather a router dot get we're gonna say all so this is gonna be all users let's do rec res i should always forget the order is it rec first or is it yes it is right and then all we're going to do is we're just going to do a res.json and we're going to send back all of the users so over here let's actually create a new route uh let's see here let's just right click on this and say that we want to add a request we're saying get all users that's what we're going to call it and essentially now what we can do is we can just copy this and we can basically paste that in here we could save this if we want to as well um you can save this so let's paste that in there and this is going to be slash off slash all we can make this request right now we have nothing because we'll be restarted our server so let's actually go ahead and let's make this request again so now we are signed in so if we make this request you can see that this is how our data is going to look like now we have this email and we have this hashed password right over here which is terrific this is awesome so now this is i mean if you know this is going to be very very hard for anybody to kind of breach this password so now again if i sign up again because this user is already in our database we have a bunch of kind of validations that prevent this from happening so that's great so if you actually go to our diagram what we did was where is our diagram there we go so if we go to our diagram we actually hashed our password and we talked about hashing and we also saved it to our database now the next step is to send a json web token and we're going to talk a little bit about what json web tokens are and how we can send them to our user all right so now that we have accomplished this step we went about hashing our password and we saved it the absolute next step is we want our server to send something back to our client that it can kind of use over and over again when making requests to indicate that hey i am authenticated and this is where json web tokens come into place so essentially what we can do is once the user passes in valid credentials so once they either sign up or they log in with the correct password so over here they give us valid credentials and we go ahead and we process it in our server with our sign up route or our log in route and we're satisfied with everything we want to give our client some sort of thing that it can use over and over again to kind of tell it hey i am this particular user and this is going to be the json web token so essentially right after it passes the credentials we are going to generate a json web token so we're going to generate this json web token we'll talk about exactly what is inside of a json web token in a little bit we're going to generate this json web token and then we're going to give that back to the client and then it is going to be the client's responsibility to store this json web token somewhere now this can be stored in a numerous amount of places let's actually go open up the just open up our inspect right over here and you can see if you go to applications you can store it in local storage you can store it in session storage you can either store it as a cookie but the client is responsible for storing this json web token and again this json web token contains information about who this client is so now once the client is authenticated and logged in they have this json web token stored somewhere in their browser and for each appending request what they can do is they can send this json web token to the server the server can then interpret this json web token see that okay this is the user right over here and then they can determine if they can authorize a certain request or not but this is basically the premise of a json web token now if we go to over here jwt.com we can actually see how our json web tokens are going to look and there's three parts to a json web token there is the header right over here which we are very we're not going to work with at all actually and then we are going to work with these two sections right over here so then we have the payload and this right here is just kind of encrypted information about a particular user so right here this was decoded into hey the name john doe the ita of whatever this number is and whatever so our json web token can contain information about our user now this is very very easily decoded they can literally just copy and paste this json web token into this uh kind of text area right over here and see that information so we never want to store sensitive information for instance we never want to store a password in here that that's a terrible idea we might not even want to store an email we will in our case but it might not even be a good idea to do that uh we want to store not not so sensitive information in here we will store the email but the email might not be the greatest idea so and then the last thing over here is some sort of secret and this is basically kind of the uh the security of the json web token inside of our server we're going to have some sort of key and this key you can see it over here let's actually zoom in a little bit more let's see if that this key could be kind of any sort of randomly generated strings so you can over here we have this particular key and you can see how this secret right over here changes so you can go over here add some more and you can see that the secret changes now if somehow some way this is tampered with over here let's say like this we get rid of the y well now we have an invalid signature because this secret right over here is basically in charge of this right over here and this is kind of what allows for the security so let's go back over here and if we tamper maybe get rid of the i again we get something invalid and then we get if we if we continuously kind of manipulate and try to change our json web token we are going to get a bunch of invalid data and this is the only way that we can actually decrypt a json web token and see if it is truly uh the json web token that our server sent out because only our server should know this key right over here this guy all right so let's actually go about and let's code this application out all right so let do this right now so to do this what we have to do is we have to install a package known as well json web tokens because this is the package that is going to create our json web token so what we can do is we can do simply npm install mpm install and then json web token let's go ahead and install this this shouldn't be too too long there we go and then over here we can do something like const jwt and this is going to be required from json web token all right so now over here at the very bottom what we can do is we can essentially create this token so let's go ahead and let's do something like well const token and over here this should also be const because we're not really changing this uh and over here this should also be a return because we don't want to execute anything if we get any sort of error i kind of forgot about that my apologies so over here we can do const token and this is going to be asynchronous so we can do jwt dot sign and this is allowing us to create our token so the first thing that we can pass in is the payload remember the payload is kind of the text that we want our json web token to have essentially over here we can basically say that our payload is going to be the email that was provided for our sake again this might not be a good idea for security reasons because well emails are pretty sensitive but uh we're just gonna do it for the sake of this application so this is going to be the payload and then over here let's provide it with some sort of secret that is the next step of the secret we're going to have it be complete gibberish now it's probably not a good idea to store it as plain text over here you might want to have this in a dot and file and not you know commit it to github but again this is kind of a dummy app so we're not going to worry about this level of security so over here this is the secret and then the next thing that we can optionally add is an object where we can specify a bunch of different options one option is hey you know what i want this uh when do i want this json web token to expire you know we probably don't want this json web token to be there forever we might want it to expire at some point so we can basically specify the time in seconds i'm just going to specify a really large time because i don't really care i wanted to really live as long as possible for this crash course so over here we have generated our token and then the absolute next step is to send that token to our client so now what we can do is we can say jsonres.json and we want to send off that token so now let's go to postman so now let's go to postman let's go sign up let's sign up with a kind of a more regular email let's just do lathe at harp or lathad hotmail dot com we'll keep the password so now when we send it you can see we get back this json web token so if we go over here now let's go back to our our website right over here and we paste this in you can see that we get well we get our payload so you can see here that okay we have our payload we have this you can see that this is an invalid signature and this is essentially how we're going to validate our json web token if if for some reason somebody decides to send us a json web token and it is invalid and this is because this is the secret key that we're providing um we're going to basically not accept it we're going to say that hey you are not authenticated now in this case this is the secret key right over here and this is why it's not working so let's go ahead and just copy that and this is so this is the secret key that we are using so we can basically paste that in there and you can see that this is verified now if someone were to tamper with this or send off a like another json web token so let's say they got rid of the j you can see that all of a sudden now it becomes invalid so this is why we have the secret so now again this json web token is going to be stored somewhere in the browser and then for each upcoming request for each uh authenticated request where you need to be authenticated it is going to pass this json web token into either the header of the request or the body now commonly it is going to be found right over here inside of the header is typically as something like x auth token and then our uh json web token so our json so our json web token would be found somewhere right over here like this so for each upcoming request basically our uh our server can then use the json web token to ensure who this user is and if they are really authenticated but we're going to do this in a future section in the next section we're gonna actually have to work on the log in route because we are actually completely done the sign up route and now that we're done the sign up route and we have a good understanding of exactly what the process is the log in route is gonna be very very quick so i'll see you guys then all right so now let's work on the log in route and this is a lot simpler especially now that we know about hashing and jwts so these are the steps that we are going to take to create our log in route the user is going to log in with a username or password and essentially what we are going to do is we are going to get that user's email and essentially search our database for the user with that particular email now if that email is already inside of our database we essentially get that user object that contains the email and the hashed password if it is not found in our database then essentially what we end up with is undefined so at that point we can trigger an error saying hey you need to go ahead and create an account so once we do this and once this is passed let's say we do end up with that user object we get that hashed password and we compare it to the password that the user provided so over here we have our hash password and we do that comparison and we can do this very easily with bcrypt now if everything is good fine and dandy then we send them a json web token like we did with our sign up route so let's go about and do this in this section so to do this we have already created our sign up route let's go over here right below the sign up and under the all let's do a router dot post and this is going to be called log in and this similarly is going to be asynchronous rec res and then let's go about doing our steps so the first step is well we want to be able to get the password and the email from the rec.body so they're going to provide that to us in the request body now the next step is to check if that email or that user with that particular email even exists and if they do we want to store it locally into our uh and out into our software so we can do something like let user is equal to users dot find we've done this exactly in the signup route so we'll just do user.find and we want to return user.email is equal to the email provided and this will give us the user object so now the next step is to essentially say hey if the user is undefined if there actually is no user with that particular email then we want to go ahead and trigger an error now the error is going to look exactly the same as this so let's go ahead and copy this and let's paste it right in here except now we're checking hey if the user is not defined then we want to throw an error and we can say hey we can say something like invalid credentials now we don't want to say something like something more specific like hey there is no uh user with that uh email and the reason for that is because if we do this then we're sort of providing malicious users that are kind of doing a brute force attack hey does this email exist in our database because if we provide a message saying hey this email doesn't exist in the database or or if we provide a message oh invalid password they kind of have a way of knowing okay well this email is valid i just have to figure out the password but if i provide a generic message like invalid credentials then they don't know whether it's the email or the password that is incorrect so that's why we're gonna have this kind of kind of generic message right over here okay so there we go so that is the validation step and this is really the only validation that we need we could also add the the expressvalidator to to validate the email but i mean this is pretty good enough because well we're never gonna have an email inside of our database that is not really an email uh and this is because we already have in the signup route this check over here so maybe we could add it just to prevent unnecessary iterations in our database but i'm not going to do that because well i want to keep this as short as possible it's already running too long all right so that is that and now what we want to do is we want to essentially compare the hashed password of that email to the password that was provided so remember the hash password is inside of our database so let's actually quickly go to postman and let's make a sign up or let's actually yeah let's do a sign up request and then let's do a get all users so over here you can see here that this is how our data is going to look this is just an anomaly that we created but this is typically how our data is going to look this is how our user is going our user password is going to look so we have to essentially compare whether hey this password over here is equivalent to the password that is provided so we can do that with bcrypt so we can do that with bcrypt dot compare and the first thing that we can do is provide the password that the user provides and then the hashed password and so the hash password is going to be from the database and this is going to be user.password now we can actually store this and this is going to return either true or false so if the password is is not valid it's going to return false if it is valid then it is going to return true so we can say something like is match is equal to this now this is going to be asynchronous because it is going to take some bit of time so essentially we can go ahead and await this so now what we can do is if this returns false we can basically trigger this exact same error saying invalid credentials so let's go over here and it seems like we're not copying this let's copy this again and let's paste it in here we can say if this is false by doing is not is match you can say invalid credentials and then the very last thing is we can go ahead and generate that token and we can go ahead and send it back so let's just copy this over here and we're gonna generate it with the exact same secret right over here so let's go ahead and let's save this and at this point we are pretty much done our login route so let's go ahead and test it so let's go ahead and let's just go to our signup route let's just copy this because it's going to be exactly the same except for the appended login and let's add a request we're going to say login so and this is going to be slash login and over here this is going to be a post request and so what we're going to do now is let's just get all of our users so over here we have uh let's go over here and let's go all of our users at this point we only have this one user let's create a user right now so we're going to create a user let's create spiderman at batman.com and then the password is wonderwoman123 so this is the password so we're going to sign up with this with these credentials we get this json web token and right now inside of our database we have this right over here and it's all hashed so now what we can do over here is we can go ahead and log in now inside of the body we'll provide it with the data that we need to provide it with and that's going to be well our credentials so the email is going to be i believe is spiderman at batman.com and then the password is wonderwoman two three i believe wonder woman one two three so if i go ahead and provide this you can see that everything is all fine and dandy and i get another json web token now let's say i i i input the wrong password so let's say i get rid of i just say woman instead of wonder you can see here invalid credentials over here you can go back to wonder woman valid credentials will say provide an invalid email invalid credentials there we go so we have essentially set up our login route very very quickly so now that we have created our routes let's start talking about how we can actually kind of protect certain routes depending on whether you are authenticated or not so we want to prevent access to certain routes depending on your whether you're authenticated or not so we'll do that quickly in the next section okay so now that we are authenticated and we sent out our json web token to our client we're going to want to now protect certain routes depending on whether the user is authenticated or not so remember over here we're authenticated we know the identity of the user but now we want to protect certain routes depending on the identity of that particular user again this is known as authorization so this particular user once authenticated they may have access to this route this route and this route but maybe not to these routes over here now if they're not authenticated at all maybe they don't have access to this route and this route as well so over here we want to start protecting routes depending on the identity of that particular user so let's go about doing that right now now over here what we're going to do is a very simple example if you are authenticated you have access to a particular route and if you are not authenticated then you don't have access to it so essentially in our example we're really going to have two routes right over here one that you always have access to and one that you only have access to if you are authenticated but these same premise can really go on with more complicated logic you can really start figuring out the user identity and figuring out if they have access to this particular route or not using the very very same logic so let's actually go about doing this right now so inside of our database let's say we have a few more tables or collections or whatever database that you're trying to use let's just say here collections for the sake of us because we're really dealing with uh mongol kind of like json format data which is like no sql but that doesn't matter don't worry about that i'm not trying to confuse you so let's go ahead inside of our database and let's say we are creating a post application and you can only see a certain number of posts if you're authenticated but there's other posts that you can see if you're not authenticated so let's say public posts and we're going to say here this is going to be an array of objects and each post is going to have a title we're going to say here something like free tips on development so this is going to be the title and then the contents so the actual text of the post we're gonna say these are some tips and let's go ahead and let's just duplicate this uh oops i will always do this let's duplicate this three times over so these are uh kind of public posts that anyone can see you do not have to be authenticated to see the ones now over here let's say we have something like private posts so these are private posts and maybe this is only for authenticated users that paid for the service so it could be something like this so let's go ahead and let's copy this let's post it over here we can say something instead of uh free tips we can say paid tips on development and so these are the tips let's actually go ahead and copy this two times over so over here we only want to show this if we are authenticated and over here we want to show this well regardless if you are authenticated or not so let's actually create the routes for these now over here we can we could append it in the off.js but that really makes no sense let's create a new file known as post.js and it's going to follow the relatively the same format we're going to have over here we're gonna have um where is it we're gonna have the router so let's copy that and let's paste that in there and then we're going to do a module dot exports of that router and then inside of our uh package we're inside of our index.js we're gonna go ahead and copy this we're gonna call this slash post posts this is gonna be called post and of course we have to import this in so we can just quickly copy this we can say from slash post and we can call this post instead of auth so let's create the public route first so let's do a router and then dot get we can just say something like slash public and then we can do a rec res and we can just simply let's get the data from our database so we can do const require in so what do we want to require in we want to go to our database we want to get the public okay well the reason why we don't see it is i didn't i didn't export it over here so let's go ahead and export it so we want the public post and the private posts exported over here we can just say now public post so essentially now all we can do is something like res.json and we can go ahead and just send off this public post so now let's go to postman let's create a brand new request so we can say get public posts save this and then we can go over here and we can do something like slash posts slash public and now we can go ahead and send this and we get these posts right over here now keep in mind we do not have to be authenticated at all to make these requests because you can see here in our header we don't have a json web token we have nothing in our body we can just be any random user that makes a request to this and we get this and this is what we want now that's not what we want for the private posts so let's actually go about and let's copy this and this is going to be for the private posts so let's paste that in there and so this is going to be slash private and over here we want to get the private posts and let's say private so now let's go ahead and save this let's create another route so let's save this one and let's create another request rather and so get all private posts so let's save this let's go here let's paste that in there and now this is going to be private now the way that we constructed it is exactly the same way that we constructed the public one so anybody has access to this but we really don't want anybody to have access to this over here so how can we essentially kind of circumvent this well for each request the the the client is going to have the json web token inside of the header this is what we're expecting now if the json web token is not in the header then what we can do essentially is well not authorize this request and how do we do this well we can do this with middleware and middleware are essentially functions that are called in between one another so over here i can have basically another function right here another arrow function that is called before the final arrow function right over here this one this final error function actually sends off our request and similarly this takes in a wreck a res and something known as a next and essentially if everything is fine and dandy if everything is fine and we want to move on to the next either middleware or final function we basically call this next function if it's not then we can basically return some sort of error so inside of this middleware what we can actually do is we can do something like okay well let's say uh user valid so let's say we do some sort of check and and we figure out that the user is not valid so this is not a valid user either they don't have the json web token or it's called or it's been compromised in some way or it expired what we can essentially do is we can basically say well if the user is valid so if the user is valid then what we can do is we can basically call this next function else else what we can do uh oops what am i doing here else what we can do is we can basically return res.json some sort of error now the error is going to look exactly like what we have over here so let's copy this error so we can do something like this so let's copy this you could do something like this you know um you know please log in you know or or something like access denied so this is going to be access denied i completely forgot how to spell denied so i'm just going to say access d so let's do access denied so over here essentially right now let's say that we did some sort of check over here and then um and then we realized that this is false so basically we get this access denied so let's go over here and let's just go and make this request again and you can see here that we get access denied now let's say that this is true we do our little check we can go ahead and save this and now well we get our tips and that's exactly how we can authenticate certain routes now we're not going to particularly want to append this whole function after every single protected route that we are going to create instead what we can do is we can get rid of that and essentially inside of here we can basically create a folder for middleware so in our root directory we can create a middleware folder and in this middleware folder we can create any middleware that we want now the middleware that we are going to want to create is the check auth middleware so they check off middleware and over here we can simply do something like module dot exports and then this is going to be let's say this is going to be async eventually because we are going to be using json web tokens and so we can do rec res and then next and then over here essentially now what we can do is well we have exported this middleware right over here so we can save this and now for any protected route what we can do now is we can say const check off and we can basically require that in from the middleware uh directory so middleware slash check off and if anything needs to be protected we can just append check off right over here because this logic is going to be exactly the same it's better if we just store it right here so for some reason we also want to uh authenticate this then we can add check auth right over here but that's not where what we're going to want to do in this case so let's not worry about that okay cool so what really do we add in here now remember for each request the client is responsible for sending us json web tokens now in the request it is typically found in the header and so that is where we're going to have it but if the client doesn't send us json web tokens then we basically want to say hey you don't have access to this particular request or if it sends us an invalid one we also do the exact same thing so over here again we're expecting the client to have some sort of json web token inside of the header so we can say something like okay we want to get the token from the rack dot header and we this can be really called whatever is want so a header has a key and a value so the key can be whatever and then the value of course will be the uh the token but typically the key is called slash x slash auth slash token or something like bearer token i like x slash odd slash token better so you can say something like that's so we can say okay we want the token from this over here now the first thing we can do is we can say okay is the token or is the json web token even present so we can say if it is not present then we can go about throwing an error so what is this error that we are going to throw well again you want to make our areas as consistent as possible so we can basically paste this right over here we can say something like no token found so that is the first thing that we are going to do and then the next thing is we want to actually validate that particular token so now what we can basically say is um jwt and of course we're gonna get this from the jwt library so we're gonna go over here and use the jwt to verify the token that we got back so we can do something like jwt and we're going to require that from the json web token library and again we're going to use jwt to verify this token so now we can do something like j j wt dot verify and here we provide it with the token and then we provide it with the secret that only our server is going to know now our secret is this thing right over here again highly suggest that in a real application you store it somewhere a little more a little more safer but this is where we're going to store it just plain text right in there and then that is pretty much it it just needs a token and it needs a secret and basically what happens is is if this is valid everything is fine and dandy it can essentially move on to the next step it gives us actually the payload of this uh json web token remember the payload is this right over here and remember we stored the email inside of our payload so this is what it's going to give us is going to give us the payload and we actually can go about storing that payload inside of a variable so it can be let user equal to json. jwt.verify the token and then the secret now this is going to be asynchronous so we can await this now if if this fails what actually ends up happening is it actually triggers some sort of error so what we can do now is we can basically put this in a try catch block so if everything is fine we get our user however if everything is not fine it throws an error so now essentially we would be in this catch block right over here and we can say something like we can say something like um token token invalid so token invalid now if everything is fine what we can do is in the request itself what we can do is we can append a value known as user and we can essentially say that this is going to be the user.email so now for every single authenticated request you actually have access to that particular user's email which could be helpful for getting their information and then of course we need to call the next function so there we go this is fine and dandy so let's actually go about doing this right now so now if i were to make a request to this you can see that no token is found let's go ahead and let's actually append just a random gibberish token you can see that hey this is an invalid token so now what we can do is let's say we go ahead and we log in over here so let's login we created this token so this token is now stored in the user's browser and then we provided this token right over here you can see here now we are completely authenticated and we have access to the data so that right there is the uh authentication with json web tokens with express crash course i hope you guys learned a lot and i'll see you guys in the next one
Info
Channel: Laith Harb
Views: 5,465
Rating: 5 out of 5
Keywords:
Id: 6ZCU4QetVTs
Channel Id: undefined
Length: 89min 11sec (5351 seconds)
Published: Sun Mar 14 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.