In this article, I'll walk through the process of setting up user authentication using Express, MongoDB, and JSON Web Tokens (JWT). This will allow you to implement user signup, login, and protect routes that require authentication.
Let's Dive Right In 😁😁
Prerequisites
Make sure you have Node.js installed on your machine. Additionally, create a new directory for your project and initialize it with the following dependencies:
npm init -y
npm install express mongoose dotenv jsonwebtoken bcrypt
This process should look like this:
Create your main entry file, .env and .gitignore if you wish to push your code
touch index.js .env .gitignore
Project Setup
- We'll import our packages into
index.jsand setup our express server.
const express = require('express');
const dotenv = require('dotenv');
dotenv.config();
const app = express();
const PORT = process.env.PORT || 3000;
app.use(express.json());
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Make sure your script is set in your package.json. Now when I do
npm run devon my terminal I should haveServer is running on port 5500
And do not forget to also declare your PORT in the .env file.
- I would quickly 😋😋 add a root entry file > Now my code looks like this
const express = require('express');
const dotenv = require('dotenv');
dotenv.config();
const app = express();
const PORT = process.env.PORT || 3000;
app.use(express.json());
app.get('/', (req, res)=> {
res.send('Welcome to Nodejs Authentication Tutorial')
})
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
- I'll create a folder called
configto hold my database file which I would calldatabase.js> Now I would configure my database, mydatabase.jsfolder would look like this:
const mongoose = require('mongoose');
exports.connectDb = async () => {
try {
await mongoose.connect(process.env.MONGODB_URI);
console.log("MongoDB connection Established...");
} catch (error) {
console.error(error.message);
}
}
- I would import the database function into the
index.jsfile and fire it. > Your index.js file should look like this now
const express = require("express");
const dotenv = require("dotenv");
const { connectDb } = require("./config/database");
dotenv.config();
const app = express();
const PORT = process.env.PORT || 3000;
// Iinitialized Database Configuration
connectDb();
app.use(express.json());
// Root Entry
app.get("/", (req, res) => {
res.send("Welcome to Nodejs Authentication Tutorial");
});
// Listened to the PORT
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
- Let's define our user Schema For Mongodb, we'll be accepting just two fields
username and password> We'll create a folder calledmodelsand a file calleduserModels.js> MyuserModels.jsfile looks like this now
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: { type: String, required: true },
password: { type: String, required: true }
});
const User = mongoose.model('User', userSchema);
module.exports = User;
- Now let's create a folder called
controllerand a file calleduserController.js> Now YouruserController.jsshould look like this
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const User = require("../models/userModels");
exports.signUp = async (req, res) => {
try {
const { username, password } = req.body;
// Check If The Input Fields are Valid
if (!username || !password) {
return res
.status(400)
.json({ message: "Please Input Username and Password" });
}
// Check If User Exists In The Database
const existingUser = await User.findOne({ username });
if (existingUser) {
return res.status(400).json({ message: "User Already Exists" });
}
// Hash The User's Password
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(password, saltRounds);
// Save The User To The Database
const newUser = new User({
username,
password: hashedPassword,
});
await newUser.save();
return res
.status(201)
.json({ message: "User Created Successfully", newUser });
} catch (error) {
console.log(error.message);
return res.status(500).json({ message: "Error creating user" });
}
};
- Now we create our
routesfolder anduser.Routes.jsfile > Now theuser.Routes.jsfile should look like this;
const express = require('express');
const { signUp } = require('../controller/userController');
const router = express.Router();
router.post('/signup', signUp);
module.exports = router;
- We'll import our Router into the
index.jsfile > We'll add these two lines of code to ourindex.jsfile
const userRouter = require("./routes/user.Routes");
app.use("/api/v1/user", userRouter);
Now
index.jsShould look like this
const express = require("express");
const dotenv = require("dotenv");
const { connectDb } = require("./config/database");
const userRouter = require("./routes/user.Routes");
dotenv.config();
const app = express();
const PORT = process.env.PORT || 3000;
// Iinitialized Database Configuration
connectDb();
app.use(express.json());
// Import The User Route
app.use("/api/v1/user", userRouter);
// Root Entry
app.get("/", (req, res) => {
res.send("Welcome to Nodejs Authentication Tutorial");
});
// Listened to the PORT
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Now Let's Test, I would be using thunder client
You test with this routehttp://localhost:5500/api/v1/user/signup
You can install MongoDB compass to also check
Now We Can Try Login
Right inside your
userController.jswe'll write the lines of code for login. And That Should Look like this
exports.login = async (req, res) => {
try {
const { username, password } = req.body;
// Check If The Input Fields are Valid
if (!username || !password) {
return res
.status(400)
.json({ message: "Please Input Username and Password" });
}
// Check If User Exists In The Database
const user = await User.findOne({ username });
if (!user) {
return res.status(401).json({ message: "Invalid username or password" });
}
// Compare Passwords
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
return res.status(401).json({ message: "Invalid username or password" });
}
// Generate JWT Token
const token = jwt.sign(
{ userId: user._id, username: user.username },
process.env.SECRET_KEY || "1234!@#%<{*&)",
{ expiresIn: "1h" }
);
return res
.status(200)
.json({ message: "Login Successful", data: user, token });
} catch (error) {
console.log(error.message);
return res.status(500).json({ message: "Error during login" });
}
};
- We need to add
loginto ouruser.Routes.jsfile
const express = require('express');
const { signUp, login } = require('../controller/userController');
const router = express.Router();
router.post('/signup', signUp);
router.post('/login', login);
module.exports = router;
Now we Test Our Login at http://localhost:5500/api/v1/user/login
So we Unhashed the password, logged and Attached Jwt to the User successfully.
Lets Do One Last thing Let's Find all Users But we'll make the Route Protected by Jwt
So we'll add this to the
userController.jsfile
exports.getAllUsers = async (req, res) => {
try {
// Retrieve all users from the database
const users = await User.find({}, { password: 0 }); // Exclude the password field from the response
return res.status(200).json({ users });
} catch (error) {
console.log(error.message);
return res.status(500).json({ message: "Error fetching users" });
}
};
We'll add this to the routes
const express = require('express');
const { signUp, login, getAllUsers } = require('../controller/userController');
const router = express.Router();
router.GET('/allusers', getAllUsers);
router.post('/signup', signUp);
router.post('/login', login);
module.exports = router;
When you test on
http://localhost:5500/api/v1/user/allusersYou should get All the users you have in your DatabaseNow can protect this route with our Jwt Token, Let's create a file called
isAuth.jsin ourconfigfolder and it would look like this
const jwt = require("jsonwebtoken");
exports.verifyToken = async (req, res, next) => {
try {
const token = req.headers.authorization.split(" ")[1];
if (!token) {
return res.status(401).json({ error: "Unauthorized" });
}
const decoded = await jwt.verify(token, process.env.SECRET_KEY);
if (!decoded) {
throw new Error();
}
req.user = decoded;
next();
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Error Validating Token" });
}
};
Now we need to import
verifyTokeninto our Route
And now our Route looks like this
const express = require('express');
const { signUp, login, getAllUsers } = require('../controller/userController');
const { verifyToken } = require('../config/isAuth');
const router = express.Router();
router.get('/allusers', verifyToken, getAllUsers);
router.post('/signup', signUp);
router.post('/login', login);
module.exports = router;
And We Are Done
Here's a Link To The Github repo for this Project
Please leave a Like And A Comment If This Article Was Helpful And Probably you have any questions. Untill Next Time








Top comments (0)