JWT Authentication Tutorial - Node.js

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
it is finally here this video we're going to be talking about JWT authentication using nodejs and express and we're going to be wrecking this into two separate parts in the first part we're just going to do a simple JWT authentication where we create tokens send tokens to users and authenticate those tokens on our server and in the second part we're going to talk about how we can use a refresh token in order to automatically refresh our JWT tokens to increase the security of our server and also revoke privileges from users that we no longer want to access our server similar to how a logout function works so make sure you stick around to the end of the video so you get both parts of this video so with that out of the way let's get started welcome back to web dev simplified my name is Kyle and my goal is to simplify the web for you so you can start building your dream project sooner so if that sounds interesting make sure you subscribe to the channel for more videos just like this one and for this video as always I have Visual Studio code opened up completely blank folder so we can start this project and the very first thing we need to do is initialize this project with NPM so if we just type NPM in it - why it's going to initialize our project with all the default settings and now we can install the libraries that we're going to be using the libraries we're going to be using as I mentioned in the intro we're gonna be using Express so if you type NPM I Express we're also going to be using a library called JSON web token all one word and then lastly we're going to install env and this is just going to allow us to use a dot env file which is going to contain our secret tokens for a JWT so we can just create that now env and this is where we're gonna put those secret tokens lastly we're gonna install a development dependency and the PM I - - save dev and this is called node Mon and what node Mon lets us do is automatically refresh our server every time we makes changes to it so we don't have to manually close and restart our server ourselves and as soon as that finishes downloading we're gonna create a script which is going to allow us to start our server using node montt really easily and we're going to do that on a file called server JSON this is going to be our main server file now inside or package.json you can see all of our dependencies are showing up in here and we can just come down here and type in dev start and we want this command to be node one and it's going to run our server dot JSON file so this is going to run our server dot JSON using node one and we can start that by just running NPM run dev start and it's going to run that file for us and of course we're getting an error because I forgot to save my package JSON now let's run that again and as you can see it started up our server and since we have nothing in it it just exited out which is fine now as we make changes for example if we put a console that log put hi in here save it you can see that it's actually refresh in our server every time so to get started with our server we want to first import Express we just do that by requiring the Express library and in order to set up an Express server we need to get the app variable which is going to come from Express so we can just call the Express function and then say app dot listening until what we want to listen for example on port 3000 now we have an application running on port 3000 but of course it doesn't do anything yet in order to get our application up and running let's actually just create a simple route and apt-get route and this is going to get all of the post inside of our application and this is of course going to have a request and a response variable oops response and inside of here we can just run a function and inside of this function all we want to redo is return a list of post so let's just create a variable which is going to have all of our posts inside of it just like this and this is going to be an array with objects we're gonna have a username for the person that created the post so for example me and we're gonna have a title for that we can just say post one and let's just put two posts in here for now so if I just copy this down and we're gonna change this username here to be Jim there we go and of course the title should be post two and instead of our app target we can just return that so we can say res JSON and we want to return our post now if we save that create a new file called request dot rest whoops dot rest not resets let me change that real quick there we go and this is going to allow us to make rest requests API requests to our API you can use something else like postman but because I have the extension installed in Visual Studio code called the rest client down here it allows me to just use a dot rest file to make these calls and this dot rest file is really simple we could just say we want to make a get request to HTTP localhost port 3000 and we just want slash post so now if we send that request you can see we get the list of our post bacc for us so we know that our application is working and running properly now the next thing for us to do is to actually authenticate our request using JWT so that we don't let everyone access the post and only specific users so we can just create a route to do that we can say apt-get and this is going to be our login route and of course it's going to take a request and a response and the very first thing you do in this login route is you want to authenticate the user and in our case I've already done a video on user authentication using passwords and usernames so if you want to check that out it's going to be in the cards in the description below so we're just going to ignore this portion of the authentication so we can focus purely on how JWT works in the authentication process so the next thing we need to do is actually create that JSON web token and to do that we want to require that library we used earlier so we can say Const and we want just JWT which is equal to require of JSON web token also since we're going to be passing JSON to this app dot get we need to make sure our server can handle that so we can say app dot use and we want to pass in Express JSON this just lets our application actually use JSON from the body that gets passed up to it inside of request and we're going to change this to be a post actually instead of a get since we actually want to create a token so post makes more sense than get now inside of here we want to get the username so we can say comments - username is equal to request dot body dot username and now normally you would make sure you authenticate the user first but as I mentioned that's going to be in a separate video which I've already done and you can check out now that we know this user has access to our application and has passed the correct username and password we want to authenticate and serialize this user with Ehsan web tokens now if you are not already familiar with JSON web tokens and how they work I have an entire video talking about why you should use JSON web tokens and how they work so you can check that out again linked in the cards and the description below for this purpose of the video we're just gonna worry about the implementation of JSON web tokens and it's really actually quite easy to create a JSON web token we just use that JWT library and we pass it sign and the sign is first going to take our payload which is essentially what we want to serialize and we want to serialize a user object so let's just create a user and this user is going to be equal to here just an object which has name and we want to pass that as our username and now we can say that we want to serialize our user and in order to serialize them we need some kind of secret key this is going to be the next parameter and we're going to get this from our environment variables so process a and V dot access whoops access token secret just like that and we can create this in our env we can say access token secret and we need to set this to some form of secret value and a really easy way to create a secret value is using the crypt library inside of nodejs so what we can do is just open up another terminal and if we just run node here we can just run any node.js code we want to I require the crypto library and all we want to do is we want to get some random bytes so we can say random bytes let's just say that we want to get 64 of them and then we want to convert this to a string which is going to be in hexadecimal now if we hit enter this is just going to give us a random list of characters if we run it again you see we get a completely different random list of characters we can just copy this up as our access token secret and since we're going to be doing refresh tokens later in this video let's set up our secret for our refresh token as well we'll just use this other value so that these have two different secrets that's really all that you need to make sure is that the secrets for both of these are completely different now we can save that and go back into our JWT sign and right now this is complete we could add an expiration date to our token but since we don't have any way to refresh our token yet we don't want to add any form of expiration date so we can just say that this is going to be our access token we want to do is just return them so we can say res JSON and we want to pass down our access token as our JSON so now when we make a request to login whatever username we pass up assuming it's authenticated correctly it's going to create an access token for us and then access token is going to have the user information saved inside of it that's what we're doing with our sign here so let's go over and actually test this if we just put in here three hash tags like that anything that comes after it is going to be a different request so we can just say post we want to post to this HTTP localhost 3000 and this time we want to do a login and we want our content type here to be JSON so we can just say application slash JSON and then in our body we need to pass up that username so let's type in username and let's just say we want to do Kyle for example now if we send that request you can see we're getting an error secret our private key must have a value and this is because we're never actually loading our env variables into our process env variable here and we can actually do that really easily just at the very top of our application we just want to put require and we want to put dot E and V dot config now if we save that and make our request this should work and there you go you can see we have an access token being returned to us that has no expiration date that has the user information saved in it so we can access any of our endpoints with this user information here so now in order to test that let's actually create some middleware which we're going to put on our post here which is going to authenticate our token so we can take a function here we're going to call it authenticate oops authenticate token and of course since it's a middleware it's going to take request response and next and then inside of this function all we need to do is we want to get the token that they send us we want to verify that this is the correct user and then we want to return that user up into the function here for get post so we can call that authenticate token function as our middleware so we know we have that in our post and now inside of this function we need to get the token and this token is going to come from the header and we're going to have a header called bearer so it's gonna say bearer and then it's going to have our token afterwards so this string over here our token is going to come after the keyword bear and that's going to be in our authorization header so in order to get this header we can just say cast off header is going to be equal to request and we want to get the headers and then from that headers we actually want to get the authorization header which is going to have the format of bearer followed by our token so then all we want to do is get our token portion so what we need to do is say that our token is going to be equal to off header whoops off header just like that and we want to get this split so we're going to split it here on up space because as you know there's a space between bear and token and we want to get the second parameter in that array so we just say oh 1 over here and this is going to be this token portion of our bearer token and in order to make sure that we actually have a header we first need to do auth header and and essentially what this is saying is if we have an auth header then return the auth header token portion which we split on the space otherwise just return undefined so our token is either going to be undefined or it's going to be the actual token so we can do a check to make sure to see if our token is null so if our token is no we just want to return to the user and error code saying that they don't have access so we can say send status and we want to send a 401 status code so that we know that they have not sent a token to us now if we get to the portion after this token check we know that we have a valid token so we need to verify that token we can do that with date JWT verify and we want to pass it the token as well as the secret that we actually hashed that token with so we can just say process env dot access token secret and this is going to take a callback which has an error and it's going to have the value we serialized which in our case is this user object so it's going to have our user as well as an error and the first thing we want to do of course is check if we have an error and if we do we want to return another status code to the user saying they don't have access so we're gonna send a status this is gonna be a 403 which essentially says that we see that you have a token but this token is no longer valid so you do not have access now if we get past this we know that we have a valid token so we can set our user on our request we can say request dot user is going to be equal to this user object so we know we have a user and we can just call next just like that so that we can actually move on from our middleware now if we save that make sure that this is next instead of next IX don't misspelled that up here we now have access to our user we can say request out user to get our user so let's actually filter the list of Post we can say dot filter and we want this of course to be a post and all we want to do is get the post where the username is equal to request user that name so this is only going to return the post that the user has access to so if we log in as Kyle we'll get post one if we log in as Jim we'll get post two and if we log in as anyone else we won't get any post at all so let's test that all we need to do is send a request to log in we're gonna get an access token let's just copy that and up here instead of our post we want to send along the authorization header and as you remember it goes bearer and then we paste our token after that now if we save that and request our post you see we're only getting the post for Kyle because we've logged in as Kyle let's login as Jim send that request copy over Jim's access token and paste this in here and we should get back just Jimmy's post so now we know that our authorization and authentication using JSON web tokens is working properly it's saving our user and everything is great in order to further emphasize the power of JSON web tokens and how you can use them across many different servers let's just go into our package JSON and create a dev start script to here now we want to start up server to JSON which we're just gonna copy this server JSON rename this to server to a s and all we're gonna do down here is change our listen to be on port 4,000 so now let's start that up we can just say NPM run dev the start to hit enter and now we have two different servers whoops make sure I save my package JSON rerun that and now we have two different servers run on port 3000 and one on port 4,000 and the key thing is they both share the same access token secret so what we can do is inside a request we can actually log in on our port 3000 as you can see here our login worked correctly copy over this token and we can use this on our other server at Port 4,000 and if we send a request it still works this is something that you can't do very well when you use session based authentication because your session is saved on that particular server but with JWT all the information is in the token so we can actually use it across multiple different servers so what we're gonna do next is implement refresh tokens which allow us to actually take our authentication server and move it outside of our other third server so we can have one server which handles all of our creation of tokens deletion of tokens and refreshen of tokens and another server which handles only our specific use case of getting post saving post all of our different API related tasks but not authentication so in order to do that let's rename server two here to auth server so we know that this server off server is only going to be for authentication and our normal server is going to be for everything that's not authentication so what we can do immediately is remove our login section from the server and there we go now our normal server all it has is the get for post and we can authenticate our token but it has nothing else inside of it we can just save that in our package JSON here we want to change our dev start to be dev start off so while you have a normal death star and then our auth one which is going to be starting our off server jeaious and of course let's just cancel out of this and make sure we run our dev start off and now it should set up our auth server and our other server is already running on a different port so we have our server running port 3000 and now our office server is running on port 4000 here and in our auth server we can actually remove all this post related code because we're no longer being to be allowing post on this server it's only going to be logged in log out and refresh tokens so before we start building and implementing our refresh tokens I need to talk a little bit about why we need a refresh token right now when we create a token it has no expiration date which means anyone with access to that token will have forever access to that users account and they can just constantly make requests as if they were that user as long as they have that access token it's very difficult to secure that because they just have infinite forever access it'd be like giving up your API key when you're accessing an API the user just now has access forever the idea of a refresh token is that you save the Refresh in a safe spot and then your normal access tokens here have a very short expiration date so that if someone gets access to your access token they only have access to your account for maybe a few minutes before the access is revoked and then the user must use the Refresh token to get a new token and now this does have the same problems where your token could get stolen and someone else could use that token to refresh your token but that's where the idea of invalidating a Refresh token is you can essentially create a logout route which deletes a refresh token so that the user now can no longer use that refresh token essentially it removes it from the list of valid refresh tokens so really the main reason to use a refresh token and so that you can invalidate users that steal access that shouldn't have access and the second reason is so that you can take all your authentication and authorization code and move it away from your normal server as you can see we have two different servers and one is specifically for authorization so you can scale these servers separately if you have a lot of authorization you can make your authorization server bigger without having to make your other servers bigger as well it's really great for when you want to deal with micro architectures or things like that so the first thing we need to do is let's just create a function which creates an access token for us and we also don't need this function for authenticating so let's just create over top of this a function which is going to generate access token and we're gonna pass it the user we're gonna generate this token for it now this code is gonna be very similar to this code right here let's copy this down we want to make sure we return this and the only extra thing we need to do is add in an expiration date so we can just say expires in and for our use case we can put anything for example 10 minutes usually you're gonna have some short minute range maybe 10 15 minutes we're gonna just set this to 15 seconds just so I can easily show you how the tokens expire and how you can refresh them but again you would want to make this much longer in a real application something like 10-15 minutes maybe 30 minutes whatever works well for your use case now that we have that done let's just change this code up here to call that function to generate our access token and now everything's working fine but our token is going to expire in 15 seconds so we need to create a refresh token let's just do that right here we can create a refresh token and this is just going to be equal to JWT sign and we want to sign a user we essentially want to put the same user inside of both tokens so we can easily create a new token from our refresh token which uses the same user we also want to go to the environment variables and we want to get our refresh token secret so that we can serialize this and we don't want to put an expiration date on our refresh token we're going to manually handle the expiration of these refresh tokens and we don't want JWT to do that for us now the last thing to do is to return this refresh token to our user just like that and now if we go over to our request and we make a post on localhost this is going to be 4,000 to login if we send that request you can see we now get an access token and a refresh token back and let's make sure we change this back to 3,000 for post and if we try to make a request this is most likely going to fail since I don't think I got it quick enough okay I did so it hasn't expired yet but if we keep sending your request you can see after 15 seconds we're now forbidden from accessing this route and we need to use our refresh token to create a new one so now let's go over to our off server and we need to create a new function this is gonna be a post and we want to post token so essentially this is going to be for creating a new token it's going to be a request and a response and inside of here we're gonna take in a refresh token so we can get a refresh token it's going to be equal to request body token and this request is going to look just like this let's actually just create a really sample request we're gonna post to HTTP / / localhost 4000 we want to post to token and we're going to of course make sure our content type is going to be set to JSON and inside of our JSON we're gonna pass a token and that token is going to be our refresh token right now we don't have one but if we were to make a request here for example here is a refresh token we can use and we could paste that in there and this would pass up that refresh token to our off server here and we need to use that refresh token and check to see if we already have a refresh token that exists for that so normally you would want to store your refresh tokens in some form of database or some form of Redis cache but for our use case we're just going to store them locally in a variable we're just going to call this refresh tokens we're gonna set this to an empty array I'm gonna initialize this with let just like that and now this is not a good idea to do in production because every time your server restarts this is going to be emptied out but it's a lot easier to show you and demonstrate with than creating an entire database just to store these tokens and the first thing we need to do is every time we create a token just like down here we just want to set our refresh tokens dot push and we want to push in the new refresh token we just created so now we have a record of that refresh token and all we can do inside of this token is check if that token actually exists so first we want to say if refresh token is equal to null we want to return our status down here so we can say res dot send whoops it's end status let me just close under this section over here this is going to be a 401 status now the next thing we can do whoops I spell things correctly is we can check if our current refresh tokens includes that refresh token that we got sent to us so what this is saying is do we have a valid refresh token that exists for this refresh essentially does this refresh token still valid have we removed it or is it still good and if it does not exist what we want to do is again return saying that they do not have access so we're going to send a status this time saying 403 now if they get all the way past all those checks we can actually verify this refresh token so we can just say refresh token we want to get that secret variable so process D and V dot refresh token secret and of course we're going to have an error as well as our user object being returned inside of this callback function and of course we want to check our error first and if we have an error we can just return that error so we can say return and we want to send down a status of 403 very similar to our normal authentication but now what we can do is actually create our access token we can say Const access token is going to be equal to generate access token and you would think we can just pass this user object this user object actually contains additional information such as the issue that date of our token so we actually need to get just the name so we can say we want to get the name and the username that we were passing down just this raw user object and not all that other additional info Meishan now we can return that information by just sending res days on of our access token just like that and now we're finally ready to test this so if we go over here and we log in Jim you can see we get both a refresh token and an access token if we copy our refresh token paste it into our token function and we copy our access token and paste it up here we can send some requests and you can see it's working and it's working but eventually we're going to get the forbidden status we no longer have access so let's create a brand new access token if we can copy that access token paste it up here and now we have access again for another 15 seconds and eventually we're going to lose access when you even notice that these are on different servers this is port 3,000 and these are on for 4,000 so our authentication where we log in and create refresh tokens and handle refresh in our tokens all happens on a different server than our actual API which is great now the next thing I want to talk about is how to actually do indicate refresh tokens because right now forever and ever and ever users just click the send request button create infinite access tokens for users no matter what and as long as they have that refresh token they can do that so in order to prevent this we need to have some form of delete function we're just going to call this a delete here and we want to do for example logout and what this is going to allow us to do is actually delete those refresh tokens and this is really easy normally you'd have to delete them from some database but since we just are storing them and a variable here called refresh tokens we can just say we want to set our refresh tokens equal to a filtered version of our refresh tokens where all we're doing is we're just checking let me just close out of this here where there's checking to make sure the token that is inside our Refresh tokens is not equal to our request body token that we pass up to it and then all we want to do is just send a status now we're just going to send 204 saying that we've successfully deleted this token let's save that and actually make a request for that so we can just say delete and we want to go to local whoops localhost 4000 we want this to be logout we want our content type to be JSON of course and inside of here we need to pass that token so let's actually do another generation here where we're going to login our user you can see we get an access token and we get a refresh token let's copy this refresh token over into this section and we also want to copy it into this section for deleting so we can actually refresh this token as you can see we're getting new access tokens and everything's working but if we click to delete you see we get 204 means they successfully executed and now we'll we try to actually create a new refresh token or access token you can see it no longer works and that's because we've removed it from this list so the user no longer has access to it when they try to create a new token and it exits out right here when it's checking to make sure that refresh token already exists and that's all there is to implementing JWT authentication in nodejs and Express if you enjoyed this video make sure to check out my other videos linked over here and subscribe to the channel for more videos just like this one thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 365,047
Rating: 4.9551787 out of 5
Keywords: webdevsimplified, jwt auth, jwt authentication, jwt authentication node js, json web token, jwt tutorial, json web token tutorial, jwt node js, json web token node js, json web token authentication, jwt token, jwt node js express, jwt auth node js, jwt authentication node js tutorial, json web token authentication node js, jwt auth tutorial, jwt auth express, jwt auth node js express, json web token auth, json web token auth tutorial, jwt, auth, node
Id: mbsmsi7l3r4
Channel Id: undefined
Length: 27min 36sec (1656 seconds)
Published: Sat Sep 21 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.