Introduction
User authentication is a critical part of any web application. In this tutorial, we'll build a secure authentication system in Node.js using JWT (JSON Web Token), bcrypt for password hashing, and Express.js for handling routes.
By the end of this guide, you'll be able to:
- Register users securely
- Hash passwords using bcrypt
- Authenticate users using JWT
- Protect API routes with middleware
Step 1: Set Up Your Node.js Project
First, create a new project and install dependencies:
mkdir auth-system && cd auth-system
npm init -y
npm install express bcryptjs jsonwebtoken dotenv cors mongoose
Create a .env
File
Create a .env
file for environment variables:
PORT=5000
MONGO_URI=mongodb://localhost:27017/auth_db
JWT_SECRET=your_jwt_secret_key
Step 2: Set Up Express Server
Create server.js
:
require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const userRoutes = require('./routes/userRoutes');
const app = express();
app.use(express.json());
app.use(cors());
app.use('/api/users', userRoutes);
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Step 3: Create User Model
Create models/User.js
:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true }
});
module.exports = mongoose.model('User', userSchema);
Step 4: Implement User Registration
Create routes/userRoutes.js
:
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const router = express.Router();
// Register user
router.post('/register', async (req, res) => {
try {
const { name, email, password } = req.body;
const existingUser = await User.findOne({ email });
if (existingUser) return res.status(400).json({ message: 'User already exists' });
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({ name, email, password: hashedPassword });
await user.save();
res.status(201).json({ message: 'User registered successfully' });
} catch (error) {
res.status(500).json({ message: 'Server error' });
}
});
module.exports = router;
Step 5: Implement User Login & JWT Authentication
Add login logic in userRoutes.js
:
router.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) return res.status(400).json({ message: 'Invalid credentials' });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(400).json({ message: 'Invalid credentials' });
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.json({ token });
} catch (error) {
res.status(500).json({ message: 'Server error' });
}
});
Step 6: Protect API Routes with Middleware
Create middleware/auth.js
:
const jwt = require('jsonwebtoken');
module.exports = (req, res, next) => {
const token = req.header('Authorization');
if (!token) return res.status(401).json({ message: 'Access Denied' });
try {
const verified = jwt.verify(token, process.env.JWT_SECRET);
req.user = verified;
next();
} catch (error) {
res.status(400).json({ message: 'Invalid Token' });
}
};
Apply middleware to protect routes:
const auth = require('../middleware/auth');
router.get('/profile', auth, (req, res) => {
res.json({ message: 'Welcome to your profile' });
});
Step 7: Test Your API with cURL or Postman
- Register User:
curl -X POST -H "Content-Type: application/json" -d '{"name": "John Doe", "email": "john@example.com", "password": "password123"}' http://localhost:5000/api/users/register
- Login User:
curl -X POST -H "Content-Type: application/json" -d '{"email": "john@example.com", "password": "password123"}' http://localhost:5000/api/users/login
- Access Protected Route:
curl -X GET -H "Authorization: Bearer YOUR_JWT_TOKEN" http://localhost:5000/api/users/profile
Conclusion
You have successfully built a secure user authentication system in Node.js with JWT authentication! 🎉
Next Steps:
✅ Connect to a frontend (React/Angular/Vue)
✅ Implement password reset functionality
✅ Add role-based access control (RBAC)
Happy Coding! 🚀
Top comments (0)