Nest.js - full authentication course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello guys and welcome to today's video in today's video i'm going to recreate a project i did in the past uh if you go to my youtube channel consider the first video i created uh was a pair on authentication course so in the past i just did it in a very simple way i did it with express.js and i decided to recreate this project it was a long time that i wanted to try nest js which is actually a framework built on top of express and i decided to try and i liked it a lot so i recreated my burn authentication project with nest js this is the official page of nest js and we're going to use a prisma which is also more ram for writing sql in my opinion right now it's the easiest and the most efficient one there are also options like typogram and sqlize but when i tried the prisma it felt very easy to use so we're going to use prisma to interact with our database and sjs of course as our framework and you can see that they have a cat image here so it's supposed to be good all right so let me show you first the complete project by the way what i liked the most about an sjs is it is how the project is very well organized and you don't need to think too much uh to organize your project they actually have some cool structure that they implement and it's very good to have organized code as a front-end react developer i know that organized code is very important and usually when you don't follow a clear structure the code is going to be very hard to maintain and how to read so i liked the structure of this next js application very much so what we're going to be building is actually the same functionality of the previous project so we're going to have a authentication system so first of all you can see that we have this prisma folder that we're going to use to interact with our database create a schema uh create migrations and stuff like that and inside src we have a few actually we have two uh modules we have the off module and the users module and inside the off module we're going to place the logic for a sign up sign in and sign out and we're going to have jwt tokens implemented with cookies i don't think there is any youtube video that actually uses cookies for nest js so i hope you enjoy this part and we're going to have a user's module which basically will fetch all the users which is going to be a public public route and we're going to use the protected route to fetch our users so if we are logged in we are going to be able to fetch our user with all the info and i created this util folder just to place some constants like nv variables and stuff like that i'm not sure that this is the best practice for sjs but if you have any better opinions write me on the comments i'm still new to nest so i created it in express style so we just have some variable nv variables here so anyway this is the finished project we're going to work with this to do text that i created and basically we're going to do all these things i'm going to generate next project and do everything from scratch and that's it so on the next video i'm going to start generating the project you can code along with me of course the complete project is already pushed to github so you can download the code if you don't want to write it yourself and this is going to be amazing boilerplate for any project that you want to do in the future so you can use this authentication project to and basically to build on top of it anything you want so this is it and we can start uh working on generating the nest project all right let's begin by creating the project so let's go to the docs and see what we're supposed to do so as you can see here uh on the on the introduction uh they said that you have to install the nsgs cli globally so just do it i already did it so i'm not going to do it again and then you create nest new and project name this is basically how you create the nest project so i'm going to use actually i'm not going to use the terminal from here because i want to save this space so by the way you can use it in the vs code i'm just going to open this new terminal every time i want to install something and to run the app so we're going to have here two tabs and let's actually do the command nest new and the project name so i'm inside my burn of sjs so let's type here nest new and let's say this is going to be youtube sjs off and let's press enter now now they ask me what uh what package manager i want to use so i will use just 10 pm you can use anything you you would like alright so it took some time and the installation finished so as you can see we got all these files from the installation so let's actually already clean the project a little bit so let's see what we have inside src uh okay so the only thing that i need from here is this app module basically we are not going to use any of this and we can delete the imports also and let's delete all these files except main ds and the up module yes and let's see what we have here uh so here we actually having this function bootstop which is which is actually running the application and the by default is running on port 3000 so this is usually my react up so let's change it to 5000 and i can get rid of this test folder because we are not going to do any of this we we don't need to write test because our code is going to be fine and basically we're done so this is uh our clean project we don't have anything inside the up module ts and this is the starting point that i wanted all right so the next thing is going to be creating a off module with controller and service so we're going to use the nest cli to actually generate us this module so if you go back to the next next website you will you can go to recipes and you have this card generator tab and here what it says that you can generate a new resource by implementing this command nest g resource and of course you have to give it the resource name so what we're going to create is a user so is off and we're going to use this no dash dash no spec to not create test files for this module so let's go back to the terminal note this back to the terminal and first of all let's cd to the youtube folder and let's paste this command and let's say this is going to be off and no spec now let's install this and by the way it's going to ask us what resource we're going to create so you have few options here we're going to use rest api would you like to generate card entry points no i don't want to do it and let's check the project all right so you can see this off folder and we're getting off controller file of module and of service and let's go to up module and you can see that i already have import of uh the off module that happened behind the scenes so we don't have to do it manually uh in the imports we're going to import uh like we when we're connecting uh mod one model to another so we can import it like this and what we're going to do now uh is first i will explain a little bit what are the controllers and providers and we're going to create to work on our controller first so controller is basically where we interact with with the api calls so we actually define our api routes in the controller and the services where we actually execute the logic of the of the route so it's divided like this and here we specify so let's start with specifying the routes in the controller all right so as you can see we have this controller which is empty i have a controller decorated here so it says that this is the controller and to have some post requests here so let's create a post here post is coming from the nsjs common so this is going to be a post route and i can already specify here the route so let's say that this is going to be sign up for example i'm going to create few of these and now we have to create actually the function of sign up and basically for now we can just return some some string or something so let's return sign up out just to test that it actually works by the way we're going to use postman to test the routes to test our api so let's create a few more of this and the next route is going to be signing and this is going to be also signing and let's change this to sign in and the last out is not going to be a post it's going to be a get load so let's import it from sjs common and this one is going to be sign out so i can change all the strings already so let's say here sign out and save this file and now i want to actually check that everything works properly so let's try to run the app and let's try to go to postman and create a post or get request to one of this routes so let's go back to the terminal and let's see we're going to use uh the command to start the development if we go to package.json uh the command is start dev so what i need to do here is npm run start dev like this and let's see for a second that we don't have any errors so it looks good now we need to go to postman now let's try to do a post request and as you can see the route that i want is going to be off and sign up so let's try to do it localhost 5000 off and sign up hit send and you can see that i'm getting back sign up route which means that the routing actually works and the app is working properly now now instead of returning the strings we're going to implement the logic for the off service so as i said this is just managing the route manager and of service is where we actually do the logic first let's define the constructor already not going to put anything for now but just to have it here and let's create all these functions with the same names so sign up sign in and sign out and all of them are going to be async because later we're going to interact with the database so first one is sign up and async sign in and async sign out okay so for now let's return and let's say here just let's say message just for the test uh this is sign up so so let's say sign up was successful just for the test and okay so now uh here let's return empty string and return empty string and let's go back to the controller and instead of returning this string we have this off service so what we can do is do this dot of service and here we have all the functions that i just created on in the off service so i'm going to return the sign up and basically this is going to return this message if everything works properly so let's do the same here so this is going to be this dot of service and sign in and this one is going to be of course the sign out sign out now let's try to send this request again and you can see a message signup was successful so now the controller is connected to the service alright so before we can actually do some things inside our off service we need to initialize the prisma module and service and we have to connect the prisma service to the off service so we will be able to do here some queries and stuff inside the database creating a user and stuff like that so let's go back to the docs and in recipes you have this prisma tab that actually explains you how to connect to prisma so let's go for this and see what we need uh to do here so first we need to install prisma has a dev dependency so let's just copy this command and here i don't want to stop the server so i have this another tab let's see i need to cd to the youtube folder and we can install prisma okay now let's do uh npx prisma in it to enable the prisma and it's going to create us some things including a dot env file so let's run this command and see what it gives us npx press my need okay so let's go to the project and you can see that they created the prisma folder with prisma schema here and by default i see that they give us a prismaclient js db provider postgres which is what we need and the env is going to be database url let me actually get rid of this comment and save the file now let's check the dot env that they created for us uh okay so we can get rid of this also and you can see this database url which is the connection to our database basically and to connect to postgres database i'm going to use a [Music] local database that i have in my machine so here you can see a list of databases that i have postgres database i'm not going to explain you how to actually create the database because i think i have an explanation about it in my uh previous of video so it's very straightforward you just need to install uh i think something from postgres uh and just create a database so i'm going to use i'm going to actually connect to this paren off database so here in this string i have to change this string according to my info so i think the user i think my user is just postgres and the password i think it's sold if i remember correctly localhost 5432 and my db is going to be this burn off so let's type here burn off let's save the cnv let me actually double check in my finished project uh so oh so it's supposed to be a string actually uh postgresql postgresold localhost yeah so i was correct but let's copy it anyway and let's just paste it here so i won't have any mistakes so this is the connection string to my database and this is basically how it is connected how the prisma is connected to the database first of all let's restart the server because usually when you add some things to the env file you should restart the server so let's go here and let's on the server again npm on start dev all right let's go back to the ski schema.prisma so let me paste here my user model and let me explain what fields the user is going to have so it's going to be it's going to have an id which is going to be type of string and it's going to be unique field and the default is going to be generated by uuid so it will generate a random random string the email is going to be string and it's going to be unique and we're going to have a hushed password which is going to be string and created and at an updated at which is going to be a date time and the created ad is going to be default as now and updated it is going to be this uh special field prisma which is just called updated at so let's save this file and now we're going to create a prisma model and prisma service okay so the next thing is going to be this installation of prismaclient so let's copy this command and let's install the prismaclient and now we can actually generate the prisma service so this is the way that they generate it so just going to copy and it's going to connect the database when the app is loading and close it or close the app and basically we can just create a prisma.service.ts file so let's go to the placement folder and create a new file here prisma dot service dot ts we can paste this code here now only thing left is to create a prisma model so let's create a new file here again inside prism folder prisma dot module dot ts and this is what we need from the prisma module so a new thing you can notice here that we're using this global decorator because i don't want to import this prisma service prisma module sorry in every [Music] in every module that i going to use it so i use this global decorator and basically uh this module is going to have prisma service as a provider and it's going to export it okay so i think we are done with the prisma setup now we have to create a migration to actually generate the sql files so let's go to the prisma docs and what i see here is we're going to use this prisma migrate dev i'm going to give it a name so let's copy this and inside the terminal let's paste it and let's just call it init and prismacommand not found so of course we have to use npx mpx in the beginning and let's see um the following operations are applied to the database missing but [Music] we need to reset postcards database let's say yes i'm not sure what this warning is and the migration is supposed to be finished so as you can see we have this folder now migrations and what this folders contain is actually if i expand it a little bit you can see that we have this init name that i gave the migration and inside this folder is going to be actually the sql file so as you can see this sql file is a representation of our uh sql schema that we created here so this user schema is actually this user table so what we're going to do next is to connect the prisma service to the off service so we will be able to use our prisma database here in the off service all right so let's try to connect the prisma service so because we defined it as a global global module let's try to use it right here so let's say here private let's call it prisma it's going to be prisma service which is coming from the prisma service and now let's say here this dot prisma dot user for example because we have this user table and you can see that i have all this i have all these properties on the user table so basically i think everything is working and we can start implementing the logic for this route all right so there are a few more things we have to do uh to actually be able to implement this logic so one of the things is how can i actually get the credentials of the user so let's say that i want to sign up i want to get the email and the password of the user so what i'm going to do is let's save this file for now let's go back to the off controller and i have to somehow get the the request body from uh from the route so what i can do inside this sign up is to define here a decorator called body and again it's coming from an sjs common and i can say that this body is going to have a dto object so i just call it dto so right now it has any type and i can pass this dto to the signup and actually be able to um to get the info from the dto so what is this dto this dto is actually means data data transfer object and we're going to create it in a separate file here in a separate folder here so let's create a folder here called dto and here we can say this is going to be off of dto.ts because the dto for signup and the idea for signing is going to be the same just email and password and to create a general of ttots we could for example say uh if if they were different we could say sign up the trts and sign in dt ots and we're not going to do it now because because it's the same all right so we're back to the desktop docs and what we need now is to install some things to pay to be able to actually uh use this tto uh properly and to validate the data that we are getting so basically this dto is going to check the password and email fields and check if they are correct so if you go here to the technics and validation you can see this using the built-in validation pipe and what we need we need to install [Music] this class validator and cluster transformer and we can go back to our terminal install it and pm npm hi [Music] alright so first of all i want to go to the main and use this use global pipes and create a new validation pipe so let's copy this let's go to maintes and let's edit actually i think i want to edit um okay so let's set it in the middle uh so create new validation pipe which is coming from sjs common now i can save this and let's go to the off dto and you can see that here the example they show again a body which is going to create user dto and it's going to be the type of create user dto basically you can see that i have this class validator that i can import some checks from here for example his email is not empty and just create a dto class and just check this kind of validations on the fields that i want so email you can see that is specified a string password is string and email supposed to be email and password is supposed to be not empty i'm going to paste my manual checks for the dto so let's go back here and these are the details these are the checks that i'm going to use so let's save and basically you can see that i have this uh off dto and it has a email which is this time and password which is a string and it's going to check if password is not this female is not empty if it's a string if it's an email actually i don't think i need any of this because it's enough to check if it's just an email and the password is supposed to be not empty and string and the length is going to be between 3 and 20 characters and the message that i provided here is going to be password has to be between 3 and 20 characters and basically we can save this file now inside the off controller i can say that this dto is going to be of dto and we import it like this and we can pass the tto to the sign up uh function which is inside the of service and of course typescript is going to complain because uh the this function is not expecting a dto so what we do here is we will go to off service and we say here that the signup is going to have a dto which is going to be the off and now what i can do is i can say const and let's say this is the dto and you can see here that i have the fields email and password so basically now i can use i know that i'm getting this email and password from the user and i can use this field to work with the database now let's actually check if this validation pipe's actually working and i suppose to get l if i don't supply this field so we're going to check this validation pipe oh by the way i think i forgot to implement here something to have a white list of true i will explain uh in a moment what it does so basically whitelist store means that only the field that i specified in the dto are going to pass to the function so let's say if i open postman and go here actually i already let's try to do uh something without email because i want to have arrow so if i add another field here i don't know for example uh roll and i say here say here admin it is not going to pass through the validation pipe and it's not going to go to the function so basically this is what whitelist does now i suppose to get an error for the email let's try to hit the signup out and seems like i'm not not getting anything [Music] all right sorry about the arrow i just forgot to import the prisma module inside the app module and this is why it couldn't find it so basically now let's try to do the post request again and you can see that i'm having a status code 400 and the message email must be an email this is uh means that the validation pipe working properly now let's try to do for example too short password and now we're supposed to get two errors which is good now let's uh supply a valid email test gmail.com and the password is going to be one two three so basically now i should pass the validations and you can see signup was successful of course we are not signed we're not making any sign up we are not interacting with the database yet but you can see that uh it's actually working because in the off service i got to this point where i returned this message which means that i passed the validations from the dto okay guys so we are finally able to create the user and work on this signup logic so first the first thing that we need to do is we have to check if the email doesn't exist in the database because if the email already taken we cannot create the user because the email supposed to be unique so now we're going to use the prisma service so first i want to search the user by the email so let's say here const found user it's going to be await and we're going to use this dot prisma dot user and we're going to use uh find unique and what we need to do here is to say well and let's say here where email so it's basically the same as doing email email so this is just a short shortcut for that and okay so we're doing this and if we have a found user so this means that the email is already taken so if let's say here if found user oops sorry if found user so i don't want to continue with the function i just want to throw an arrow and exit function so i'm going to use here for a new and how do they call it bed bed embed request exception so this bad request exception can be imported from an sjs common and i can supply here the message that i want to display so if i find the user i want to say email already exists all right so if we have the user we throw this bad request exception and if we don't find the user what i want to do before i save the user is to hash the password and to save the user with the email and the hashed password rushing the password let's go uh real quick to the next chest docks to encryption and hashing section and we can go down here and here they have a explanation of how to use beekeeped so first we need to install bigcrypt and install the big ripped types so let's install the bighip types first as a depth dependency so inside our terminal let's install this first and now we can npm i be crypt also okay and let's check package.json uh so dependencies be clipped and types be gripped okay so now let's import this big crypt over here but let's say everything be be creeped from uh be kept i think supposed to do it like that yeah all right so now what i want to do is actually let's create a helper function for uh hashing the password so what i need here is to the hash is going to be a way await bigrapes.hash password and salt rounds um okay so let's go down here let's actually make some spaces and let's create here another async function and call it a hash password and this function is going to take a password as string and let's say here that i want to let's say const [Music] password is going to be await first let me actually copy this let's copy this salt rounds let's make it 10 and a weight decrypt dot hash and we can copy this line of code uh so we're going to hash the password with the big crypt and then i want to return the hashed password and if i hover over this i can see that typescript typescript already say knows that i'm going to return a promise with type of string so we can use this hash password function in my uh sign up so let's say here that i want that const hash hashed password is going to be equal to it's going to be async so await this dot this dot password so we're going to pass the password to the function this password and now we can create the user with the email and the pass and the hashed password so let's say here const actually i don't have to define it as a variable i'm just going to await and let's say this dot prisma dot user dot create and now i think there is a data object here and with the data object i suppose to [Music] put the email so email and what else i need just the harsh password so this is how we create the user very simple all the other fields are going to be created manually the id is going to be created created that updated that going to be created uh manually so i don't so i don't have to do it and basically wait so basically this is it i'm just going to return this message signup was successful i don't have to return this user and [Music] okay let's save and let's try to run this again with postman and let's go here and try to create this user with this field let's hit send signup was successful so the way that we are going to test if the user actually created is something that is called prisma studio where i think the command is npx prisma studio i hope that i'm correct yeah all right so we have this prisma studio where we can actually check our database and look at this we have uh the user that we just created with the hashed password so all of this is my hashed password actually we can do a lot of things here also we can delete this user and add records and you know stuff like that so this is actually the reflection of our database all right so we finished with the sign up function we can close this for now it was pretty easy now we're going to work on the sign-in functionality all right so the sign-in function is going to be more difficult to implement because we're going to need actually the jwt service and all these things to actually be able to uh send a cookie with job with the jwt to the user but let's start working on it slowly step by step and the first thing actually that we need to do is to go to the controller and here i want to say that i'm also this signing is going to be also a post request with the body of the off dto that we defined earlier and i'm going to pass this dto to the signing basically the user going to sign in with email and password the same as the sign up so let's save this and inside the service let's say that here we're getting the dto as of dto and basically we can do the same of the structuring so const and this is going to be dto and here we have the email and the password alright so again i want to check if i can find the user by the email but now it's in purpose to check if the user provided a valid email so we can actually copy this section from the sign up and we can paste it here and again we're going to find the user by the email and in this condition if we don't find the user that means that the user provided a wrong email so we can say here instead of email already exist we can say wrong credentials credentials right the next thing i have to do is to check if the password is actually correct so here we're going to use the big clip again and we can use another helper function uh by the way right now i can see that we have a duplication here so we can just actually return the await statement like this so let's say return and it's going to be the same it's going to return a promise with a string so here let's create another helper function i think let's let's say compare passwords and what what we're going to get uh from this function let's say here x is going to be an object and we can say here that we we have to get the password and the hash the hash is going to be the hashed password both of them are going to be string string and let's say if we have an info here of compare here so is match and a way to be equipped compare with the password and the hash so we can take this and we can say return await be crypt so it's not going to be like this it's going to be args dot password and alex dot hash and the return statement is going to return us a boolean so if you can see here promise boolean so if if we get true from this function that actually means that the password is correct the the password the user provided is correct because we compared it with the harsh password so basically let's say here that i want to let's put it in a verbal const is match is going to be wait and compare passwords and this compare passwords having an object with with the password and the hash password is going to be hash and we can say found user dot hashed password and we can say here if no is match and again we can return this bad bad request exception so basically just copy this it's going to be exactly the same if no match i'm going to throw the bad request exception of wrong credentials and after all this we can be sure that the users provided the right email and password and now we can sign the jwt token so we can say here sign jwt and return to the user and to do this we're going to do some work before so let's start working on this jwt signing okay so before we start we need to install this uh nest jwt for now uh to actually be able to sign the jwt token so you can see that we have the gwt service that we can import and then we can use jwt service dot sign to sign the token with the payload that we want and npm hi this is jwt okay so first i have to import the jwt model so let's go to the off module and let's import here from nest jwt and this is going to be the how they call it jwt model module so let's take this so remember to import a module one module to another we use import imports and here i place this jwt module and now i'm going back to the oauth service and here bought from nest jwt and shade up jwt service okay so here we can say private jwt is going to be jwt service and now we can use this jwt to sign the token so let's create another helper function here i think sign token it's going to be it's going to take arcs again and the args i want to assign the the id of the user and the email so let's say here id string and email string because later we're going to use this fields to check which which user we have in the jwt so let's see here we can use here let's say const payload is going to be equals to hogs which is basically a payload now is equals to id string and email string let's see this dot jwt let's say here sign sync and here i specify the payload and here i specify the options for the options i want to have the secret so the secret let's actually import it um wait i think i actually didn't create the secret yet let's check the env no i didn't create a secret so let's say here let's create the env variable real quick so jwt secret is going to be equal to secret and we have to restart the server but first of all let me actually create here the utils utils folder so let's say details and as i did in the complete project i'm going to have constants dot ts and from here i want to import the env variables so const jwt secret is going to be process dot env and i don't have the secret updated yet because i need to actually restart the server so let's close this and let's say the secret is going to be jwt secret uh will it auto import let's go here about jwt secrets from details constants forgot to export it so let's say here export and back to the off service so now i supposed to have the secret and let me actually start the help so start the server okay and now we're going to use this sign token helper function so let's use it down here and let's say const token equals a weight sign token and the args that i need that id and email which are going to be the found user found user dot id and found user dot email and basically now talking for talking basically now i'm not returning this so let's say here return and promise string okay so basically now this token supposed to be the jwt token so let's actually try to test it by returning the token and now i can try to sign in with the user that i created so this is my user test gmail.com so let's go to postman and these are the fields the correct fields let's try to go to signing signing and send and you can see that i'm getting the token so actually the sign in functionality works the only thing that we have to add here is instead of sending the token like this i'm going to actually send it as a cookie to the client all right to send the cookie is actually pretty easy so first let's install this cookie parser and types cookie parsels dev dependency so let's go back to the terminal this is my prisma studio so let's go here and install npmi cookie parcel and let's copy also baseline and let's install the dev types and what we need to do here is we have to import it in the main ts file like that and we're going to use the cookie parcel in the in the main ts so let's import the cookie parser and let's say here up dot use and we can say cookie pulser like that uh do we need to do anything else here okay so basically now if i go to my app i need to go to the off controller and i have to supply some things here not only the body but i have to supply the request and the response actually i don't need the request i need to delete any the response but just to show you that this way i'm importing the request from let's just nest js common and i can say here this is going to be rock and i can say also res this is going to be the response and i can take this rack and runs and supply them to the signing so like advance like that and go back to the oauth service and let's say here that i supposed to get like and rise and now this second eyes are going to be a request request this is going to be phone express because this is the request and response that are coming from express and this one is going to be less response form express and as you know to send the the cookie to the client and we're going to use cookie and we're going to send the token so basically here what i want to do is dot cookie and here we specify the name of the cookie so let's just call it um jwt now let's just call it token token token and here i have to actually put the value so the value is token by the way i want to check that if i for some reason don't don't have a token so if no token let's say here throw [Music] throw new forbidden exception okay so if for some reason we don't have this token i want to stop uh the function and if we have the token i'm going to send the token as a cookie to the client and here instead of sending the token again let's say here just rest.send and let's say message and log logged in successfully okay so now we're going to test it and we're going to see if i'm getting the cookie back from the server so first let me check that everything is working okay so let's go to postman and now let's try to send one more time logged in successfully and if i go to the cookies section you can see that i'm having this jwt that i got that i got from the server and now it's saved in the cookie and basically we done also with the signing so it was a little bit more complex but it wasn't so bad now the only thing left is to actually uh do the sign out which is going to be very very very easy so the only thing we do here is we clean the token from uh from the client so how we do it we again i'm going to use the response and request so let's go back to off controller and i can just copy this request and response to the sign out and here i can say like and less and this is going to be get request so i don't have anybody here and basically now i can go to off service and i can get again i can just copy this request and response and to clear the cookie what i need to do is let's start clear cooking and i specify the name so the name is the name is token so token and we can send rs dot send and let's say here message logged out successfully and we can already test it so let's go back to postman and create a get request to [Music] sign out hit send and i don't have the cookie i deleted it correctly and of course i have the message logged out successfully all right great we finished with all this uh off uh off functionality and the only thing left to do is to create a user user resource and we're going to have two functions one is going to fetch all the users which is going to be a public public route and one is going to be fetching a user by buy id which is going to be guarded by off guard that we're going to create so let's start working on that and we will wrap up the project of let's actually create the user resource first so as you remember to create the resource we're going to use this command g resource and we're going to give the resource the name and it's actually going to be users not user i think this is the best practice to use it like that come again comment below what you think about that so next g resource users and we're going to use a no spec flag to not generate test files so let's go to our terminal and paste the command here users and let's say no spec okay so we're generating rest api and i don't want any card entry points okay so we have this user's resource and of course the user's module auto imported so let's see what we need from the user's controller so first of all i'm going to have route to fetch to fetch a single user so this one is going to be this one is going to be a get request and here we can say um we can actually call it get my user and where do i want to get the id form so this is going to be a get request so i want to get the id from params and this is supposed to be the route so the route let's just say id like that so users slash id all right so let's define how is this params object is going to look like so i can say that i'm going to get id which is going to be a string and for now let me actually create the you know what let's create all the routes already so this one is going to be get and this is going to be to get all the users so we can say get users and here i don't have any params and i don't have any route so just going to be to localhost 5000 slash users and now we can say no we cannot say because we need to actually go to the service and create this functions so let's say here for now constructor it's going to be empty and we can say now that get it's going to be of course async get my user and sync get users like that and we can save and let's say that get my users supposed to get the id as a string so let's say here id not if id the string and get my users is not going to get anything so now i can say here this don't get my user i'm going to have the id from the palms so actually i need to say arms dot id and it's not working properly it's this dot user service user dot get my user okay so now it's working properly and this one is this dot user service and get users of course i have to return this and return this all right so we have the routes now let's go back to the service let's actually get the prisma from let's say here private prisma is going to be prisma service and to get the users we're just going to return the users so let's say here return await this dot prisma dot user and i'm going to find many don't want to add anything so we will find all the users and this is a promise user okay so let's save so let's test this get users route so this one is going to be just get request to users and you can see that i'm getting array of one user because i created only one user for now uh the only thing that actually i have to change here is i want to get rid of all these files all these fields so i want to return only the id and the email so how do i do it i can say here select and in the select i have all the fields so let's say that i want the id so i have to say id2 and i want to have the email and this one is true and basically now i will get only the id and the email so if i run this again now you can see that i getting only these fields which is uh what i want actually from this route and when we work on this get my user i want to return all the fields like not all the fields not including the password but i want to return also the created and updated it and this is basically going to be the private route and this is the last thing that we're going to work on on this project okay so before we can implement the jwt strategy and guard we need to install some things related to passport so you can see this is actually my finished project json package.json so you can see that i highlight the password the passport field here and you can see that we need an sjs passport passport passport jwt and also dev dependency types passport gwt so first let's go to the to our terminal and install all these dependencies so we're going to install this dependencies nasjs passport passport and passport jwt and after it installed we're going to install a dev dependency npm i d and we're going to install types passport jwt uh now we can actually go to the oauth folder and i'm going to create here uh two files so let's create jwt guard a ground dot yes and let's create another file jwt jwt strategy dot yes all right so before we create the strategy let's go to the off module and we need to import the passport module first so let's say here passport uh passport module from nsjs passport and now i want to go to the jwt strategy and i'm just going to paste here the strategy uh because there is there is a lot of boilerplate so i will just paste it and explain uh what we're doing here so basically if you go to the docs you can see that this is usually usually how you create a jwt strategy is by creating this class jwt strategy and it extends passport strategy as you can see here you you could see in the docs that usually what they do is extract the jwt from a header asber token but in our case we are going to do it from the cookies so instead you can see that this is actually an array and i can even get rid of this because we are not going to use this strategy form header so let's get rid of this and this is our strategy that i created manually so digital ability strategy extract jwt basically this is going to have a request and it's going to check if we have requests.cookies and we have a token in requested cookies then we return request.cookies.token otherwise return null and this is a function that the default function that validates the the token so now let me first save this off module file and the jwt strategy and now we have to create the jwt guard that we are going to use for the routes and this way is how we we will create the guard we just export a class readability off card and it extends the off guard that is coming from sj's passport and here we supply the string with the strategy so let me check the terminal that everything is working properly i don't see any errors for now and now what we can do is we can use uh the strategy in the routes the guard sorry in the routes that we need to use it so as i said before we're going to use it in the users and i want to guard this get my user route all right now we have to go to the users module and we have to supply the jwt strategy here in the providers so let's say here jwt strategy which is coming from strategy that we created inside the oaf folder and let's save it and now let's go to the users controller and this is how we're going to use the guard so here we specify the quarter use guards and we have to pass that jwt the jwt off guard so let's say here the jwt off guard and now this route should be protected by the tradability strategy so let's open postman and actually check what we are getting okay so in postman i'm going to use the route to get a user so it's going to be users and then slash id so let's say some random id here doesn't matter what i type for now and hit send and you can see that i'm having status code 401 unauthorized okay so let me actually try to un uh comment this and see that we can actually uh not display this arrow so if i don't have the guard so i'm not getting anything but i'm not getting the error which is good so this guard actually now it works so let's go to the user's service and i want to actually actually return something from the function if i pass it so let's use this prisma to find the user by id and return it so let's say here const const user equals this dot prisma dot a user and we can say find unique because the id is going to be unique and here we say where where id and this should give me the user if i passed the off card so let's try now to actually login and to hit this route again and let's let's check if i having the user so let's say here return and i can say my user is going to be the user let's just say user doesn't matter so user and now we supposed to log in so let's go here the fields are correct so we're going to make a post request to off sign in because i want to have a cookie okay so now i have this cookie and what i need actually i need the id of the user so let's go to the prisma studio let me actually open it so okay so i need this user's id because i want to find the user by id how can i copy this this is the way so copy and let's go to postman and change it to get request and it's going to be users and the id let's hit send and of course now i'm getting the user back because i passed the off card because i have this cookie that i supplied and i provided a valid id here so i got back the user all right so basically what we have to do now is there is one more issue that we need to fix i wanted to make sure that the user that is logged in can get only his user so i cannot be logged in and get any user that i want by any id you know in my database so i want to make sure that only if i'm logged in as this user i can get only this user so now we're going to work on this part and we will finish with the project first of all to do this test i want to get to create another user so let's create a post request and it's going to be off sign up of sign up and actually i have to specify here a different email so let's say test two okay now i supposed to have two users let's check it in the prisma studio okay cool now i have two users and i want to test that only if i'm logged in as this user i can get only this user not the other user if i for example type manually his id so this is how we're going to do this first i want to go to the users controller and i want to get here the request and response from from this route so let's say here again let's specify here a request actually i need only the request so we can actually skip the response so let's say that i want to get here the request and let's go to user service and we can say like it's going to be request from express and basically now because i have this off guard you can see that if i type here request dot user you can see that actually the off guard is passing me the decoded values for my jwt so basically if i go to the strategy the user will have this payload with id and email so let's say here that this requested user this is going to be a const decoded user is going to be requested user and let me actually specify here that it's going to be s id string and email string ok so this is one thing another thing i wanted to do if uh if i for example supply a wrong route or something with on on the params and i don't find the user i want to return the error so if no user let's throw [Music] throw new not found exception not not founded exception okay so the last thing i want to check is only if this user id so the user that we found only if it has the same id as the decoded user that coming from the jwt payload then i want to show the user so let's say here if the user dot id is not equals to decoded user dot id and then i want to send a forbidden exception so let's throw flow new forbidden exception so now basically only if i am the user that that is logged in i can see only my details and the last thing i don't want to send the password of the user so i can do again this select and select all the fields that i want but i know that i want all the fields except the password so i can just say uh to short it i can say delete user dot password and then i can send the user so now let's see uh if i go to postman so let me actually i think i'm logged in yes i'm still logged in as uh as the test is test gmail.com so let's go to [Music] the get request and let's say here users and i need the id for this user so let's check it in the prisma studio right now the cookie that i'm logged in is for this user so let's take his id and try to get his info so users slash id and hit send and you can see that i don't have the password that is coming back which is good and i have the user details and now what we have to check is to try to get the other user so let's take his id and copy and now i'm going to change this out to the other user and hit send and you can see that i have a arrow with for free status and the message of forbidden we are finished with protecting this route and now only if a valid jwt and only if the jwt token belongs to the user that's trying to get it only then we will get the user all right guys to summarize things uh this was the authentication course that i created in the past and i recreated it with sjs i actually really enjoyed creating uh this uh off system with nesjs i think it's uh modern and much easier to do applications with that i haven't tried sjs in production yet and as i said of course i'm new to net js so if you have any uh comments to post about better best practices that i implemented here so just do it and i hope you enjoyed this video and if you have any uh requests to maybe extend this course and create some more complex stuff with this authentication so comment below and i hope you enjoyed the course and i will see on the next one thank you guys and bye
Info
Channel: Mike dev
Views: 26,855
Rating: undefined out of 5
Keywords:
Id: 4JyBeN69wq4
Channel Id: undefined
Length: 90min 50sec (5450 seconds)
Published: Thu May 26 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.