JWT Authentication in Node.js: A Practical Guide

Table of contents

When building a web application with Node.js, one of the key steps is adding authentication. A widely used method is token-based authentication, which helps secure the application. This method uses tokens—most commonly JSON Web Tokens (JWTs)—to identify and verify users.
In this method, a token is created when the user logs in, and this token is sent with each request to prove their identity. Below is a simple explanation and code example to show how you can set this up in a Node.js app.
1. Pick an Authentication Method:
Start by choosing how users will log in. The common ways include using a username and password, logging in through social media accounts (like Google or Facebook via OAuth), or using tokens such as JWT (JSON Web Tokens) for authentication.
npm init -y
3. Install Necessary Packages:
Based on the method you selected, install the packages you’ll need.
For example, if you’re going with JWT authentication, install the jsonwebtoken
package like this:
npm install jsonwebtoken
4. Set Up a User Model:
You need a user model to save user details in the database (like MongoDB, MySQL, etc.).
You can use an ORM tool to make this easier—like Mongoose for MongoDB or Sequelize for SQL databases.
Here’s a basic example using Mongoose with MongoDB:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: String,
password: String,
});
const User = mongoose.model('User', userSchema);
module.exports = User;
5. Build Routes and Controllers:
Now, create routes and controllers to handle user signup, login, and token-based authentication.
Below is a simple example using Express.js:
// routes/auth.js
const express = require('express');
const router = express.Router();
const User = require('../models/User');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
// Register a new user
router.post('/register', async (req, res) => {
try {
const { username, password } = req.body;
// Hash the password before saving
const hashedPassword = await bcrypt.hash(password, 10);
// Create and save the user
const user = new User({ username, password: hashedPassword });
await user.save();
res.status(201).json({ message: 'User registered successfully' });
} catch (err) {
res.status(500).json({ error: 'Registration failed' });
}
});
// Login an existing user
router.post('/login', async (req, res) => {
try {
const { username, password } = req.body;
// Find the user by username
const user = await User.findOne({ username });
if (!user) {
return res.status(401).json({ error: 'Invalid username or password' });
}
// Compare hashed passwords
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(401).json({ error: 'Invalid username or password' });
}
// Generate JWT token
const token = jwt.sign({ userId: user._id }, 'your-secret-key', {
expiresIn: '1h',
});
res.status(200).json({ token });
} catch (err) {
res.status(500).json({ error: 'Login failed' });
}
});
module.exports = router;
6. Secure Routes with Middleware:
To keep certain parts of your app safe, you need to protect routes that require users to be logged in. This is done using a middleware function that checks if the JWT token sent by the user is valid.
Example middleware to verify JWT:
// middleware/authMiddleware.js
const jwt = require('jsonwebtoken');
function verifyToken(req, res, next) {
const token = req.header('Authorization');
if (!token) return res.status(401).json({ error: 'Access denied' });
try {
const decoded = jwt.verify(token, 'your-secret-key');
req.userId = decoded.userId;
next();
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
}
module.exports = verifyToken;
7. Apply Authentication Middleware
Use the middleware you created to secure certain routes. This ensures only users with a valid token can access them.
Example of using the middleware in a route:
// routes/protectedRoute.js
const express = require('express');
const router = express.Router();
const verifyToken = require('../middleware/authMiddleware');
// Protected route
router.get('/', verifyToken, (req, res) => {
res.status(200).json({ message: 'Protected route accessed' });
});
module.exports = router;
8. Start Your Express Application:
Set up your main application file and start the Express server:
// app.js
const express = require('express');
const app = express();
const authRoutes = require('./routes/auth');
const protectedRoute = require('./routes/protectedRoute');
app.use(express.json());
// Routes for authentication (register, login)
app.use('/auth', authRoutes);
// Protected routes that need authentication
app.use('/protected', protectedRoute);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Here, /auth
handles user signup and login, and /protected
contains routes that require a valid token.
9. Run Your Application
Start your Node.js server by running this command in the terminal:
node app.js
This example shows a basic way to add authentication to a Node.js web app using Express.js, MongoDB to store users, and JWT for token-based login.
Important tips:
Always use a strong secret key instead of
'your-secret-key'
.Store secret keys and other sensitive info in environment variables for security.
For production, use HTTPS to encrypt data between client and server.
This setup is a good starting point for securing your web app with token-based authentication.
Subscribe to my newsletter
Read articles from Hari Rajak directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
