Part 1: Building Secure Applications: A Practical Guide to JWT and Passport in NestJS
Introduction Nearly all applications today require authentication, as security is a key business priority. So, authentication is the gatekeeper, ensuring only authorized users can access an applicatio

Etienne Maway
6 octobre 2024 · 7 min de lecture

Introduction
Nearly all applications today require authentication, as security is a key business priority. So, authentication is the gatekeeper, ensuring only authorized users can access an application’s resources and data. Whether you’re building a web app or an API, authentication solid practices are essential for security, protecting against unauthorized access and exploitation.
Without proper authentication, applications are vulnerable to attacks, leading to potential data breaches, legal issues, and even career consequences for developers. Mastering authentication is not just a security measure — it’s a professional necessity.
Overview of Authentication Strategies
NestJS offers various authentication strategies that developers can easily implement to secure applications:
- JWT (JSON Web Token) Authentication: A stateless method where users are authenticated using tokens included in headers.
- Local (Username/Password) Authentication: Verifies user credentials (username and password) using Passport.js.
- OAuth2: Enables social logins via providers like Google or Facebook.
- API Key-based Authentication: Commonly used for protecting API endpoints or service-to-service communication.
Let’s dive into two of the most common authentication methods — JWT Authentication and Local Strategy with Passport(the most used NestJs auth library). These approaches will help you grasp the authentication flow without much abstraction, as the goal is to provide you with a clear and practical understanding of the data flow.
1. JWT Authentication
JWT (JSON Web Token) is a widely used standard for securing API-based systems. It’s a compact, URL-safe token that represents claims between two parties — typically, a server and a client. JWT provides a way to authenticate users without relying on session storage, making it ideal for stateless applications, especially in modern web and mobile APIs.
The structure of a JWT consists of three parts:
- Header: Contains the token type (JWT) and the signing algorithm used.
- Payload: Holds the claims (e.g., user information, expiration time).
- Signature: Ensures that the token hasn’t been altered, using a secret key.
In a typical flow:
- The user logs in with credentials.
- The server verifies the credentials and sends back a JWT.
- The client stores the token (usually in local storage or cookies) and includes it in the Authorization header of subsequent API requests.
- The server validates the token on each request to ensure the user is authenticated.
1. Set Up the Environment
Start by creating a basic NestJS project and installing the required dependencies for JWT authentication.
Create the auth and users resources
Generate an Auth resource to house the authentication logic. You’ll also need a Users resource for handling user-related operations.
- nest generate resource <name>: Generates a resource with module, controller, and service.
- --no-spec: Skips the creation of test files.
By default, it will also skip generating CRUD-based endpoints unless you specifically enable it.
2. Code Implementation
In src folder, locate users/users.service.ts , paste this code:
The UsersService is responsible for managing user data in the application. It simulates fetching users from a database using an in-memory array of user objects. The service provides two methods:
- getByUsername(username: string): Fetches a user by their username.
- findAllUsers(): Returns a list of all users
Configure JWT in NestJS App
In auth/authModule.ts paste these lines of code:
The AuthModule configures JWTs library we installed in the App. It imports the UsersModule and configures the JwtModule to sign tokens with a secret loaded from the .env file, ensuring security.
Using the ConfigModule, the JWT secret can vary by environment, allowing different values for development, staging, and production. Tokens are signed with a 7-day expiration.
In auth/authService.ts paste this:
The AuthService handles user authentication, utilizing the UsersService for credential validation and the JwtService for generating JSON Web Tokens (JWTs).
Key components include:
- Login Method: Validates user credentials from a LoginDto. If valid, it returns a JWT, user ID, and username; otherwise, it throws an UnauthorizedException.
- User Validation: Checks if the user exists and verifies the password. If successful, it returns the user’s ID and username.
- Token Generation: Creates a JWT using the user’s ID and username as payload.
For enhanced security, it is essential to hash passwords before storing them in the database to protect user credentials.
Go to app.tsfile located in the root of your project, and register your modules:
With this setup, you’ve managed to authenticate the user successfully, allowing them to generate a token that provides secure access to services within the application.
2. Routes Protection: JWT Authorization
You’ve reached a level where you can restrict access to sensitive services. After the JWT token is issued, the client must provide it to access protected routes. The server verifies the token to grant access.
Remember, the token contains the user’s ID, username, and the server’s secret key, making signature verification straightforward. If the token expires, the request is rejected, requiring a new token to be generated. This is where your security measures come into play, ensuring only authorized users access sensitive resources.
Create a new folder and file in the auth folder, name it guards/auth.guard.ts and inside the file, paste this code:
The AuthGuard is a security feature in NestJS that checks if users are authorized to access certain routes using JWTs. This guard ensures that only authenticated users can access protected parts of your application.
How It Works:
JWT Verification: It uses the JwtService to verify the JWT provided in the Authorization header of incoming requests.
- The guard checks if the token is present. If not, no authorization access
- If the token is present, it tries to verify it. If verification fails, it again throws an UnauthorizedException.
- If the token is valid, the guard adds the user’s ID and username to the request, making it available for further processing.
In your controllers, for example in users.controller.ts , you can make use of guards like this:
The UsersController handles user-related requests in your NestJS application. It includes two endpoints that are protected by the AuthGuard, ensuring that only authenticated users can access them.
- The findAllUsers method retrieves all users.
- The getByUsername method allows users to fetch their own profile by username.
- @UseGuards(AuthGuard): This decorator ensures that the user must be authenticated before accessing this endpoint. You can use this decorator throughout the application on the endpoints you need access only to authenticated users.
This overview equips you with the essentials of authentication and access restriction in web development. You’ve implemented a JWT-based authentication system and secured routes with guards to ensure only authorized users access sensitive data.
In Part 2,
we’ll elevate our authentication strategy using Passport.js, introducing greater abstraction and flexibility for enhanced security.
Congratulations on reaching this stage and thank you for reading! Your dedication to these concepts will empower you to build robust, secure applications. Stay tuned for the next installment!