WEBVTT

00:00.080 --> 00:00.410
Okay.

00:00.410 --> 00:04.340
So we're ready to add our new authentication microservice.

00:04.340 --> 00:11.120
We're just going to deal with all authentication and identity access management related functionality

00:11.120 --> 00:11.690
in our app.

00:11.690 --> 00:16.280
Let's go ahead and create this new app by going back to the CLI.

00:16.280 --> 00:21.800
And we'll use the nest CLI and run Nest Generate app auth.

00:21.800 --> 00:28.010
So this is going to go ahead with this normal process of creating a new application by creating a new

00:28.010 --> 00:34.730
app's auth directory, updating our TS config and our package.json as well as the nest cli dot JSON.

00:34.730 --> 00:39.320
We can of course go to the nest CLI and see the new auth application that was added.

00:39.320 --> 00:45.560
So our first step in implementing authentication in our auth microservice is going to be to actually

00:45.560 --> 00:47.570
implement the idea of users.

00:47.570 --> 00:54.890
So we want this microservice to be able to create new users and authenticate or log in against those

00:54.890 --> 00:57.830
users and obtain a JSON web token.

00:57.830 --> 00:59.780
So the user will provide their credentials.

00:59.780 --> 01:05.810
We'll give them back that token to authenticate them, which is a very common authentication mechanism.

01:05.900 --> 01:11.480
And we can make use of this authentication mechanism in all of our different microservices that will

01:11.480 --> 01:12.920
implement authentication.

01:12.920 --> 01:14.600
So let's go ahead and get started.

01:14.600 --> 01:20.480
Back in our terminal here we're going to generate a module called users.

01:20.480 --> 01:22.910
And then it should ask us which project we want to use.

01:22.910 --> 01:24.740
In this case we can say auth.

01:24.740 --> 01:30.590
So we're also going to use the CLI to generate a controller here so that we can actually create new

01:30.590 --> 01:32.780
users over HTTP.

01:32.780 --> 01:39.230
And we'll select the auth project here you can see it create the new users controller and update the

01:39.230 --> 01:40.430
users module.

01:40.430 --> 01:46.370
So now if we go back to our auth module we can see we're importing the users module which is inside

01:46.370 --> 01:48.320
this new users directory.

01:48.320 --> 01:52.010
And the users module here has the user controller.

01:52.010 --> 01:58.790
And this has the boilerplate users controller where we will specify a new post route here from Nestjs

01:58.790 --> 01:59.480
common.

01:59.480 --> 02:03.170
And this will be our async create user route.

02:03.170 --> 02:08.720
So we're going to create the DTO for the create user route I'll create a new folder in the users directory

02:08.720 --> 02:15.530
called DTO and we will create a create user dot DTO in this DTO directory.

02:15.530 --> 02:22.100
So we're going to go ahead and export a class called Create User DTO here which will have two properties

02:22.100 --> 02:27.320
an email of type string and a password of type string which we will need to create a new user.

02:27.320 --> 02:32.630
So we're going to take advantage of class validator in this authentication microservice as well to validate

02:32.630 --> 02:34.850
all incoming input from users.

02:34.850 --> 02:41.120
So let's go ahead and use the is email decorator here from class validator which will check if this

02:41.120 --> 02:42.890
string is a valid email.

02:42.890 --> 02:49.340
And then for password we're going to use the is strong password decorator here to specify that we want

02:49.340 --> 02:50.810
a strong password.

02:50.810 --> 02:54.590
And it will also check to see if the value is a valid string.

02:54.590 --> 03:02.480
So now back in the users controller let's go ahead and add the body annotation here from Nestjs common

03:02.480 --> 03:08.480
where we'll specify the create user DTO of type create user DTO.

03:08.480 --> 03:17.390
And in here we're going to return this dot user service which doesn't exist yet and call create and

03:17.390 --> 03:20.690
pass in that create user DTO.

03:20.690 --> 03:23.870
So of course there is no user service right now.

03:23.870 --> 03:30.680
We can go ahead and generate it with the CLI swapping controller out here with service to generate a

03:30.680 --> 03:34.130
user service underneath the auth project.

03:34.220 --> 03:36.830
So now we have a user service.

03:36.830 --> 03:44.390
We'll go into our constructor here and actually inject the newly created users service of type users

03:44.390 --> 03:45.320
service.

03:45.320 --> 03:48.050
So this method does not exist on the service yet.

03:48.050 --> 03:50.750
You can see it's newly created in this users directory.

03:50.750 --> 03:58.610
Let's go inside of here and add our async create method here which takes the create user DTO of type

03:58.610 --> 04:00.740
create user DTO.

04:00.740 --> 04:06.320
And inside of here, of course, we want to reach out to our repository and actually persist this user.

04:06.320 --> 04:12.230
Now to do this we will manually create a users repository and we'll create a new file called users dot

