Security is a critical aspect of web development, and understanding how to implement authentication and authorization is essential for any developer. In this part of our Node.js series, we will explore how to secure your application by implementing a simple authentication system. We'll use JSON Web Tokens (JWT) for authentication and middleware for authorization.
please subscribe to my YouTube channel to support my channel and get more web development tutorials.
Understanding Authentication and Authorization
- Authentication: The process of verifying the identity of a user. Typically, this involves checking a username and password.
- Authorization: The process of determining if a user has permission to perform a certain action or access certain resources.
Setting Up the Project
Let's start by setting up a new Express project. If you haven’t already, initialize a new project and install the necessary dependencies:
npm init -y
npm install express bcryptjs jsonwebtoken body-parser mongoose
Connecting to MongoDB
First, we need to connect our application to MongoDB. If you need a refresher on connecting to MongoDB, refer to Part 7 of this series.
database.js
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/auth_demo', {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('Connected to MongoDB');
});
module.exports = mongoose;
Defining User Model
We need a user model to store user information, including hashed passwords.
userModel.js
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true }
});
userSchema.pre('save', async function (next) {
if (this.isModified('password') || this.isNew) {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
}
next();
});
userSchema.methods.comparePassword = async function (password) {
return await bcrypt.compare(password, this.password);
};
const User = mongoose.model('User', userSchema);
module.exports = User;
Setting Up Express Server
Next, set up the Express server and create routes for user registration and login.
app.js
const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const User = require('./userModel');
const mongoose = require('./database');
const app = express();
app.use(bodyParser.json());
const JWT_SECRET = 'your_jwt_secret';
// User Registration
app.post('/register', async (req, res) => {
try {
const { username, password } = req.body;
const user = new User({ username, password });
await user.save();
res.status(201).send('User registered successfully');
} catch (err) {
res.status(400).send('Error registering user');
}
});
// User Login
app.post('/login', async (req, res) => {
try {
const { username, password } = req.body;
const user = await User.findOne({ username });
if (!user || !(await user.comparePassword(password))) {
return res.status(401).send('Invalid username or password');
}
const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '1h' });
res.send({ token });
} catch (err) {
res.status(400).send('Error logging in');
}
});
// Middleware to Protect Routes
const authMiddleware = (req, res, next) => {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).send('Access denied. No token provided.');
}
try {
const decoded = jwt.verify(token, JWT_SECRET);
req.user = decoded;
next();
} catch (err) {
res.status(401).send('Invalid token');
}
};
// Protected Route
app.get('/protected', authMiddleware, (req, res) => {
res.send('This is a protected route');
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}/`);
});
Testing the Application
-
Register a User:
- Send a POST request to
/register
with a JSON body containingusername
andpassword
.
- Send a POST request to
-
Login a User:
- Send a POST request to
/login
with the same credentials. - If successful, you will receive a JWT token.
- Send a POST request to
-
Access a Protected Route:
- Send a GET request to
/protected
with the token in theAuthorization
header.
- Send a GET request to
Conclusion
By implementing authentication and authorization, you can protect your application’s routes and ensure that only authenticated users can access certain resources. In the next part of our series, we will delve into building RESTful APIs using Express and best practices for structuring your application.
Stay tuned for more advanced Node.js development techniques!
Follow me for more tutorials and tips on web development. Feel free to leave comments or questions below!
Follow and Subscribe:
- Website: Dipak Ahirav
- Email: dipaksahirav@gmail.com
- YouTube: devDive with Dipak
- LinkedIn: Dipak Ahirav
Top comments (0)