In this article, we will take a look at how to implement a registration form and login form using Node.js and MongoDB. The reason I am using Node.js is the fact that Node.js is the latest and most advanced platform for the web front-end which have a power to run simultaneously and can use the power of a server to the full extent.
As we already know Node.js is used for creating a server-side application. So for building a registration form and login form, we need to build a server-side application.
First, we have to create the project. Open the terminal and write the below code, and press enter.
npm init
Once you enter the command, you must fill in some information about your backend project. Once it has been done, we will follow the next step.
We will make a folder structure for our project that includes folders like controller, DB, middleware, modules, routes, validator, and one file index.js in the src folder. You can see the picture below.
After creating this folder structure, we must make a .envfile at the root level. We store our database URL in that file so we can access it anywhere in the project using the process. env.<URL_NAME>
Before starting coding, we have to install some npm packages, and they are listed below.
Let me give you some idea about these libraries.
npm install dotenv
dotenv is used to read the key and value pair from .env and add them to an environment variable. It is great for managing app settings during development.
npm install express
Install the Express framework globally using NPM so that it can be used to create a web application using the node terminal.
npm install bcrypt
Install this NPM package in our project to convert the user’s password into a hash.
npm install express-validator
The express-validator is used for checking users’ requests where we can check recommendations like length, min-max character, empty or not, and so on.
npm install http-status-codes
This package is used for the status code, which we return with a response.
npm install jsonwebtoken
This package generates a unique web token from a user’s data and the verified tokens when we pass with the APIs.
npm install cors mongoose shortid
These are other packages that we need to make this project complete.
So after installing all the packages successfully, we are moving forward to the code section, where we will see how to make the APIs using these packages.
In the DB folder, make one file, give the name connect.js, and write the code below. The purpose of this code is only to connect our backend to the database.
const mongoose = require("mongoose"); const connectDB = (url) => { return mongoose.connect(url); }; module.exports = connectDB;
Now In our index.server.js, write below the code for connection.
const express = require("express"); require("dotenv").config(); const connectDB = require("./db/connect"); const app = express(); var cors = require("cors"); const authRouter = require("./routes/auth"); app.use(cors()); app.use(express.json()); app.use("/api", authRouter); //Port and Connect to DB const port = process.env.PORT || 5000; const start = async () => { try { await connectDB(process.env.MONGO_URL); app.listen(port, () => { console.log(`Server is running on port ${port}`); }); } catch (error) { console.log("error =>", error); } }; start();
In this file, we wrote a code to establish the connection between the backend and the database. We called the start method for reference, and we used some packages for .env configuration, route configuration, and all those things.
One more change in the package.json file as well. We will use nodemon, so we don’t need to run our backend repeatedly. Without nodemon, we need to run our backend after making some changes to the code. Otherwise, it will not reflect. So nodemon is good to use.
"scripts": { "start": "nodemon src/index.server.js" },
In the third step, we will write a User schema in the modal folder where we create boundaries for the APIs, like which data will allow and key names, etc.
const mongoose = require("mongoose"); const bcrypt = require("bcrypt"); const userSchema = new mongoose.Schema({ firstName: { type: String, require: true, trim: true, min: 3, max: 20, }, lastName: { type: String, require: true, trim: true, min: 3, max: 20, }, username: { type: String, require: true, trim: true, unique: true, lowercase: true, index: true, }, email: { type: String, require: true, trim: true, unique: true, lowercase: true, }, hash_password: { type: String, require: true, }, role: { type: String, enum: ["user", "admin"], default: "user", }, contactNumber: { type: String, }, profilePicture: { type: String, }, },{ timestamps: true }); //For get fullName from when we get data from database userSchema.virtual("fullName").get(function () { return `${this.firstName} ${this.lastName}`; }); userSchema.method({ async authenticate(password) { return bcrypt.compare(password, this.hash_password); }, }); module.exports = mongoose.model("User", userSchema);
Like this, we define the keys for requests and can make a virtual method using mongoose. Here we made one method for authentication. We can compare passwords with the database and return the result from here.
By using virtual, we can directly make one key-value pair and give it to the DB response.
In the third step, we will make a file auth.js in the validator folder. After that, we are going to write a code for request validation.
const { check, validationResult } = require("express-validator"); const { StatusCodes } = require("http-status-codes"); const validateSignUpRequest = [ check("firstName").notEmpty().withMessage("First Name is required"), check("lastName").notEmpty().withMessage("Last Name is required"), check("email").isEmail().withMessage("Valid Email required"), check("password") .isLength({ min: 6 }) .withMessage("Password must be at least 6 character long"), ]; const validateSignIpRequest = [ check("email").isEmail().withMessage("Valid Email required"), check("password") .isLength({ min: 6 }) .withMessage("Password must be at least 6 character long"), ] const isRequestValidated = (req, res, next) => { const errors = validationResult(req); if (errors.array().length > 0) { return res .status(StatusCodes.BAD_REQUEST) .json({ error: errors.array()[0].msg }); } next(); }; module.exports = { validateSignUpRequest, isRequestValidated, validateSignIpRequest, };
We wrote three validation here for good sign-in/signup requests. You can see we used the express-validator package to handle validation. This validator is used to check whether the requested data is enough or right to succeed in an API call.
Make an auth.js file into the router folder and write the below code
const express = require("express"); const router = express.Router(); const { signUp, signIn } = require("../controller/auth"); const { isRequestValidated, validateSignUpRequest, validateSignIpRequest, } = require("../validators/auth"); router.route("/signin").post(validateSignIpRequest, isRequestValidated, signIn); router.route("/signup").post(validateSignUpRequest, isRequestValidated, signUp); module.exports = router;
So in this code, we import the router by using express, and by using that we make out API endpoint.
The router has one route method when we can make our APIs endpoint as we added in upper code according to our APIs. For example, for Sign In API, we add “/sign in,” and for SignUp API, we add “/signup.”
After that, we have to define methods of APIs like get, post, put, patch, etc. then we will use a validator which is imported from the validators folder, and after the validator, at last, we put our controller where we will write our APIs logic.
Let me explain to you from scratch when the user does sign in with the credentials like email and password and hits the button at a time sign-in API call, and before going to the controller, in the router, it will check validation through our validator.
So if there is anything wrong with the credential, like email format or password length, then it will break this call from here and respond to the user with an error message which you can check on the validation file where we wrote code for it.
If everything is fine, the call will go into the controller, and now we will write a code for it.
Make an auth.js file in the controller folder and write the below code.
const { StatusCodes } = require("http-status-codes"); const User = require("../models/auth"); const jwt = require("jsonwebtoken"); const bcrypt = require("bcrypt"); const shortid = require("shortid"); const signUp = async (req, res) => { const { firstName, lastName, email, password } = req.body; if (!firstName || !lastName || !email || !password) { return res.status(StatusCodes.BAD_REQUEST).json({ message: "Please Provide Required Information", }); } const hash_password = await bcrypt.hash(password, 10); const userData = { firstName, lastName, email, hash_password, }; const user = await User.findOne({ email }); if (user) { return res.status(StatusCodes.BAD_REQUEST).json({ message: "User already registered", }); } else { User.create(userData).then((data, err) => { if (err) res.status(StatusCodes.BAD_REQUEST).json({ err }); else res .status(StatusCodes.CREATED) .json({ message: "User created Successfully" }); });
} }; const signIn = async (req, res) => { try { if (!req.body.email || !req.body.password) { res.status(StatusCodes.BAD_REQUEST).json({ message: "Please enter email and password", }); } const user = await User.findOne({ email: req.body.email }); if (user) { if (user.authenticate(req.body.password)) { const token = jwt.sign( { _id: user._id, role: user.role }, process.env.JWT_SECRET,{ expiresIn: "30d"}); const { _id, firstName, lastName, email, role, fullName } = user; res.status(StatusCodes.OK).json({ token, user: { _id, firstName, lastName, email, role, fullName }, }); } else { res.status(StatusCodes.UNAUTHORIZED).json({ message: "Something went wrong!", }); } } else { res.status(StatusCodes.BAD_REQUEST).json({ message: "User does not exist..!", }); } } catch (error) { res.status(StatusCodes.BAD_REQUEST).json({ error }); } }; module.exports = { signUp, signIn};
First, we will talk about using API; you can see the code when the user does signup with an email, password, first name, and last name. If this request parameter is not found will return an error message.
If the user requests all required data, API does the further task and generates a hash password using the bcrypt package.
Then we try to find an email using findOne in the database. If we get it, we send a response with the message “Email address is already used”; we add that user to the database.
Here, we are using the User schema we made in the Modal folder. This schema gives us many methods to play with databases, like create, find, delete and update.
Now, we will talk about signing API. We need only two pieces of data from the user side, one is an email, and the second is a password. If one of these data is missing, then break this API and send a response with an error message and appropriate status code.
After that, we find that user in the database by email address. If we get that user, we do the other process for authentication. Otherwise, we break this API from here and send a response with an error message like “user does not exist.”
If we get the user from the database, then we cross-check the password that the user gives. You can see the method we access it from the user and write it in the user schema. If the password matches the database, generate one token with an expiration time. For that, we are using jsonwebtoken package to develop it and send a successful response with the token.
Now your APIs are ready to use, and make sure one thing is that when you use APIs, your backend server needs to start when you use it locally. APIs look like
SIGN IN: http://localhost:2000/api/signin
SIGN UP: http://localhost:2000/api/signup
In this blog, we learn how to make APIs for registration and login form using Node.js and MongoDB, generate tokens, create a hash password, connect to the DB, and make schema, controller, router, and all those things.
How to Effectively Hire and Manage a Remote Team of Developers.
Download NowThe Mindbowser team's professionalism consistently impressed me. Their commitment to quality shone through in every aspect of the project. They truly went the extra mile, ensuring they understood our needs perfectly and were always willing to invest the time to...
CTO, New Day Therapeutics
I collaborated with Mindbowser for several years on a complex SaaS platform project. They took over a partially completed project and successfully transformed it into a fully functional and robust platform. Throughout the entire process, the quality of their work...
President, E.B. Carlson
Mindbowser and team are professional, talented and very responsive. They got us through a challenging situation with our IOT product successfully. They will be our go to dev team going forward.
Founder, Cascada
Amazing team to work with. Very responsive and very skilled in both front and backend engineering. Looking forward to our next project together.
Co-Founder, Emerge
The team is great to work with. Very professional, on task, and efficient.
Founder, PeriopMD
I can not express enough how pleased we are with the whole team. From the first call and meeting, they took our vision and ran with it. Communication was easy and everyone was flexible to our schedule. I’m excited to...
Founder, Seeke
Mindbowser has truly been foundational in my journey from concept to design and onto that final launch phase.
CEO, KickSnap
We had very close go live timeline and Mindbowser team got us live a month before.
CEO, BuyNow WorldWide
If you want a team of great developers, I recommend them for the next project.
Founder, Teach Reach
Mindbowser built both iOS and Android apps for Mindworks, that have stood the test of time. 5 years later they still function quite beautifully. Their team always met their objectives and I'm very happy with the end result. Thank you!
Founder, Mindworks
Mindbowser has delivered a much better quality product than our previous tech vendors. Our product is stable and passed Well Architected Framework Review from AWS.
CEO, PurpleAnt
I am happy to share that we got USD 10k in cloud credits courtesy of our friends at Mindbowser. Thank you Pravin and Ayush, this means a lot to us.
CTO, Shortlist
Mindbowser is one of the reasons that our app is successful. These guys have been a great team.
Founder & CEO, MangoMirror
Kudos for all your hard work and diligence on the Telehealth platform project. You made it possible.
CEO, ThriveHealth
Mindbowser helped us build an awesome iOS app to bring balance to people’s lives.
CEO, SMILINGMIND
They were a very responsive team! Extremely easy to communicate and work with!
Founder & CEO, TotTech
We’ve had very little-to-no hiccups at all—it’s been a really pleasurable experience.
Co-Founder, TEAM8s
Mindbowser was very helpful with explaining the development process and started quickly on the project.
Executive Director of Product Development, Innovation Lab
The greatest benefit we got from Mindbowser is the expertise. Their team has developed apps in all different industries with all types of social proofs.
Co-Founder, Vesica
Mindbowser is professional, efficient and thorough.
Consultant, XPRIZE
Very committed, they create beautiful apps and are very benevolent. They have brilliant Ideas.
Founder, S.T.A.R.S of Wellness
Mindbowser was great; they listened to us a lot and helped us hone in on the actual idea of the app. They had put together fantastic wireframes for us.
Co-Founder, Flat Earth
Ayush was responsive and paired me with the best team member possible, to complete my complex vision and project. Could not be happier.
Founder, Child Life On Call
The team from Mindbowser stayed on task, asked the right questions, and completed the required tasks in a timely fashion! Strong work team!
CEO, SDOH2Health LLC
Mindbowser was easy to work with and hit the ground running, immediately feeling like part of our team.
CEO, Stealth Startup
Mindbowser was an excellent partner in developing my fitness app. They were patient, attentive, & understood my business needs. The end product exceeded my expectations. Thrilled to share it globally.
Owner, Phalanx
Mindbowser's expertise in tech, process & mobile development made them our choice for our app. The team was dedicated to the process & delivered high-quality features on time. They also gave valuable industry advice. Highly recommend them for app development...
Co-Founder, Fox&Fork