04:12.230 --> 04:14.480
repository dot TS.

04:14.480 --> 04:19.940
And of course like our other repositories, this will be an injectable class so that we can inject it.

04:19.940 --> 04:23.840
And we'll export a class here called Users Repository.

04:23.840 --> 04:29.270
And as you might have guessed, this will extend our abstract repository.

04:29.270 --> 04:32.210
And you can see here it's trying to import it directly here.

04:32.210 --> 04:35.690
Let's change this out for add app slash common.

04:35.690 --> 04:41.060
Now just as we did before in the reservation service we need to supply the abstract repository with

04:41.060 --> 04:41.810
the schema.

04:41.810 --> 04:50.120
So now in the users directory we can create a new models folder where we'll include our user dot schema

04:50.120 --> 04:51.380
dot ts.

04:51.410 --> 04:58.760
Now we can make this super easy by going into our existing reservation schema and copying everything

04:58.760 --> 04:59.660
over and.

04:59.890 --> 05:05.860
Hasting into the new user schema so everything will stay the same of course, except for the naming

05:05.860 --> 05:07.570
conventions and properties.

05:07.600 --> 05:14.380
The reservation document here will be changed to the user document, and the reservation schema will

05:14.380 --> 05:19.750
be a user schema and this will use the user document.

05:19.780 --> 05:25.960
Now we will specify the two properties that exist on the user the email of type string.

05:25.960 --> 05:28.960
And we'll of course decorate this with the prop decorator.

05:28.960 --> 05:34.630
And then we have the other property here the password of type string.

05:34.630 --> 05:42.550
So now back in the users repository we can actually supply the newly created user document document

05:42.550 --> 05:44.890
here from our models directory.

05:44.890 --> 05:52.330
And just like we did in the previous repository, we're going to create that read only logger here,

05:52.330 --> 05:56.320
which will be a new logger from Nestjs Common directly.

05:56.320 --> 06:01.690
And we'll supply the user's repository dot name here for some context.

06:01.720 --> 06:07.060
Now, just like we did in the other repository, we're going to have a constructor that will use the

06:07.060 --> 06:10.870
inject model decorator from Nestjs mongoose.

06:10.870 --> 06:14.860
And inside of the inject model, we're going to pass in the injection token that we're going to set

06:14.860 --> 06:15.640
up later.

06:15.640 --> 06:20.620
In this case it will be the user document dot name itself here.

06:20.620 --> 06:26.230
So this will be the user model that will be of type model from mongoose.

06:26.230 --> 06:29.770
And the type that we provide here will be the user document.

06:29.770 --> 06:35.740
So all we have to do now is pass this up to our abstract repository by calling super and pass that user

06:35.740 --> 06:36.190
model.

06:36.190 --> 06:42.910
So now we can reap the benefits of this abstract repository by creating a constructor in the user service

06:42.910 --> 06:48.730
that injects the user's repository of type user's repository.

06:48.730 --> 06:55.210
And then in create, we will simply call this dot users repository dot create and pass in that DTO.

06:55.210 --> 06:57.760
So now it's time to wire everything up.

06:57.760 --> 07:00.880
We're going to go inside of the users module.

07:00.880 --> 07:07.180
And since we're instantiating a new repository and making use of the database connection, we of course

07:07.180 --> 07:11.770
need to import the database module as well as set up our user schema.

07:11.770 --> 07:18.880
So let's make this easy by going to the reservations module and importing the database modules here.

07:18.880 --> 07:22.480
And we'll copy them to the users module.

07:22.480 --> 07:28.270
So we'll add an imports array here and paste in the database module imports.

07:28.270 --> 07:32.560
We will import the database module up top from app slash common.

07:32.560 --> 07:38.620
And we will change the reservation document out for the user document for the injection token.

07:38.620 --> 07:43.690
And the schema itself will be a user schema from the models user schema.

07:43.720 --> 07:51.250
Last but not least, don't forget to actually add the users repository that we've created to our providers

07:51.250 --> 07:51.640
array.

07:51.640 --> 07:53.830
So Nestjs is aware of it.

07:53.830 --> 07:58.780
So now back in our terminal, we can just make sure that everything is wired up correctly by running

07:58.930 --> 08:05.170
npm start dev and then passing in the auth project here to make sure we start the auth app.

08:05.170 --> 08:09.940
And this will not use docker compose, this is just using our local machine.

08:09.940 --> 08:15.550
So of course we're not going to be able to connect to the MongoDB container that's running because we

08:15.550 --> 08:17.410
aren't currently running it in Docker.

08:17.410 --> 08:21.880
That's going to be our next step to actually dockerize the authentication app.

08:21.880 --> 08:26.290
So we can continue to compile it alongside our other microservices.

08:26.290 --> 08:31.600
Let's go ahead and dockerize our app next so that we can test out our new user creation functionality.

