Перевод 8 (видео) - NestJS Authentication

Перевод 8

Видео: ссылка

Часть 1 - Введение

  1. In this tutorial
    we'll build an authentication system using NestJS.

    В этом руководстве
    мы создадим систему аутентификации с помощью NestJS.

  2. Before we build up
    I would like to remind you
    that this video is meant to be combined with other videos.

    Прежде чем мы начнем.
    Я хотел бы напомнить вам,
    что это видео предназначено для объединения с другими видео.

  3. So if you want to use Nest
    with Angular React NestJS Vue NextJS or Svelte
    I provided some links in the description of this video.

    Поэтому, если вы хотите использовать Nest
    с Angular React NestJS, Vue NextJS или Svelte,
    Я привожу несколько ссылок в описании этого видео.

  4. Also make sure to check scalablescripts.com

    Также обязательно проверьте scalablescripts.com

Часть 2 - Установка и запуск

  1. Now let's build the app.
    So let's start creating the project.

    Теперь давайте создадим приложение.
    Поэтому давайте начнем создавать проект.

  2. Already did it.
    So let's create the project

    Уже сделал это.
    Итак, давайте создадим проект

  3. nest new I'll call it nest auth

    nest new Я назову его nest auth

  4. and a lot of lag here skip git
    because git will color all our files
    and i don't want that

    и тут много лагов, пропустите git,
    потому что git раскрасит все наши файлы,
    а я не хочу это

  5. I'll select npm
    and let's wait till it's installed
    so the files are generated

    Я выберу npm
    и подожду, пока он установится,
    чтобы файлы сгенерировались.

  6. I will open now it with my ide I'm using phpstorm here

    Я открою сейчас с помощью моей ide
    Я использую здесб phpstorm

  7. So you can use
    visual studio code is the same

    Так что вы можете использовать
    тот же vscode

  8. Now let's run the project.
    Open the terminal and run
    npm run start dev

    Сейчас давайте запустим проект.
    Откройте терминал и запустите
    npm run start dev

  9. So this will start the server
    also it will watch our files for changes

    Итак это запустит сервер,
    а также будет следить за изменениями в наших файлах

  10. So let's see the port
    that he is running

    Поэтому давайте посмотрим порт
    на котором он работает

  11. So it's running on port 3000
    localhost port 3000

    Итак он работает на 3000 порту.
    localhost port 3000

  12. We can see here
    Hello world!

    Мы видим здесь
    Hello world!

  13. So it's working fine

    Итак работает нормально

