DEV Community

Cover image for Building a Secure Authentication System in Node.js using JWT
Manas Uniyal
Manas Uniyal

Posted on

1

Building a Secure Authentication System in Node.js using JWT

Building a Secure Authentication System in Node.js using JWT

Authentication is a crucial aspect of backend development, ensuring secure access to resources. In this tutorial, we'll build a secure authentication system in Node.js using JSON Web Tokens (JWT).

Prerequisites

  • πŸ“Œ Basic knowledge of JavaScript and Node.js
  • πŸ“Œ Node.js installed on your system
  • πŸ“Œ A package manager like npm or yarn

Step 1: Setting Up the Project

First, create a new Node.js project:

mkdir jwt-auth-system
cd jwt-auth-system
npm init -y
Enter fullscreen mode Exit fullscreen mode

This initializes a new Node.js project with a default package.json file.

Next, install the required dependencies:

npm install express jsonwebtoken bcryptjs dotenv cors mongoose
Enter fullscreen mode Exit fullscreen mode

Also, install nodemon for development:

npm install --save-dev nodemon
Enter fullscreen mode Exit fullscreen mode

Step 2: Setting Up Express Server

Create an index.js file and set up a basic Express server:

require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const authRoutes = require('./routes/auth');

const app = express();
app.use(express.json());
app.use(cors());

mongoose.connect(process.env.MONGO_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));

app.use('/api/auth', authRoutes);

app.listen(5000, () => console.log('Server running on port 5000'));
Enter fullscreen mode Exit fullscreen mode

Step 3: Creating User Model

Create a new folder models and a file User.js inside it:

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
  username: { type: String, required: true, unique: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true }
});

module.exports = mongoose.model('User', UserSchema);
Enter fullscreen mode Exit fullscreen mode

Step 4: Implementing Authentication Routes

Create a routes folder and an auth.js file inside it:

const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../models/User');

const router = express.Router();

// πŸ“ Register
router.post('/register', async (req, res) => {
  try {
    const { username, email, password } = req.body;
    const hashedPassword = await bcrypt.hash(password, 10);
    const newUser = new User({ username, email, password: hashedPassword });
    await newUser.save();
    res.status(201).json({ message: 'User registered successfully' });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// πŸ”‘ Login
router.post('/login', async (req, res) => {
  try {
    const { email, password } = req.body;
    const user = await User.findOne({ email });
    if (!user) return res.status(404).json({ message: 'User not found' });

    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({ error: error.message });
  }
});

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

Step 5: Protecting Routes

Create a middleware for authentication:

const jwt = require('jsonwebtoken');

const authMiddleware = (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' });
  }
};

module.exports = authMiddleware;
Enter fullscreen mode Exit fullscreen mode

Step 6: Testing the API

Use Postman or any API testing tool to test:

  1. πŸ“ Register a user: POST /api/auth/register
  2. πŸ”‘ Login a user: POST /api/auth/login
  3. πŸ”’ Access protected routes with the received token

Image description


Enter fullscreen mode Exit fullscreen mode

Conclusion

βœ… You've successfully built a secure authentication system in Node.js using JWT. This setup ensures users can securely authenticate and access protected resources.

Tiugo image

Fast, Lean, and Fully Extensible

CKEditor 5 is built for developers who value flexibility and speed. Pick the features that matter, drop the ones that don’t and enjoy a high-performance WYSIWYG that fits into your workflow

Start now

Top comments (2)

Collapse
 
javillat profile image
Javier Villatoro β€’

Great explanation. Thanks for sharing.

Collapse
 
uniyalmanas profile image
Manas Uniyal β€’

No problem , always there to help . Feel free if you have any other doubt .

ITRS image

See What Users Experience in The Browser β€” Anywhere, Anytime

Simulate logins, checkouts, and payments on SaaS, APIs, and internal apps. Catch issues early, baseline web performance, and stay ahead of incidents. Easily record user journeys right from your browser.

Start Free Trial

πŸ‘‹ Kindness is contagious

Discover more in this insightful article and become part of the thriving DEV Community. Developers at every level are welcome to share and enrich our collective expertise.

A simple β€œthank you” can brighten someone’s day. Please leave your appreciation in the comments!

On DEV, sharing skills lights our way and strengthens our connections. Loved the read? A quick note of thanks to the author makes a real difference.

Count me in