08:31.600 --> 08:31.900
Okay.

08:31.900 --> 08:36.520
So we're ready to start dockerizing our authentication microservice.

08:36.520 --> 08:41.020
And so the easiest way to do this is we're going to go into our auth directory.

08:41.020 --> 08:47.590
And we're actually going to create a new Docker file in here just like we did reservations project.

08:47.590 --> 08:53.770
And to speed things up we can go ahead and just copy over our existing Docker file for the reservations

08:53.770 --> 08:56.200
project and paste that in here.

08:56.200 --> 09:01.810
The only change we're going to have to make is the command to start the node process.

09:01.810 --> 09:07.090
Instead of going into the reservations folder, we're now going to go inside of the auth folder and

09:07.090 --> 09:09.160
start the Main.ts that way.

09:09.160 --> 09:15.730
Then we can open up our Docker compose here, and let's add a new service to our services list the auth

09:15.730 --> 09:19.480
service here, where we will have a build section.

09:19.480 --> 09:25.510
Just like the reservations service, we have the context at the root where we're currently at.

09:25.510 --> 09:32.680
We are going to copy over the docker file from dot slash apps, slash auth slash docker file.

09:32.680 --> 09:36.490
And of course our target here will still be development.

09:36.640 --> 09:43.600
Let's go ahead and copy over the rest of the configuration from the reservation service and paste it

09:43.600 --> 09:44.050
in here.

09:44.050 --> 09:49.360
And we're going to have to change the start command here to start the auth project.

09:49.570 --> 09:53.320
And we're also going to change the port we're running on to be on 3001.

09:53.320 --> 09:58.570
So we don't conflict with the reservation service which will be running on port 3000.

09:58.570 --> 09:59.440
So let's make.

09:59.570 --> 10:04.700
A similar change inside of the auth service will open the main.ts and change the port.

10:04.700 --> 10:07.190
We're listening on to 3001 now.

10:07.190 --> 10:12.560
Back in the terminal, we can go ahead and run docker compose up so we can test things out.

10:12.560 --> 10:13.880
Back in postman.

10:13.880 --> 10:16.820
I'm going to change the port here to 3001.

10:16.820 --> 10:20.090
So we point at the authentication service.

10:20.090 --> 10:24.260
We'll launch a Post request at slash users.

10:24.260 --> 10:28.970
And we'll edit our body here to include an email.

10:29.510 --> 10:34.460
And I'll just use a test email here test at example.com.

10:34.460 --> 10:37.610
And we'll have that strong password as well.

10:37.610 --> 10:42.440
So I'll add a random strong password 123.

10:42.440 --> 10:48.200
And then we can send this post request off to the server and see we get that 201 created back.

10:48.200 --> 10:51.020
Which means we have successfully created the user.

10:51.020 --> 10:56.090
And we don't have a way to get the user currently, but we will soon be able to log in with this newly

10:56.090 --> 10:57.050
created user.

10:57.050 --> 11:04.040
However, if we go ahead and try removing the email here and sending this, we can still see that the

11:04.040 --> 11:05.210
request succeeds.

11:05.210 --> 11:10.760
And that's because we haven't set up class validator or Nest Pinot logger in our auth service.

11:10.760 --> 11:16.640
So let's go ahead and do that now back in our main.ts in the auth service, we'll do the same thing

11:16.640 --> 11:22.700
we did in the reservation service where we attach the validation pipe to a global pipe.

11:22.700 --> 11:28.760
And we also used the nest peanut logger here to get the Nest peanut logger working properly.

11:28.760 --> 11:34.040
So let's copy both of these and paste them into our Main.ts for the auth service here.

11:34.340 --> 11:39.590
We'll of course update our imports here as well, and make sure we import the logger from Nestjs piano.

11:39.590 --> 11:46.160
And then we're going to go into our auth dot module and make sure we import the logger module.

11:46.160 --> 11:50.930
And make sure we import the logger module from app slash common here.

11:50.930 --> 11:56.660
So now if we go back to the terminal we can see sleeper auth here is using the nest logger.

11:56.660 --> 11:58.730
And we successfully started up.

11:58.730 --> 12:02.060
And now if I go back to postman I send this request off.

12:02.060 --> 12:06.260
Of course we get two validation errors saying that the email does not exist.

12:06.260 --> 12:11.210
So I'll change my password here as well to use a capital letter and an exclamation mark.

12:11.210 --> 12:14.600
And now we can see our payload succeeds.

12:14.600 --> 12:19.430
So we're finally ready to actually start implementing our authentication with JWT.

12:19.640 --> 12:24.710
Now that we have the ability to create new users and take advantage of the popular authorization library

12:24.710 --> 12:30.800
passport that integrates very nicely with Nestjs to implement this JWT auth, let's go ahead and do

12:30.800 --> 12:31.730
that next.