Часть 3 - Настройка и разработка

  1. I'll make some changes now.
    I'll remove the spec files here

    Сейчас внесем некоторые изменения.
    Я удалю spec здесь

  2. I will change the port to 8000
    because that is the port
    the that the front end will use

    Я изменю порт на 8000
    потому что это порт,
    который будет использоваться на фронтенде

  3. Now it's complaining
    about my styles here

    Сейчас он жалуется
    на мои стили здесь

  4. and I will remove here the in .eslintrc
    I will remove all these recommended styles

    И я удалю здесь в файле .eslintrc
    Я удалю все эти рекомендованные стили

  5. You don't have to do that
    if you follow the styles

    Вам не нужно этого делать,
    если вы следуете стилям

  6. I format it differently so
    this is my preference also
    is not required

    Я форматирую по-другому. now let's restart the server because we changed our port and now we will listen to port 8000 so it's working the same now this message we get it from up controller or where we have a get method get hello and this calls an app service here that this service will return hello world here so this is our main controller and service and app model will wrap them all now we want to connect with the database already connected to my local database which is an empty schema if you don't have phpstorm installed you can use mysql workbench now let's go to the next js documentation and search here type orm so this is not the page this warning we should click here so this is the right page for us and let's install it this is the command i will open the terminal and install this so let's wait till it's completed and after it's completed here in the imports we'll add type or m module so we need to import typo model from net js type or m we need to add four root here actually we can copy this i'll copy this and i will add it here so the connection is mysql host localhost port 3306 username root and password is root root database youtube nest out so these are my credentials and you should use your own credentials now we need to add an entity so we can populate the database so let's create here an entity user entity and let's export class user here we need to make this an entity and the inside entity is the name of the table i'll name it users so this will be the name of the table and this will map the table values so this 11 id is a number a name as a string email as a string and password as a string so these are the columns that the table will have and we have to add a decorator for all of them so this is the primary column so we need to import that from typorm also this is just a column and these are also columns but for the email we have to make it unique so to make a unique column we have to add it like this so this is our user entity and now we have to add it to our app module.ts we have to add user here so i added user entity and when i save it will create the table in our database let's see so we have users here with all the feeds that we added also the email is unique so we added everything that we need now let's try to create the register so i will remove this function and add another function here yeah i will make it asynchronous and i will call it register and this function needs a post request to register also so let's import also post in sjs common here also i want to add an api as a prefix here but there is a better way since api prefix will be added for every for every endpoint we can add it here directly so api here and this register function will be aps slash register now when we send the request we'll send the body so the body will be the data that we will send along the request so there are two ways to get the data from the body one is like this so every data will be stored in this variable and the other one is getting each data individually like this body name name as a string body email email as a string embody password password as a string so there are multiple ways to do it i will do it like this because i won't add validations but it depends on your app which one is better for you so now we got all the variables so we have to create a service in order to register our user i won't create a service because we have app service here and uh i will remove this get hello function so to make this service work first we have to add the constructor here and inside we'll add private so before private we'll add an inject repository decorator and inside we'll add our entity so user entity here so we will inject a repository and this is private read-only user repository will be a type of repository of user like this now that we injected this we have a lot of functions that we can use to our advantage so the first one is reducer and this time we will pass the data here so let's pass the name or i will get the data as any here and we want to return the creation of that user so this user repository save the data just like this i'll change the name here not register i will make it better create and this will return a promise of user like this so we created our first function and now let's use it to our app controller before using it we have to hash the password so to ask a password we have to install first bcrypt so in the next js documentation we have hashing encryption and hashing in security let's install bcrypt install it and also install the typescript version so let's install this also and we need to import it like this i'll copy this and i will import it here on top now let's use bcrypt we'll create here a variable hashed password will be equal to weight decrypt hash will pass the password and we need the salt rounds i'll put 12 doesn't matter and we asked our password now we can register our user so we can return here this app service create and we will pass here the name email and the password but we should do it like this because we change the name so these two variables have the same key and the value but this should change now we have to test this endpoint but to test it you have to install first postman i already did it so i will open it and now let's send the request a post request to http localhost port 8000 slash api slash register now click the body and we will send some json so we need to send a name i will name it a email ata.com and the password a so let's send this request so we have a error let's see what is the error it seems that we have a problem with the user repository so it's not knowing this user repository so we can do it like this now we'll add typewirem module here for feature and we will pass the entity inside which is our user so this will now we don't have any problem this will add the user repository to the app model so this is just for configuring the com the connection for the database and this is for configuring the user repository so it will add the functions to query our user with this let's send the request again and we have an internal server error let's see again the error field id doesn't have a default value so probably i made a mistake in the user entity so i know the error i made a mistake here this is not a primary column but is a primary generated column so this was my mistake it it can be confusing sometimes because the name is similar primary column it means that this field is a primary key but it doesn't generate the primary key so we have to generate it and primary generated column will let it to mysql to generate that primary key so with this let's hope now everything works and indeed it does so we registered our user since we returned the id of one so this was the registration now let's add the login so add here async login and we need to post here to login the login will have an email and a password so i'll copy it from here and what do we want to do now first we have to get the user by the email so we will go to our app service and we will add the function find one and i will pass a condition here as any and we will return this user repository find one will pass the condition like this and this will return a promise of user so we created this functional so we can use it for up controller and now the user will be equal to await this app service find one will will pass the email here and we are done so i should have renamed this app service to user service but it doesn't matter so normally the service that gets the users should be named user service so we got the user but let's add some validations if the user is not set then we will throw new bad request exception user or invalid credentials so we should not return the error that tells the user that it's the email or the password so this is more secure like this so if we go here it means that the user is not found now if we pass here it means that the user is found now we have to check the password so to check the password we will call bcrypt again so i'll make a condition here again here if a wait be crypt compare the password with the user password like this so if i will add an exclamation point here if this is not the same then we have another errors which i will throw the same error so both these errors are the same and the user won't know which is the problem the email or the password and after we pass here for the moment just return the user and let's see it on the browser so i'll copy this send a post request to login and we'll send some json email ata.com and the password is a now i'll write the wrong email and we have invalid credentials the same will apply if i change the password again here so it is the same if everything is correct then we return our user we have to generate a jwt token to return it to the front end so go to the nest js documentation and in security authentication go to jwt functionality and install this packages so let's install it here we'll install password jwt and i will install it here so this is a typescript version so now that we got it we have to inject it like the jwts service so let's inject it here so we will inject now private jwt service jwt service and now we have to sign in a token so we have to generate a token and to do it is very easy i'll create jwt here which is equal to await this jwt service sign async and we'll pass the data that we want to encode and i will send only the id with of the user so that's it so for the moment i will return the jwt now and let's see it on the browser on the postman again i forgot to add the jwt in the model here so we'll add the jwt model we have to register and we will pass some data some data the first one is a secret so this is a secret value that we need to encode our jwt so to encode the jwt uh the secret i will just write it secret here but usually it should be stored in an emv file it should not be stored like i did but i will keep it simple so the next parameter that we need assign options and here we'll add the expires in how much time do you want the token to stay so i will make it one day so the token will be alive in one day let's send the request again now and we got a jwt so everything is successful now the last change is we want to store this jwt in a cookie which is http only so let's do it now we will add here the response so re response is short wrist like this response as a response and we should manually import the response from express so import response from express here this response will have also another property which is pass through to true because we want the cookie to send it to the front end and the only way to do it is to add this pass through to true so response here cookie let's create it so the name will be jwt the value will be jwt and we will add an option which is http only to true this means that the frontend won't be able to access this jwt only the backend will use that jwt and now we don't want to return the gwd we'll just return a message success and that's it so let's send the request again we get the message success and we got a cookie here as we can see it is http only and now we have to use this cookie to retrieve our logged in user before doing that we have to go to our mind main.ts and here we need to add some configuration because it's not enough what we added about the cookies we have to add here up enable course and inside we need to add credentials to true so in order for the front end to get the credentials which means the cookie we have to add this pass through and we have to add the credentials to true here also we need to add the origin so i'll put one origin here which is a http localhost and here we need to po you need to put the port of your front end up so i have multiple front ends so 3000 is for react 8080 is for view and 4200 is for angular you just pick whatever works for you i'll pick 8080 it doesn't matter and now with this we completed the login now let's add the authenticated user so let's create the function user and we need to add here a method which is get user and to get the user we have to get the cookie first and to get the cookie we have to get it from the request so we will add here the request request is the request also we need to import this request from express so i'll add it here request so we got the request and the cookie will we will get it cookie is equal to request cookies jwd but this won't work so i will show you so let's return the cookie for the moment and let's copy this url paste it here get the user send request and the one thing to mention that the cookies will be preserved if we open new tabs the cookies will be preserved in every request and we got an error because we cannot parse a cookie like this we have to install another package and this package is cookie parser so go to techniques cookies and copy this cookie parser here copy also the typescript version and let's go to our main.es again here and use up use cookie parser like this also import the cookie parser here so with this let's send the request again i guess i have to import a cookie parser differently so import all s cookie parser like this send the request and now we go to the jw team so is the same as this value now we have to verify it and to get our logged in user so the cookie is retrieved now we have to get the data which is equal to await this jwt service verify a sync and we'll pass the cookie here so let's return what this data returns send request and we can see it returns an id an expiration etc so let's uh make the condition so i'll wrap this with a try catch so i'll use it like this once we have an error here we have to return we will throw an exception unauthorized exception so if an error happens we return unauthorized also if the data is invalid we will return the same exception actually when we throw an exception here it will catch it with a try catch and throw the same exception again so i will we will keep it like this so it is the same it doesn't matter and after we go here it means that we successfully retrieved everything and we have to query the user now so let's get the user which is equal to wait this up service find one and we will find the user by the id which is data id and in the end will return the user so let's send a request and we successfully got the user based on the cookie so now let's remove this password because i don't like returning the password of the user even though they cannot decode it it's not a good practice to return the password so what i will do right now is i will deconstruct the password and the uh i will call it response or result doesn't matter is equal to the user i forgot to add cons here and in the end we'll return the result so we will remove the password from the user and this will return this response i'll do the same for the register since we return also the password here so we will get the user again here which is equal to weight this and i'll copy this where is it and i'll paste it here so the password is removed so we have it's confusing with this password here so to remove it this way we have to use a delete user password and let's return the user like this so let's register another user to see if this works send a request and as we can see the password is not returned so we got the authenticated user and now let's add the last part which is logout so sync logout this will be a post request to log out we need to pass here again the response so copy from this we need also the passthrough to true and what do we want to do when we log out is really simple we just want to clear the cookie so response clear cookie jwd and that's it so let's return a message success so this is our logout function and i will copy this paste it here log out and we'll send a post request now we have the cookie here as we can see let's send the post request to the logout and we get message success and we don't have a cookie here and if we get the user we will get no cookie here and we'll get unauthorized so this is how logout works we can log in again here and we can get the user so this was our authentication i hope you like it and if you did please share and subscribe thank you