Nowadays, building an API without authentication is no different than having a "home without a door" and can easily be "questioned". I have struggled with messy routes, confusing error handling, and especially API security. This article is my real-life experience, guiding you Express.js to create a complete REST API from A-Z with Node.js and MongoDB. In particular, I will focus on integrating JWT (JSON Web Token) authentication in the most methodical, safe and easy-to-maintain manner according to 2026 standards.
The most important part: Building the foundation and CRUD framework for REST API
Building a RESTful Express.js API with authentication requires a solid foundation. The CRUD framework is the heart of any backend service, helping to manage data flows smoothly and effectively.
Prepare the "soil and bricks" - Set up the Node.js environment and initialize the Express.js project
Để thiết lập dự án Node.js, bạn cần cài đặt môi trường, khởi tạo package.json bằng npm init và cài đặt các package cơ bản như express, mongoose, dotenv.
Cách tạo REST API với Express.js bắt đầu từ những dòng lệnh đơn giản nhất. Đầu tiên, bạn tạo một thư mục trống và mở terminal lên. Chạy lệnh npm init -y để tạo file cấu hình mặc định. Sau đó, chúng ta cài đặt các "vũ khí" cần thiết bằng lệnh: npm install express mongoose dotenv cors jsonwebtoken bcryptjs.
Mỗi package đều có nhiệm vụ riêng. Express lo phần khung server, Mongoose giao tiếp database, Dotenv bảo mật biến môi trường. Để quá trình code nhàn hơn, đừng quên cài Nodemon (phát triển) bằng lệnh npm install -D nodemon. Công cụ này giúp server tự khởi động lại mỗi khi bạn lưu file, tiết kiệm vô số thời gian gõ lệnh thủ công. Đối với những bạn mới chuyển sang làm backend, việc nắm vững nền tảng là rất cần thiết. Bạn có thể tham khảo bài viết Học Node.js từ đầu cho backend developer để củng cố kiến thức trước khi đi sâu hơn.
Many of you often ask at Pham Hai which language to choose as a startup backend. If you are wondering, the review PHP vs Node.js backend comparison 2026 will give you the most objective perspective on performance and current market trends.
Build the "skeleton" with a scientific REST API Express.js project folder structure (Models, Views, Controllers)
The 2026 standard REST API Express.js project structure often applies the MVC model, clearly separating Routes, Controllers and Models for easy expansion and maintenance.
Một dự án gom tất cả code vào file server.js là một thảm họa bảo trì thực sự. Mình khuyên bạn nên chia Cấu trúc thư mục dự án thành các phần riêng biệt ngay từ ngày đầu tiên. Cụ thể, thư mục routes sẽ chứa các Routes (Định tuyến API) làm nhiệm vụ điều hướng. Thư mục controllers chứa logic xử lý (Controller) quyết định API sẽ làm gì. Thư mục models chứa Model (Mô hình dữ liệu) định nghĩa cấu trúc dữ liệu.
- routes/: Nơi định nghĩa các đường dẫn như
/api/users. - controllers/: Nơi chứa các hàm như
createUser,getUser. - models/: Nơi chứa file
User.jsđịnh nghĩa database schema. - middlewares/: Nơi chứa các trạm kiểm soát xác thực.
This division strictly follows REST principles, helping to keep the code neat and understandable to anyone who looks at it. As the project grows, you can easily integrate more TypeScript (in Express.js) without being overwhelmed by code. Of course, to write logic smoothly in controllers, the language foundation is core. If you feel unsure, you should review the tutorial Learn basic JavaScript for beginners 2026.
Connecting to the "repository" - Instructions for creating an Express.js API that connects MongoDB using Mongoose
To connect to MongoDB, we use the Mongoose library - a powerful ODM that helps define Schema and interact with the database easily via the URI connection string.
Hướng dẫn tạo API Express.js kết nối MongoDB không thể thiếu Mongoose. Đây là cầu nối tuyệt vời giúp Node.js nói chuyện với MongoDB một cách trơn tru. Bạn tạo file db.js và sử dụng hàm mongoose.connect() truyền vào chuỗi URI của database.
Việc định nghĩa Schema MongoDB giúp kiểm soát chặt chẽ kiểu dữ liệu đầu vào, tránh việc lưu rác vào database. Ví dụ, schema của User sẽ quy định email là kiểu string, bắt buộc phải có và phải là duy nhất (unique). Quá trình kết nối database hay truy vấn dữ liệu luôn mất một khoảng thời gian chờ đợi phản hồi từ server. Do đó, việc hiểu rõ Async Await Promise JavaScript dễ hiểu là điều kiện bắt buộc để viết code xử lý bất đồng bộ, tránh tình trạng server bị treo cứng chờ database.
Creating the first "bricks" - Node.js Express.js MongoDB API CRUD Guide (Create, Read, Update, Delete)
CRUD operations in Express.js are mapped with HTTP methods (GET, POST, PUT, DELETE) to create, read, update and delete data on MongoDB correctly.
This is the core and most interesting part of this Node.js Express.js MongoDB API CRUD Tutorial. Express.js creates an extremely logical step-by-step API. Each operation will correspond to a specific API Endpoint. Below is a table summarizing how to map methods:
| Operation (CRUD) | HTTP Methods | Main mission |
|---|---|---|
| Create | POST | Create a new record (for example, create a new user) |
| Read | GET | Get a list or details of a record |
| Update / Delete | PUT / DELETE | Fully update or delete records by ID |
When building these endpoints, always remember to return standard HTTP status codes (like 200 OK for success, 201 Created for new creation, 404 Not Found for no data). This API design thinking applies to all programming languages. If you're curious how other frameworks handle this architecture, you can see Build a REST API with PHP Laravel to see interesting similarities between backend technologies.
Enhanced security: Integrate JWT "lockdown" for API
Express.js API security is a vital factor that cannot be overlooked. Proper integration of JWT (JSON Web Token) and Authentication helps protect user data from dangerous cyber attacks.
What is JWT? Why is Express.js the optimal choice for API security?
JWT (JSON Web Token) is a stateless authentication standard, helping the server not need to store sessions, thereby enhancing API scalability and security.
With Stateless API designs (stateless API), the server does not need to remember who is logged in. All authentication information is contained in an encrypted token string. This provides great Scalability because you can run dozens of servers behind a Load Balancer without worrying about losing sessions. Traditional session management is sometimes quite cumbersome and consumes RAM, while JWT is light and extremely flexible for mobile applications or Single Page Applications.
The structure of a JWT includes Header, Payload (containing user data) and Signature (security signature). However, JWT tokens are easily stolen by thieves if the network connection is eavesdropped. Therefore, encrypting the transmission with a security certificate is required. You can learn What is SSL HTTPS and how to install it for your website to ensure that user tokens are always securely encrypted in the production environment.
Create Login Registration API with Express.js JWT - Secure Password Encryption with Bcryptjs
When creating a registration and login API, the user password must be hashed using the Bcryptjs library before saving to the database to prevent data leaks.
Tạo API đăng ký đăng nhập với Express.js JWT bắt đầu bằng việc nhận thông tin từ người dùng qua req.body. Nguyên tắc bất di bất dịch: Tuyệt đối không bao giờ lưu mật khẩu dạng plain-text (chữ thường) vào database. Tại Phạm Hải, chúng mình luôn khuyên các dự án dùng Bcryptjs (băm mật khẩu) với cấu hình saltRounds từ 10 đến 12 để cân bằng giữa bảo mật và hiệu năng.
Khi người dùng đăng nhập đúng tài khoản và mật khẩu, server sẽ dùng hàm jwt.sign() để tạo ra một token. Theo các cập nhật bảo mật mới nhất năm 2026, access token chỉ nên có tuổi thọ ngắn (khoảng 15 phút) để hạn chế rủi ro nếu token bị lộ. Bạn có thể kết hợp thêm Passport.js (xác thực) nếu hệ thống của bạn yêu cầu tính năng đăng nhập nhanh qua Google, Apple hoặc Facebook.
Decentralize API - How to create Middleware to check tokens and authorize access
Middleware in Express.js acts as a checkpoint, helping to authenticate valid JWT tokens and perform Access Authorization for each specific endpoint.
Middleware bản chất là một hàm đứng giữa request của người dùng và response của server. Khi một request gửi đến các route cần bảo vệ (như xem profile, đổi mật khẩu), middleware sẽ chặn lại để kiểm tra. Nó sẽ trích xuất token từ header Authorization, sau đó dùng hàm jwt.verify() cùng với Secret Key để giải mã.
Nếu token hợp lệ và chưa hết hạn, middleware sẽ gán thông tin user (như userId) vào object req.user và gọi hàm next() để cho phép request đi tiếp vào Controller. Đây chính là cốt lõi của hệ thống Phân quyền (Authorization). Bạn hoàn toàn có thể viết thêm logic để kiểm tra role (ví dụ: chỉ admin mới được xóa bài viết) ngay bên trong middleware này.
Use Postman to "test the key" - Test API Endpoints that require authentication
Postman is an indispensable tool that helps send HTTP requests with the Authorization header containing the JWT token to test security endpoints.
After coding the authentication part, you cannot use a regular browser to test POST, PUT routes or routes that require tokens. Postman (API testing) was born to solve this problem. You just need to copy the token received from the successful login API, paste it into the Authorization section (choose the Bearer Token type) and press the Send button to send the request.
Thorough testing of data flows on Postman helps ensure the API works 100% correctly before handing over to the frontend team. After the API has run smoothly and securely, the frontend programmer will use JavaScript code to call it. You can see in detail how Fetch API calls REST API with JavaScript to understand the actual communication flow between client and server.
Improve your skills: Best practices when creating REST APIs with Express.js
Best practices when creating REST APIs with Express.js include standardizing error codes, data security, and optimizing configuration before Deployment to the actual server.
Professional Error Handling: Don't let users see "oh my god" errors
Centralized error handling with a single middleware helps the API return accurate HTTP status codes and hides sensitive server error details.
Xử lý lỗi (Error handling) lộn xộn, mỗi nơi trả về một kiểu JSON khác nhau là căn bệnh cực kỳ phổ biến của người mới làm API. Thay vì rải rác console.log khắp nơi, hãy tạo một middleware xử lý lỗi global (thường có 4 tham số err, req, res, next) nằm ở cuối cùng của file app.js. Bất cứ khi nào có lỗi trong hệ thống, bạn chỉ cần gọi next(error).
Middleware này sẽ format lỗi thành một chuỗi JSON thống nhất (bao gồm status, message) và trả về cho client, đồng thời giấu đi stack trace (chi tiết lỗi code) khi chạy ở chế độ production. Để hiểu sâu hơn về tư duy bắt lỗi an toàn trong code, việc áp dụng Xử lý lỗi JavaScript try catch best practices trong từng hàm controller là một bước đi khôn ngoan không thể bỏ qua.
Input Validation - Principle "never trust the user"
Use libraries like Joi or Zod to check input data (Input validation) from body, params, query before processing database logic.
"Never trust what the client sends" is the mantra of every backend developer. If you expect an integer age, make sure it is an integer. If you need an email, check the email format closely. This validation helps prevent minor errors that cause server crashes and minimizes the risk of NoSQL Injection. Currently in 2026, Zod is an extremely popular library in the Node.js community thanks to its neat declarative syntax and excellent data type inference capabilities.
Manage environment variables with .env file - Separate configuration and code
The .env file helps securely store sensitive information such as database connection strings and JWT secret keys, completely separating Environment Variables (.env) from shared source code.
Bất cứ thứ gì được xem là "bí mật" (mật khẩu database, API keys của bên thứ ba, secret key của JWT) tuyệt đối không bao giờ được hardcode trực tiếp vào file .js. Hãy đưa tất cả chúng vào một file .env ở thư mục gốc và dùng package dotenv để đọc cấu hình vào process.env. Một lưu ý sống còn: Đừng quên thêm file .env vào danh sách .gitignore ngay lập tức để tránh thảm họa vô tình đẩy toàn bộ bí mật công ty lên kho lưu trữ GitHub công khai nhé.
Overcome CORS (Cross-Origin Resource Sharing) barriers when developing
Properly configuring CORS middleware helps frontends in different domains to safely call APIs without the browser blocking CORS (cross-origin resource sharing).
Khi frontend React của bạn chạy ở http://localhost:3000 còn backend Node.js lại chạy ở http://localhost:5000, trình duyệt web sẽ tự động chặn các request gọi qua lại vì chúng khác nguồn gốc. Cài đặt và sử dụng package cors trong Express.js sẽ giải quyết triệt để vấn đề đau đầu này. Tuy nhiên, khi đưa dự án lên production, hãy cấu hình tham số origin của CORS chỉ cho phép các domain frontend hợp lệ được phép truy cập để đảm bảo an toàn tối đa cho hệ thống.
So you now have a detailed blueprint for Express.js to create the most complete, secure and well-structured REST API available today. Don't just read the theory, open VS Code right away and start typing each line of code. The process of building it yourself, encountering a red error on the terminal and then finding a way to fix it is the shortest path for you to master backend technology. Remember, a great API isn't just one that gets the right results, it's also a system that's easy for others to understand, maintain, and extend in the future.
If you have any questions during the process of configuring Express.js or MongoDB, don't hesitate to leave a comment below, I will try to answer as quickly as possible!
Note: The information in this article is for reference only. For the best advice, please contact us directly for specific advice based on your actual needs.