How to Create a NestJS App with Authentication
By: Paulo Henrique De Carvalho
Tags: Typescript, Nest, Backend Development, JavaScript, Node

Creating the application

It’s pretty easy to start a NestJS application using it’s CLI. We will start by installing it globally (I’ll be using yarn on this tutorial) and running the command to create the base application:

yarn global add @nestjs/cli

nest new project-name

The project is set and ready. Run the below command and open the http://localhost:3000 to see a “Hello World”:

yarn start:dev

Setting up a .env file

The next thing we have to do is setup the NestJS’s Config Module: This module is used to load your .env files and it has some nice features if you want to have multiple or dynamic configurations. The first step is to install it:

yarn add @nestjs/config

Now we can import it on our app.module.ts:

app.module.ts

We add the ConfigModule to the imports parameter array and we set its isGlobal property to true so this module is loaded on every other module (if you don’t set this, you’ll have to add the ConfigModule to the imports of every module where you have to use the .env information).

Connecting to the database

To access and connect with the database we’ll be using TypeORM (with MySQL) because NestJS has a nice integration with it. Let’s start by installing the required libraries:

yarn add @nestjs/typeorm typeorm mysql2

Now we will set our database information. I’ll be using Docker to run MySQL (you can check the first part of this tutorial to discover how to setup your own database with docker). Create a .env file on the project’s root folder and change the information as below:

.env

Let’s add the TypeOrmModule to our app.module.ts file:

app.module.ts

Here we created a entities array that we’ll use to add our entities and used the DB information from our .env file.

Creating users

So, let’s continue and create our users. Start by running the following command:

nest g resource users

# Select REST API

# Select to NOT generate CRUD entry points

The first time that we run this command it’ll install some libs using NPM. If you are using yarn, don’t forget to delete the package-lock.json and run yarn again.

A lot will going to happen after you run this. NestJS’s CLI will create a users folder with the following content:

users.controller.ts and users.constroller.spec.ts file

users.service.ts and users.service.spec.ts file

users.module.ts file

The specs files are test files and will be ignored for the rest of this tutorial (you can delete it if you want).

Let’s start by installing bcrypt to hash the user’s password:

yarn add bcryptjs

yarn add @types/bcryptjs -D

And now we create a user.entity.ts file inside the users folder:

user.entity.ts

We have to create our User class with the Entity() decorator and extend the BaseEntity. Then we add the id, email, password, createdAt and updatedAt fields and the hashPassword and validatePassword methods (don’t forget to add the BeforeInsert() decorator to the hashPassword method).

With our user entity ready, let’s create a DTO. The DTO is used to validate the data that we receive. Let’s first add the class-validator library to help us with the validation:

yarn add class-validator

And then we create a dto folder inside the users folder and add the create-user.dto.ts to it:

create-user.dto.ts

We’re going to use this DTO to make sure that we’ll receive a valid email and a password that is not empty. Let’s move on and edit the users.service.ts file:

users.service.ts

So, here we create the create, showById, findById and findByEmail methods. To create the user, we instantiate a user object with the data from our DTO and save it. Then we delete the password parameter from this user object and return it.

Now we just have to edit our users.controller.ts and add our User entity to the entities array on the app.module.ts file:

users.controller.ts

app.module.ts

Let’s start our application and create a user. Run the yarn start:dev command and then send a Post request with email and password to http://localhost:3000/users. I usually use Insomnia to send requests, but you can use whatever program you want (Postman is another great option):

The last thing we have to do here is export our User Service. Edit the users.service.ts file:

users.module.ts

Creating the authentication

Let’s start by creating the files that we’re going to need. Run NestJS’s CLI generate command:

nest g resource auth

# Select REST API

# Select to NOT generate CRUD entry points

We’re going to need some libraries to implement the authentication. Let’s install it:

yarn add @nestjs/passport @nestjs/jwt passport passport-jwt

yarn add @types/passport-jwt -D

Now we have to set some things up before doing the actual login. We have to add a JWT_SECRET to our .env file:

.env

We have to create a jwt.strategy.ts and a jwt-auth.guard.ts:

jwt.strategy.ts

jwt-auth.guard.ts

Then we have to add the UsersModule, PassportModule, JwtModule and the JwtStrategy to the AuthModule. Edit the auth.module.ts:

auth.module.ts

Let’s explain some stuff before moving on: The JwtStrategy is responsible for getting our token from the header of the request and checking if it’s valid. If it’s, then it’ll get the userId from the payload (we’ll add this userId to the payload on the AuthService). The JwtAuthGuard is the one that will call the JwtStrategy and is the class that we’ll use to secure our routes.

We’re almost there. Let’s create a auth-login.dto.ts (inside a dto folder) and edit our auth.service.ts file:

auth-login.dto.ts

auth.service.ts

We are getting the UsersService and the JwtService through our constructor, and adding the login and the validateUser methods. Now we just have to edit the auth.controller.ts:

We created the login and the test methods on the controller. The test method here is only to exemplify how to use the JwtAuthGuard that we created earlier (take a look at the UseGuards decorator).

Let’s try to login now: Send a Post request to http://localhost:3000/auth with a body with email and password:

Testing the auth login

It works! Let’s test if our JwtAuthGuard is working too: Let’s send a Get request with and without the token to http://localhost:3000/auth: