In this tutorial we'll build an authentication system using NestJS.
В этом руководстве
мы создадим систему аутентификации с помощью NestJS.
Before we build up
I would like to remind you
that this video is meant to be combined with other videos.
Прежде чем мы начнем.
Я хотел бы напомнить вам,
что это видео предназначено для объединения с другими видео.
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,
Я привожу несколько ссылок в описании этого видео.
Also make sure to check scalablescripts.com
Также обязательно проверьте scalablescripts.com
Часть 2 - Установка и запуск
Now let's build the app.
So let's start creating the project.
Теперь давайте создадим приложение.
Поэтому давайте начнем создавать проект.
Already did it.
So let's create the project
Уже сделал это.
Итак, давайте создадим проект
nest new I'll call it nest auth
nest new Я назову его nest auth
and a lot of lag here skip git
because git will color all our files
and i don't want that
и тут много лагов, пропустите git,
потому что git раскрасит все наши файлы,
а я не хочу это
I'll select npm
and let's wait till it's installed
so the files are generated
Я выберу npm
и подожду, пока он установится,
чтобы файлы сгенерировались.
I will open now it with my ide
I'm using phpstorm here
Я открою сейчас с помощью моей ide
Я использую здесб phpstorm
So you can use
visual studio code is the same
Так что вы можете использовать
тот же vscode
Now let's run the project.
Open the terminal and run npm run start dev
Сейчас давайте запустим проект.
Откройте терминал и запустите npm run start dev
So this will start the server
also it will watch our files for changes
Итак это запустит сервер,
а также будет следить за изменениями в наших файлах
So let's see the port
that he is running
Поэтому давайте посмотрим порт
на котором он работает
So it's running on port 3000 localhost port 3000
Итак он работает на 3000 порту. localhost port 3000
We can see here Hello world!
Мы видим здесь Hello world!
So it's working fine
Итак работает нормально
Часть 3 - Настройка и разработка
I'll make some changes now.
I'll remove the spec files here
Сейчас внесем некоторые изменения.
Я удалю spec здесь
I will change the port to 8000
because that is the port
the that the front end will use
Я изменю порт на 8000
потому что это порт,
который будет использоваться на фронтенде
Now it's complaining
about my styles here
Сейчас он жалуется
на мои стили здесь
and I will remove here the in .eslintrc
I will remove all these recommended styles
И я удалю здесь в файле .eslintrc
Я удалю все эти рекомендованные стили
You don't have to do that
if you follow the styles
Вам не нужно этого делать,
если вы следуете стилям
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