In this blog series, we’ll explore how to set up user creation and authentication in a NestJS application with MongoDB as our database. Our goal is to build a robust back-end that includes user creation, login, and basic authentication using JWT. We’ll be covering the folder structure, code organization, and implementation step-by-step.

In this application, users log in using their email and password. After logging in, the server creates two types of JSON Web Tokens (JWT): an access token and a refresh token
 
  • The access token is valid for 1 hour and is used to verify a user's authentication for subsequent requests. Users include this token in the authorization header as a bearer token when accessing protected routes.

 

  • The refresh token has a longer validity period of 30 days. It allows users to obtain a new access token when the original one expires, which enhances both security and usability. With the refresh token, users can stay logged in without needing to enter their credentials repeatedly. Additionally, the refresh token can be used to reset passwords if necessary. 
 
By using both tokens, we create a secure and user-friendly authentication process, ensuring that only authorized users can access protected resources while effectively managing session expiration.
 

By the end of this series, you'll have a working authentication system that can be further extended with more complex features.

 

 

What We’ll Do

 
In Part 1, we’ll focus on:
  1. Setting up the initial project structure.
  2. Creating modules and organizing code for user and authentication logic.
 

Folder Structure

Here’s the folder structure of our project (Part - 1):

This structure organizes our code by features, which keeps the project modular and easy to maintain.

 

Dependencies

Here’s a list of the dependencies and why they are used:

 

@nestjs/mongoose: This package provides decorators and utilities to integrate Mongoose with NestJS, allowing you to define and manage MongoDB schemas in a structured and type-safe way.

mongoose: Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. It simplifies MongoDB interactions by providing schema-based solutions to model data and perform CRUD operations.

class-validator: This library is used to validate objects based on decorators in DTO (Data Transfer Object) classes. It ensures that incoming data adheres to specific validation rules, helping maintain data integrity.

class-transformer: This library works alongside class-validator to transform and serialize/deserialize objects. It allows you to control how incoming JSON data is mapped to TypeScript classes, enhancing data handling in NestJS.

bcrypt: Bcrypt is a library used for hashing passwords. It provides a secure way to hash and compare passwords, helping to protect sensitive user data.

uuid: This package generates universally unique identifiers (UUIDs), which are often used for creating unique IDs for records. In applications, UUIDs are helpful for creating unique keys without relying on sequential numbers, enhancing security and scalability.

 

Code Explanation

 

.env

main.ts

The line app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true })); enables global validation to automatically remove unwanted properties (whitelist) and transform request data types to match the expected DTOs in the NestJS application.

 

app.module.ts

This is the root module of our application. Here, we configure the modules, including UserModule, and connect to MongoDB using environment variables.
 
 
User Module
The UserModule manages user-related operations. It includes UserController, UserService, and MongoDB schema integration using Mongoose.
 
user.module.ts
Sets up UserController and UserService, and defines the UserSchema.

 

base.entity.ts

Defines the base structure for MongoDB entities, including properties like a unique id (UUID), createdBy, and updatedBy, which are common to all entities in the application.

 

user.schema.ts

Defines the structure of the user documents in MongoDB.

 

user.controller.ts

Defines the user-related API endpoints, including a POST endpoint for creating a new user by accepting data in the CreateUserDto format and passing it to the UserService for processing.

 

 

user.service.ts

Implements the main user logic, including creating users and hashing passwords with bcrypt.

 

 

user.dto.ts

 

create-user.dto.ts

Extends UserDto to include a role property, validated to ensure it matches one of the values in the UserRole enum, specifying the user's role.

 

 

user-role.ts

 

user-status.ts

Conclusion

In Part 1, we set up our NestJS project structure and walked through the initial code setup for user creation. This setup lays the foundation for implementing authentication in the next part, where we’ll handle login, JWT-based authentication, and securing routes.