๐ Introduction
In this tutorial, you’ll learn how to add authentication to your Node.js application using JWT (JSON Web Token).
You will build secure API routes that require users to log in before accessing protected resources.
By the end of this guide, you’ll have a complete Register → Login → Protected Route → Logout authentication system using Node.js, Express, MySQL, and JWT.
✅ Prerequisites
Before starting, you should already know:
Basic Express API concepts
User registration with encrypted passwords
User login with JWT token generation
How middleware works in Express
You must have installed:
Node.js & npm
MySQL (running locally)
Postman (for API testing)
๐️ Step 1 — Set Up the Database
Open your MySQL terminal and run:
CREATE DATABASE auth_demo;
USE auth_demo;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100) UNIQUE,
password VARCHAR(255)
);
This table stores registered users with hashed passwords.
๐ Step 2 — Set Up the Project
Create a new project folder:
mkdir node-jwt-auth
cd node-jwt-auth
Initialize the project and install dependencies:
npm init -y
npm install express mysql2 bcryptjs jsonwebtoken cors
๐งฉ Step 3 — Create app.js and Base Setup
const express = require('express');
const mysql = require('mysql2');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const cors = require('cors');
const app = express();
const PORT = 3000;
app.use(cors());
app.use(express.json());
MySQL Connection
const db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'auth_demo'
});
db.connect(err => {
if (err) throw err;
console.log('✅ MySQL Connected!');
});
JWT Secret Key
const SECRET_KEY = 'mysecretkey';
๐ Step 4 — Register User (POST)
Route: /api/register
app.post('/api/register', async (req, res) => {
const { name, email, password } = req.body;
if (!name || !email || !password)
return res.status(400).json({ message: 'All fields required' });
db.query('SELECT * FROM users WHERE email = ?', [email], async (err, results) => {
if (results.length > 0)
return res.status(400).json({ message: 'Email already registered' });
const hashedPassword = await bcrypt.hash(password, 10);
const sql = 'INSERT INTO users (name, email, password) VALUES (?, ?, ?)';
db.query(sql, [name, email, hashedPassword], err => {
if (err) throw err;
res.json({ message: 'User registered successfully!' });
});
});
});
๐งช Test with Postman
POST http://localhost:3000/api/register
{
"name": "Souy",
"email": "souy@example.com",
"password": "123456"
}
๐ Step 5 — Login User (POST)
Route: /api/login
app.post('/api/login', async (req, res) => {
const { email, password } = req.body;
if (!email || !password)
return res.status(400).json({ message: 'Email and password required' });
db.query('SELECT * FROM users WHERE email = ?', [email], async (err, results) => {
if (results.length === 0)
return res.status(401).json({ message: 'Invalid email or password' });
const user = results[0];
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword)
return res.status(401).json({ message: 'Invalid email or password' });
const token = jwt.sign(
{ id: user.id, email: user.email },
SECRET_KEY,
{ expiresIn: '1h' }
);
res.json({ message: 'Login successful', token });
});
});
๐ก️ Step 6 — JWT Middleware (Protect Routes)
function verifyToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token)
return res.status(401).json({ message: 'Access denied: No token provided' });
jwt.verify(token, SECRET_KEY, (err, decoded) => {
if (err)
return res.status(403).json({ message: 'Invalid or expired token' });
req.user = decoded;
next();
});
}
๐ค Step 7 — Protected Route (GET)
Route: /api/profile
app.get('/api/profile', verifyToken, (req, res) => {
const userId = req.user.id;
db.query(
'SELECT id, name, email FROM users WHERE id = ?',
[userId],
(err, results) => {
if (err) throw err;
res.json({ user: results[0] });
}
);
});
๐งช Test in Postman
Method: GET
URL:
http://localhost:3000/api/profileHeader:
Authorization: Bearer YOUR_JWT_TOKEN
๐ Step 8 — Logout User (JWT)
JWT authentication is stateless, so logout is handled on the client side.
How Logout Works
Remove JWT token from browser or app
Without the token, protected routes are inaccessible
Example (Frontend)
localStorage.removeItem('token');
Optional Logout API
app.post('/api/logout', (req, res) => {
res.json({ message: 'Logout successful. Please remove token on client.' });
});
๐ Step 9 — Start the Server
app.listen(PORT, () => {
console.log(`๐ Server running at http://localhost:${PORT}`);
});
Run the app:
node app.js
๐ง Summary
In this tutorial, you learned how to:
Register users with hashed passwords
Authenticate users using JWT
Protect routes using middleware
Implement logout in JWT authentication
Store and manage users in MySQL
Build a secure Node.js authentication system
✅ This setup is production-ready for small projects and perfect for beginners.

