hello guys and welcome to this video where we're going to dive deep into authentication we're going to see how we can create sign up login and refresh token and points and we're going to see how we can generate access tokens and refresh tokens to use them in our authentication flow while of course using guards so I have here a normal nestjs application uh of course we're listening on Port 3000 and this is just the basic setup the first thing we're going to do is we're going to create a nor module so let's go ahead and say Nest generate resource o to create our o module rest API and now I'm going to go ahead and then create two folders the first one is going to be called schemas for our schemas and then let's create another one called dto and since we're using Mongoose of course we need to install those two packages njs and then the normal Mongoose package so let's go ahead and install them and now once this is done let's go and open up our schemas folder and then create user schema. TS and here we're going to have our user schema so I went ahead and created a basic uh schema of course with the schema decorator and then we have created three different properties name email and password they are all required and for the email I made sure to set the unique attribute to true to create a unique index on this since every user should have a unique email and now let's go to our controller and now we need to start creating our different endpoints so here we have three different endpoints to implement the signup endpoint where the user is going to uh create a new user by sending their name email and password of course we need to check that the email is not already in use and then for the login we need to enter the existing credentials to get the access token and refresh token so that this user can actually use the access token in different requests and use the refresh token to call this refresh token endp point whenever the access token expires so let's get started with the sign up first so since it's going to be a post request let's go ahead and and use the post decorator and then we're going to set a route of sign up so to reach this API andp point we could say o/ signup because o is used as the prefix in this controller and now for the route Handler method let's say async sign up async because of course it's asynchronous and then here we need to take a body which is going to contain the data for this new user and then here we could call it for example signup data and then we need to create a dto for that signup data first of all let's go ahead and import body from njs common let's give it the type of signup dto that we're going to create now so inside of our dto folder let's go ahead and create a new file let's call it signup D.S and then if we take a look at our user schema again we can see that that we have three different fields name email and password and those are the fields that should be entered in the signup by the user so let's go ahead and say export sign up dto and let's take those three different fields and add them here and of course this is a class so export class sign up dto and those are the three different fields that you are expecting here now that this exists we can of course import it but this is not enough to actually validate the data because now even though we have set this as the type of the payload if someone tries to send a request that does not contain those fields or that contains different fields this is not going to throw an error of bad request so we have to use a package for that called class validator with a built-in pipe in sjs so let's go ahead and do that let's go back to our terminal and say npm install and the two different packages are class validator and class Transformer as well so let's go ahead and and install those packages and once this is done let's go to our main.ts and actually apply a global pipe so that it validates every uh different dto that we have inside of our route Handler whenever we assign them to a body or other decorators so we can say app.use Global pipes and then here we can pass in the validation pipe of course we need to say new and here we can pass in some configuration now I like to pass wh list through and then forbid nonwhite listed to true as well and what Whit list does is it will take away the fields that should not be sent in the body and then if it is not allowed it's going to throw an error here so instead of just sripping them away it will throw an error and of course for this to work you also have to have Whit list I've already covered this in my njs series and the validation and pipes video so feel free to check them out if you want to dive deeper now in order for this validation pipe to work we should actually add some decorators here on every field or every property from the class validator package so let's go ahead and do that so I added some decorators from class validator as you can see for the name we just expect a string for the email we expect an email this is going to check if this value is an actual email and then for the password I added some uh decorators of course it should be a string and then uh we want the minimum length to be six of course you can set anything you'd like and to make the password a bit stronger I just added a regex here by using the matches decorator that expects a number so if if this password does not contain any numbers is going to throw this message password must contain at least one number of course you can add one for the symbols and so on you can do anything you want but this is how I want my sign of d2o to look like now let's go ahead and run our server and then go to postman and make sure we select the post HTTP method and then here of course we're running on Port 3000 and the route is o/ signup and if we try to hit send as you can see we got different error messages name must be a string email must be an email password must contain at least one number so this is perfect our validation pipe is now working correctly however now when we have a proper uh body we are respecting those different constraints if you hit send as you can see we got 2011 created of course now we're not actually creating anything but we are sure that our validation is working properly so the next step is to actually create a service method for the signup and handle the different logic there so I went ahead and created a method Asing signup inside of our o service which of course takes the signup data which is of type sign of dto and then here we have three different tasks we need to check if the email is use or we can actually use it for this new user and then of course we need to Hash the password by using bcrypt which is a package used for hashing and other stuff and finally of course we need to save the new user in our database so to be able to actually do that we need to set up the Mongoose module in our application so let's go to app module and do that inside of our Imports in app module we need to say Mongoose module and of course this is from nj/ the package that we have installed already do for root then here we need to pass the connection string for our database now my database is local so this is the IP and the port that you're going to be using and then you need to name your database we just going to call it o example DB now in case you want to read this dynamically from your EnV file and from a configuration which is of course how you should be doing it for production instead of using for root you can use for root async now to be able to save to our database of course we we need to actually inject the user model the one that we created inside of our Earth service so that we can use it and query our database now to be able to do that we have to go to the module in which we need to use that model so in our case the O module let's go to O module here and then we need to import and here what we could say is mongus module. for feature this time and here we can register the mod mod that we need to use inside of this module so this takes an array and then here for the name user. name of course I have a video explaining everything here so feel free to go and check it out I'm going to leave the link in the description and then here we need to provide a schema which is the user schema which is the one that we defined here why by using user schema. create for class and here if you notice we got an error reference error document is not defined and this this is because here we're extending from document but it's not actually importing the correct document the document that we're trying to extend from is the document from so with this change if we save again and run our server as you can see everything is fine and now with this in place we can actually inject this user model inside of our o service and then use it so what we need to do is let's come here and inject it in our Constructor using at inject model and then here user. name is the token and then we could say private user model for example and this is going to be of type model from Mongoose and then we can give it a type of user for example which is this user schema here so now if we take a look here we could say this do user model. find. create and so on let's go ahead and Implement our sign of flow let's start by checking if the email exists so let's say for example uh email in equal away this. user model. find one for example and we could pass in the email from the sign of data email so now we are checking if we have any document that has this email and if that's the case so if email in use if you got a document what we could do is say Throw new you could say bad request or conflict exception as you wish I'm going to say bad request and then here I'm just going to say uh email already in news now for hashing a password let's go ahead and say NM install bcrypt and now we can create our hashed password so let's go ahead and say hashed password equal bcrypt and of course we need to import it here so I'm going to say import Star as bcrypt from bcrypt and then here if you take a look at bcrypt we could say dot right we need to install the types package so let's go ahead and do that mpm install at types SL bcrypt and now if you take a look here we could say dot and we can see the different methods so we're going to say do has and then here we need to pass in the data that we are hashing so in this case our password and I don't want to always just type sign up data. password. email whatever so what I'm going to do is here I'm going to say const and then I'm going to extract the email the password and of course the name from the signup data and then here here we could just find one on the email itself right away and here we could hash our password so the plain text password that was sent in the signup dto in Postman so in this case long pass 1 to3 for example and then if we take a look we should also pass a second argument which is salt or salt rounds you can think of this as another layer of security so here we can specify a number for example 10 which is going to be the number of rounds in the algorithm to make it more secure uh sold basically is used to have different hashes for same PL text passwords so if two different users chose a password of 1 to three using sorts would actually uh generate two different hashes for the same password which makes it more secure and protected so we're done with hashing the password we're done with checking the email and finally now we need to create the document so we could say await this. user model. create and then here we could press in the name that we extracted and then the email and then for the password field we're actually going to use the hashed password so that we store it securely in our database so this is pretty much it let's go ahead and test this out so here I'm going to go ahead and say return this. off service. signup and let's pass in the sign up data let's run our server open Postman and now if we hit on send we got internal server error let's see what happened okay so basically we forgot to actually await the process of hashing the password here so we need to await this we need to wait for this to actually complete hashing the password correctly and now if you go ahead and hit send we got 2011 everything is fine if you go back to our database as you can see we got off example DB with the users collection and if you take a look we got name email John and then the password as you can see this is properly hashed and now if we try to actually create another user with the same email if we hit send we actually got an error status code 400 b request saying email already in use so our sign of flow is actually working properly now let's go ahead and create a route Handler for the login endpoint so here we're going to have a post method log in and then instead of sign up data we're actually going to get the login data or the credentials so we could call it credentials or anything you want and here we could say login dto for example which we're going to create right now and then here we're going to call a login method which will take the different credentials of course we're going to build everything right now so for the login dto just like we did with the sign of dto let's go ahead and say login. dto dots and our login dto is simply going to have an email which is of type email and then the password which is is a string let's go back here and then make the import okay and now let's go ahead and create our login logic here so the steps here is first of all we need to find if this email exists to make sure that the user exists if that's the case the next step is to actually compare the different passwords the password that the user entered in the login form and then the password that exists on the user in our database of course we're going to be using bcrypt to make that comparision it will compare the two hashes finally if everything is fine we are going to generate our JWT tokens so we're going to generate an access token and then a refresh token and we're going to talk a bit more about them so let's get started so just like before I went ahead and extracted the email and the password from the credentials and I'm searching I'm trying to find a user with this email so user model. find one and then we pass in the email now in case we don't have a user so if no user we can go ahead and throw an error and here is a good to throw unauthorized so we are not going to let the user know that this email does not exist in our system instead we're going to give them a generic message such as uh PR credentials for example and of course here we should not forget the new and unauthorized exception is going to return a 401 uh status code now in case we actually found a user with this email so for example if we sent uh John gmail.com and we actually got this record we now need to actually compare the password that was sent in the API request in the request itself and then the password the hashed password inside of our database and to do that let's for example say password match and then we can use bcrypt I'm going to say a wait bcrypt Dot and then here we have a method called compare which takes two different arguments the first argument is the plain password that we sent in the request and the second one is actually the hashed password from our database so that would be user. password and now if not password match so if this returned false then we can throw an error here throw new unauthorized and as well generic message wrong credentials now of course it's a better practice to actually have an errors file for example which is going to have your errors that you can reuse but I'm not going to do that in this video before moving forward to the final step let's just make sure that what we have right now works so I'm going to return my message success let's go ahead and run our server go back to postman and this time create another request of course it should be post as well and this time it should actually be to the login route and here for the body let's go ahead and past this body here and of course we should actually remove the name so let's say we actually send the correct email and password that exist in our database if we hit send as you can see we got message success however if our password was incorrect for for example long pass 1 2 3 4 as you can see we got wrong credentials but let's say uh we actually had a wrong email so we send Jeff at gmail which is someone that does not exist here if we hit send we also got wrong credentials so that's a good practice this is a generic message to make sure that users cannot actually find out what different emails exist in our system now that you know that everything is working fine here we still have to generate the tokens and use them so let's see see how we can do that so first of all we need to install a package called nestjs JWT that is going to actually help us generate tokens and verify them the next step is to actually register the JWT module inside of our app module so to do that we could import JWT module from njs JWT and then register it and here we can pass in many different configurations as you can see here such as if this module should be globally used and the secret the secret should be securely stored somewhere so it could be in your environment variable so in your EMV file and then you can use register async and read it from there I have a full video on that I'm going to do it quickly here but you should always make sure to never actually push your secrets to your repository so I made the fixes to actually read those values dynamically and I'm going to quickly go over them but if you want the detailed video I'm going to keep the link down below I have a full video on configuration basically you need to install nestjs / config which will allow you to actually import a config module and then you can use for root to register it I set it as Global and then you need to load a config file my config file I created I created one here it returns a function with some key value pairs I have a JWT with a secret and then just like we said the secret should not be statically in the code it should be securely stored inside of a Secure Vault in our case here we're using aemv file of course it should not be pushed to GitHub or gitlab so we need to add it inside of our G ignore so here we could say for example EnV and if you take a look now as you can see it's no longer highlighted in green it will never be pushed to your repo and this is the right way to do to do it and I also have a Mong URL here so now we can read those in the config file using process. EnV and then inside of our app module we can now use register async and for root async instead of register and for root and here I'm I'm going to go over it really quickly we just injecting this config module here and then we're using a factory function to actually set those URI and secret values dynamically using our config service that we inject here with that in place we can now dynamically change those values and have them securely stored and since we have globally registered this JW module now we can actually inject it inside of our US service here and then use it to actually create a token here so I went ahead and injected this JWT server from Nest JWT and of course this works because because we have installed the package and imported this module here and now if we take a quick look here for example this. JWT we can see that we have decode sign verify and so on here we need to sign a token I'm going to do the this in a separate function to keep it to keep this one clean so I went ahead and created a separate method called generate user token which takes a user ID and it's going to actually return an access token and a refresh token and I'm going to explain the difference in a second but to be able to generate an access token just like we said we can make use of this JWT service to actually sign a token and it can take a payload it could be anything we want I'm going to pass in an object that has the user ID so that whenever we get that access token we can actually know this token belongs to which user and then here if you take a look we can pass in some options such as a secret key however since we're already setting a secret key in our app module here we already specified a secret key we don't really need to specify it again manually here so we can just say do sign and it's going to use this secret key here to sign our tokens now we could also pass some other configuration other than the secret for example we could we could pass in an expires in and here we can specify how long it takes for this token to actually expire because you should not of course create a token that lives forever usually for Access tokens we give them a short time span and we use a refresh token to actually keep generating other access tokens so one main difference between the access token and the refresh token is that an access token has a short time to live but the refresh token has a longer time to live and the refresh token is used to actually create new access tokens whenever an access token expires so that's the main difference and the main role of those uh different tokens so here for the expires in I'm going to go ahead for example let say 1 hour if you take a look here we could say uh 2 days 10 hours 7 days and we can also pass in a number I believe it takes it in second or milliseconds so that's it for our access token here we can go ahead and actually return it and just like we set this expires in here manually directly we could also have done this here as well so we could have said sign options and then here we could say expir in but just to show you that you could actually put it either way I'm going to keep the secret globally here and then I'm going to set the expire option here manually now before generating the refresh token I want to actually try and return this access token to the user and see how it's formed so here let's go ahead and return this. generate user tokens and then for the user ID is going to be the user that we found here dot of course going to have the underscore ID field here and then let's restart our server and go ahead and use John and then the password was long pass 123 if we hit send as you can see now we actually received an access token and if we take this token if you go to jw. and then paste our token here we can see that whenever this token is decoded we have three different parts we have the header here which specifies the algorithm and the type and then we have the payload here if you take a look we can see that we have a user ID the one that we set in our code and if you take a look at our database John has an ID ending with 891 which is the same ID that we have here so we know that this specific token belongs to John now of course uh we can decode tokens without actually having the secret key so I don't really have a secret key here to verify it but in our code we're never going to decode a token and then move on we're going to actually verify that this token belongs to our application by checking the secret key if you don't understand what I'm saying right now don't worry we're going to cover this when we reach the guard part of our application I also want to point out that here we have the expiry of this uh token so if we take this EP converter if we take this and then put it here as you can see it has 1 hour so this expires in 1 hour so in my time zone 222 now it's 124 of course we generated this token 2 minutes ago so it is actually 1 hour and this is what we actually set here 1 hour so this is actually working correctly so just like we said the main purpose of a refresh token is to actually uh create new access tokens once the expiry time of an access token expires so it would make sense to actually return a refresh token here well for refresh tokens we need to save them in our own database so we we need to actually go ahead and create a new schema here I'm going to call it refresh token. schema. TS so our refresh token is going to look look like this we have three different properties the actual token value and then the user ID so that we can tell this refresh token belongs to which user in our database and then the expiry date because of course a refresh token just like an access token is also going to have an expir date now the difference between this expiry date and the access token expiry date is that usually a refresh token is long lived so this expiry date would be uh way longer than the one for an access token and that makes sense since you using a refresh token to actually generate many access tokens now let's go ahead and register this model inside of our o module just like we did with the user so refresh token. name and refresh token schema and now we also need to inject this model right here just like we did with the user so refresh token again then let's call this refresh token model which is a model and it's going to have the refresh token uh type which is the one that we created here now to create an access token we use JWT service. sign for the refresh token I'm actually going to generate a random long string that we are going to store in our database now since refresh token is a random string I'm going to go ahead and use a uu ID a very popular package to create unique IDs or unique strings so I'm going to be using this package okay to generate my refresh token so let's go ahead and install this package and then let's copy this and here after importing of course we can call this function I'm going to say refresh token equal this U ID and then I'm going to return the refresh token we still need to to store that refresh token in our database but first I just want to see how it looks like in the response so let's go ahead and run the server again and now if we log in again as you can see we now also have a refresh token of course you can use any package that you want you can make it as long as you want uh but I'm going to be using this package now we still need to actually save this refresh token in our database we already have a schema and we have already uh injected our moduel here so we can use it to create it I'm going to go ahead and create another method here I'm going to call it uh store refresh token which is going to take a token which is a string and then here we need to actually create it so I'm going to say away this do refresh model. create and then here we need to pass in the token and of course we also need to pass in the user ID here because if you take a look we are also storing the user ID so that we can tell this token belongs to which user so here we can pass in the user ID uh we're going to have the token the user ID and of course we need an expiry date here so for the expiry date what I've done is I took the current date and then I add 3 days on that current date and this is going to be our expiry date so our refresh token is going to expire in 3 days now we just still need to store the token here so I'm just going to say away this do store refresh token and then I'm going to pass in the refresh token as my token argument and then the user ID let's go ahead and save this and now if you call this API again as you can see we got a new access token and a new refresh token if you go back to our database and if you refresh here as you can see we got a refresh token collection and then we can see that we have one document this is the token which is the same refresh token that we returned to the user and we can also see that we have the user ID which belongs to John and if you take a look at the expiry date we can see that it expires this month so May 28th today is 25th so this is correctly 3 days so now we have successfully created our log in API which checks if we have a user by email and then if we find that user we are going to match the passwords the one that was sent in the request and the one that is hashed in our database and then if everything is correct we are going to generate an access token and a refresh token and we store the refresh token in our database and of course we return them both to the user and we also said that the access token is shortlived and the refresh token is long lift so anytime the access token expires the front end or the client is going to actually make a request to this refresh token endpoint that we're going to create so John is going to send the refresh token again to that refresh token endpoint that we're going to create which will check if the expiry date and the actual token value is correct in our database and if that's the case then it's going to create two different tokens for John an access token which is a JWT token which has the user ID and its payload and then a new refresh token to with 3 days as expiry again so for the refresh token I created a new uh Handler the route is refresh I call it refresh tokens and then we're going to get a refresh token dto which we're going to create now and of course we're going to call the refresh tokens service and then we need to pass in the refresh token so let's go ahead and go to our dto create a new dto going to call it refresh tokens. D.S and our refresh token dto the payload is just going to have a token which is a string and now after the login uh method I'm going to go ahead and create Asing refresh tokens and it's going to take a refresh token which is a string and then here we have a few things that we need to do first of all we need to verify that this refresh token exists in our database and has not yet expired and then we're going to get the user ID from that refresh token and call this generate user to tokens uh function so that we can generate a new access token and a new refresh token which we store again and yeah that's pretty much it it's pretty straightforward actually so it's pretty straightforward token equal this refresh token model. find one and we try to find the the actual document by searching for the token and of course we also need to make sure that it has not yet expired so expiry date should be greater than now's date so if that's not the casee if we haven't found this so it either does not exist or it has expired we could throw new uh unauthorized exception for example and at this point what the front end does they would uh throw the client back to the login screen where they have to log in again and get brand new tokens and if the token is valid so it has not yet been expired and the refresh token is correct then what we need to do is actually return new tokens so return this do generate user tokens and we need to pass in a user ID thankfully we are actually storing the user ID on this token so we can simply say token. user ID let's go ahead and save this and of course here we need to send the refresh token does not exist on type refresh token dto let's call it refresh token and save and let's go back to postman and try to actually refresh our existing tokens currently our tokens are these this is the access token and this is our refresh token if you take a look this is the same value so I'm going to go ahead open a new request it should be a post request and then here it should be refresh and in the body of course we need to go ahead and send a token we call it refresh token so we need to make sure we pass in the correct uh name of the key and then let's let's go ahead and pass in a wrong uh token first so I'm just going to pass this part to see what happens if we hit send as you can see we got unauthorized of course here we can enhance the message we could say refresh token is invalid or anything else we could also just like we previously said have an eror folder that has a lot of error objects that you can Define but this is not in the scope of this video but anyway this is a good message uh let's go ahead and actually pass a valid refresh token and hit send as you can see we actually got a response we got a new access token and a new refresh token so d55 and so on if you go back to our database and refresh as you can see we actually got a new document here which belongs with the same user ID now what we could do is let's say that we can we can only have one refresh token uh per client then what we would need to do is remove the previous one so remove the previous refresh token and only keep the new one so let's go ahead and do that now back in our code we can simply say find one and delete so this is going to delete uh the record going to go ahead and refresh going to delete the first one manually but now let's go ahead and take this new refresh token and then back in Postman let's say we actually want to refresh our tokens so I'm going to put the new refresh token hit send as you can see we got a new refresh token and a new access token the refresh token starts with with 7 F5 if we go back to our database and if we refresh as you can see we only have one document for this user with the refresh token of 7 F5 so our refresh token is working properly now let's say our expiry date actually expired so this token's expiry date ends in 2023 and now we're in 2024 if I go ahead and try try to refresh this token so let's take this value here and let's try to refresh this token to generate new tokens if I hit send as you can see refresh token is invalid and that's because it has expired but if you go back to 2024 for example update and then send again as you can see our refresh token end point is actually working properly now this is the most basic way of doing refresh tokens now if you'd like to actually uh maybe add some layer of security make it maybe harder uh for anyone to try and exploit this route you could maybe also ask the user to enter their user ID here and then you would search for the combination in your database and of course the user would actually have that user ID uh from the login here so alongside with the access token and refresh token we can also pass in the user ID from our login here so here we can actually store these in a token for example uh in a variable we could say token to equal away this and then here we could say return tokens and then maybe user ID which is going to be the user doore ID and now whenever we log in send uh that's a sign up actually here is the login API if you hit send as you can see we are now also returning the user ID for the actual user which they can store on their local storage but enough for that now let's see how we can actually protect our apis and only allow users with an access token to actually call our endpoints but before we actually Implement our oard I just want to say if you guys are still watching and enjoying my content please leave a like subscribe and I'm probably going to make a part two in which we actually uh Implement two different endpoints change password and forget password in which we actually send an email with a link to uh reset your password and I'm also planning on making another video which is going to take care of authorization roles and permissions and so on now inside of appcontroller dots I went ahead and created a route Handler some protected route which returns message access access resource by default this is a public route so if I go to postman and hit send as you can see we got access to Resource but what if we actually want to only allow authenticated users to actually call this route so users who have logged in previously and got a valid access token we're going to be using guards for this so let's see how we can do that let's go ahead and ins inside of the source folder I'm going to create a new folder called guards and then I'm going to create a new file and then I'm going to create a new file I'm going to call it O.G guard. TS and this is how a guard looks like by default it's basically a class decorated by injectable so we can actually inject it as a dependency in our other services and it implements an interface called can activate so now we need to implement this can activate method which takes a context of type execution context and then we need to make sure that we return a bullion or a promise of a bullion so with acing await or an observable just like we do with rxjs so now it's important to actually return true or false here if we return false every request that actually enters this oscard won't be able to go to the route Handler it will actually throw an error by default it throws forbidden 403 but if we return true then this will allow the request to actually proceed and go to the route Handler so here we need to have some logic to actually check if our request has an access token in the headers and if that access token is actually valid so we need to verify it and if that's the case we can continue if not we can throw an error so let's see how we can do that so the first step is to actually inject the JWT service inside of our o card and of course this works because previously in our video we actually registered the JWT module in app module and we Define it as Global so now we can actually use it here as well not just in our o servers and the next step is to actually check if our request headers actually have a token so technically inside of our request Postman for example here in the headers we can add authorization okay we can either add it here or we can also add it here we can go to authorization Tab and then go with bar token and then here we can add our token so for example in our case our token or our access token is this so if you take it and go back here if you put it here as you can see by default it added this authorization here and it added the word barer and then space and then we have our actual token which ends with vrl which is the token that we actually added here VL which is the token that we got from our refresh token API now to get access to our request headers what we could do is let's go ahead and say request for example and then using this context we can actually switch to http and then here if we say dot we can see that we have the next object the request and then the response object of course we need the request here we don't really see what we have so what we could do is specify that this is a request and then here we could say import request from Express and then here request dot we can see that now we have access to for example the body the headers and so on going to go ahead and create a method called extract token from header which takes a request and then checks for the headers okay so it will take a look at our headers and it will try to find a key of authorization so here we're going to try and find this authorization and if that's the case we're going to split the value and then take the first index so not index zero but index one and if you recall I previously said that we have here a value of barer space and then the token so since we need the second uh value so index one we would need to do that here to only get the token value so here what we could say is Con token equal this do extract token from header and we can pass in the request now of course this is whining because we're not returning true or false yet but we're going to do that in a minute now with this token first of all we need to make sure that it exists and then we need to make sure that if it does exist it is actually a valid token so we could say if not token now I like to instead of returning FS which will like I said previously throw a forbidden 403 error I like to actually throw throw an unauthorized error with 401 so so what I'm going to do is throw new unauthorized exception and then for example we could say invalid token and in case the token is actually here we have a token we need to verify it so I'm going to say payload equal this. JWT service. verify and then here we need to pass in the token so token of course usually we would need to also pass in a secret but we don't really need need to pass in a secret here because in app model. TS we already defined our secret and we're already reading it from our EnV so let's go back to our guard and here we could add a TR catch block actually because this will throw an error in case the token has expired or in case we used a wrong secret or whatever so I'm going to add this here and then for the catch block here we could for example uh throw an error thr new unauthorized except option we could say invalid token and here we could use a logger for example so logger from ljs and we could say error and then here we could say a e do message to just check what is the problem here and if everything is fine we can actually uh return true and in that case if we got the payload we did not catch any errors so we have successfully verified our token we can proceed with through and go back to our route Handler now usually in nestjs and express we attach the user object to the request so we could say you request. user or user ID and then we could give it the payload or payload user ID whatever now of course it's going to throw an error because user ID does not exist on request and request here we specify the type as an Express request now usually you would go ahead and create your own request okay so maybe you could create a class request with the user info which would extend the actual request from Express but to be uh faster in this video I'm just going to keep it like that with an with a type of any and now whenever we return through we're going to have this user ID on the request object and to verify this let's go to our app controller and here you could say add TR and then I'm going to get a reference to the request and I'm just going to log or actually I'm going to return here the user ID user ID which is going to be from rec. user ID let's save this and now we still have to do one more thing which is actually applying this guard on top of this controller right here so what I'm going to do is I'm going to say use guards on the controller level of course you can do it on the rou level or globally but here I'm just going to do it on top of this controller so it will apply to every route that we have use guards I'm going to say um authentication we call what did we call it o card so I'm going to say o card here and let's save and now if you go ahead and try to actually make a request here but first i'm going to remove the O so we don't really have an O here and I'm I'm going to remove this if you go ahead and hit send as you can see we got invalid token unauthorized if you go ahead and add a better token if you hit send as you can see we actually got a response Now message access access resource and then we got the user ID and this user ID is the one that we actually fetched from the token so back in our code if you take a look at the guard here whenever we verifi this token it actually returned a payload which has whatever data that we actually assigned on it whenever we actually generated this token so in our app service so in our o service actually and generate uh user tokens here whenever we created this access token we actually sent a payload of user ID and this is exactly why we can now in our oard get this user ID from the payload and to verify this we can go to jw. take a look here paste this token and go to the payload data here we can see that we got this user ID that we assigned whenever we logged in this way whenever a user makes a request to a protected endpoint we are able to tell which user actually made that request by just taking the request and then getting the user ID from it of course you can create a custom decorator here so we don't have to always inject the request itself you can create uh something like user info and all of that but that's not the point of the this video now just to show you a few different errors let's say we don't actually send a correct token if I hit send we got invalid token if you go back here we got error invalid signature and this is the log that we actually added here so as you can see we got invalid signature now let's try to actually generate a token and ex and wait until it expires and then try to make a call and see the expiration error so to do that I'm going to go to my o service and then instead of expires in 1 hour I'm going to set it to a few seconds so if I go ahead and save this now by default if you don't pass a string here you just pass a number it's going to take it in seconds so now if you generate a new access token it's going to be 10 seconds let's go ahead and log in at this user as John we got this token the 10 seconds has started if I go to buy token and paste this token and hit send as you can see we got access everything is perfect but let's wait a few more seconds and then hit send again as you can see now we got invalid token unauthorized if you go back to our code you can see error JWT expired which is from our guard here now here what happens is that the front end is actually going to take the refresh token so after logging in this is the access token that expired we have the refresh token that we got from the login API and the front end is going to make a request to the O refresh API paste the refresh token here and of course everything is working fine if we refresh our database oh we saved more tokens so basically whenever we are logging in again we are creating a new uh record for the refresh token we're not deleting the previous one I'm going to show you how you can fix it uh in a bit but for now we got this refresh token DCB which is this one and we got an access token that expired after 10 seconds so what we could do is call the refresh token API pass in this token hit send we generated a new access token and a new refresh token of course the access token is going to have an expiry of 10 seconds so let's send and as you can see it's now working but if you keep calling it after 10 seconds eventually it's going to be uh invalid because it has expired again now let's say for your application you just want to have one refresh token document for your user maybe that's your use case that's how you build your application so we don't really want to create different refresh tokens for the user every time they uh log in we just want to replace the older one okay let's say that's our use case or business logic what we could do is first of all whenever inside of our refresh token we used to do find one and delete to make sure that we're deleting the previous one let's just keep it find one here it's fine and then here whenever we are storing a refresh token instead of actually creating it we're going to use update one and then here in update one we're going to search for a token okay we're going to search for this token with this user ID combination and then we're going to set the expiry date and then here is the key point the most important part is using upsert true let's check that this is working correctly I'm going to go ahead and delete all of our records here and now I'm going to go ahead and log in once as John if you go back we refresh we can okay why did we get two okay my bad here we should actually only filter only search on the user ID since we're going to have one document or one refresh token per user so we need to make sure that we only have one so we search on the user ID not the user ID and the token and then here we set the new token value and then the expiry date and upser through to make sure that we at least have one document so if it does not exist we end up creating it if you ex if it exists we just update those two Fields let's try to do that now if we hit on log in if you open this we can see that we have one document if you hit send again go back here refresh as you can see we still have the same uh record but this time we have updated the token so it ends up with ca2 if we send again it should end up with Ed if we open this refresh as you can see it ends up with Ed so this is based on your actual uh use case if you don't mind having different refresh tokens for any reason that's fine you can just create and not use update one with upsert and also let's see if we can actually uh if when we call refresh token if it's going to create a new document or actually update it technically it should update it because we're still calling this store refresh token function if you go ahead and refresh as you can see we actually got the newly uh generated refresh token 7 f8 which is 7 f8 so to summarize everything we created a earth module this module has two different schemas now of course the user schema in case you had uh some users related apis you could have went with two different separate modules you could have created a user module but since here we we don't really have a user module I just added the user schema inside of the O module and we also have a refresh token schema which is going to have the token the user ID and the expiry date we have some basic o apis such as sign up log in and refresh to refresh our tokens and generate new ones for the sign up it's pretty simple we just check if we have an existing user with this email in use if that's the case we don't allow the user to create a new account if not we can actually hash the password by using a package called bcrypt and then we create this new user in our database with the hashed password name and email and then for the login API we need to pass some some credentials the email and the password and then here first step is actually finding a user with this email that the user entered if you don't find that user we throw an error wrong credentials however if we do find a user we need to compare the passwords of course using bcrypt again we need to pass the plain text password from the request and compare it with the found user in our database so the hashed password if it returns true then that's amazing if not we can throw an error wrong credentials and then finally we need to generate some tokens such as the access token and the refresh token the access token uh is a JWT token it is created of three different parts headers payload and signing secret now to be able to use this JWT service we had to inject it here and of course for that to work we need it to actually import JWT module after actually installing nestjs JWT and here we can set some default configurations such as the secret that weet should always be in a secret vault or somewhere protected and should not be exposed we need to set it to Global and now we are able to actually inject it in our US service and use it to sign and to verify tokens in this case we signed this uh token we created a token we signed it uh we specified a payload which is our user ID and then we gave it 10 seconds as an expiry date of course in real life it's not going to be 10 seconds it's going to be uh more depending on your application it could be 24 hours it could be a week it could be six hours depending on your application we also said that we need to create a refresh token which is going to be long LIF so it's going to have a longer period of or a longer expiry date than the access token it should be a random string so I went ahead and used your ID you can use Nano ID you can use any string generator that you want and then finally we need to store this refresh token in our database as such so that whenever we need to refresh and create new access and new refresh tokens we can actually check if this refresh token is valid hasn't expired and belongs to the user before actually uh refreshing it and then finally we are returning those tokens and the user ID to the client so that they can use them so that they can uh make calls or requests to the server with that access token to protected routes and we're going to see them in a minute but first we also said that we need to have a refresh tokens uh API so just like you see here it's going to take a refresh token and then here we need to find or make sure that this token exists and hasn't expired and if if that's the case we generate new user tokens based on the user ID of that token so that's pretty much it for this now to be able to protect routes from unwanted access so for example here our app controller has one API that should be protected so we can make use of guards which is something available in sjs so basically it's a class decorated with at injectable that implements the can activate interface so we need to actually Implement that method which should return uh true or false of course could be a promise or an observable as well and here what we did is we took the context got the request out of it extracted the token from the header from the authorization and then we used the JWT service again once again to verify our token and make sure that it's valid of course as well we need to pass a secret we don't have to do it here manually because we already did it again here in our configuration and then we said that we can attach the user information the user object the user ID whatever you need on the request object itself and then of course we're catching any errors provided by the verify so if the JWT expired or it's not valid or whatever and we can return an error else we give access to the request or to the user to access our server and here they were able to reach this route Handler that's pretty much it guys please make sure to leave a like And subscribe if you enjoy this video I'm probably going to make the next video maybe in one or two weeks uh let me know if you want to see something else and if you have any suggestions please let me know down below uh I'm going to keep some resources for my sjs playlist down there if you want to take a look thank you for watching and see you next time