This application is a simple authentication server built with Express, using JSON Web Tokens (JWT) for session management and bcrypt for securely storing passwords. Users can register and log in to access protected routes. MySQL is used for storing user data.
Technologies Used
1. Express.js: Web framework for handling routes and middleware.
2. bcrypt.js: Library for hashing passwords securely.
3. jsonwebtoken: Library for creating and verifying JWT tokens.
4. mysql2: MySQL client for Node.js with support for Promises.
5. cookie-parser: Middleware for parsing cookies.
Code Breakdown
1. Import Required Libraries
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const cookieParser = require('cookie-parser');
const mysql = require('mysql2/promise');
express: Provides functions to create routes and handle HTTP requests.
jsonwebtoken: Used to create and verify JWTs for user sessions.
bcryptjs: Used for hashing passwords before storing them in the database.
cookie-parser: Middleware to parse cookies from incoming HTTP requests.
mysql2/promise: MySQL client with promise support, allowing asynchronous operations.
2. Initialize Express App and Define Constants
const app = express();
const PORT = 3000;
const JWT_SECRET = 'your_jwt_secret_key';
app: The Express application instance.
PORT: The port the server will listen on.
JWT_SECRET: A secret key used to sign JWTs. Replace this with a secure, randomly generated value in production.
3. Database Connection Setup
const db = await mysql.createConnection({
host: 'localhost',
user: 'your_mysql_user',
password: 'your_mysql_password',
database: 'user_auth'
});
db: The MySQL database connection object.
mysql.createConnection(): Establishes a connection to the MySQL database using async/await, which is needed for non-blocking queries.
host: Yout MySql application hostname, If you are running it on localhost, put localhost only, if you have deployed your MySql to a server, use the server hostname with PORT.
user: Your MySql Username
password: Your MySql Password
database: The Database name
4. Middleware Setup
app.use(express.json());
app.use(cookieParser());
express.json(): Middleware to parse JSON request bodies.
cookieParser(): Middleware to parse cookies, allowing us to read cookies from req.cookies.
5. Register Route
/register
This route registers a new user by hashing their password and saving it in the database.
app.post('/register', async (req, res) => {
const { name, email, password } = req.body;
try {
// Check if user already exists
const [rows] = await db.execute('SELECT * FROM users WHERE email = ?', [email]);
if (rows.length > 0) {
return res.status(400).json({ message: 'User already exists' });
}
// Hash the password
const hashedPassword = await bcrypt.hash(password, 10);
// Save the user in the database
await db.execute('INSERT INTO users (name, email, password) VALUES (?, ?, ?)', [name, email, hashedPassword]);
res.status(201).json({ message: 'User registered successfully!' });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server error' });
}
});
db.execute(): Executes a query to check if a user with the given email already exists. If they do, return a 400 status.
bcrypt.hash(password, 10): Hashes the password with a salt rounds value of 10 for security.
db.execute() (Insert): Saves the user's name, email, and hashed password in the database.
6. Login Route
/login
This route logs in an existing user by checking their credentials and generating a JWT token.
app.post('/login', async (req, res) => {
const { email, password } = req.body;
try {
// Find user
const [rows] = await db.execute('SELECT * FROM users WHERE email = ?', [email]);
const user = rows[0];
if (!user) {
return res.status(400).json({ message: 'User not found' });
}
// Check password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ message: 'Invalid credentials' });
}
// Create JWT token
const token = jwt.sign({ id: user.id, name: user.name, email: user.email }, JWT_SECRET, { expiresIn: '1h' });
// Set JWT in cookie
res.cookie('token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'Strict',
maxAge: 3600000 // 1 hour
});
res.json({ message: 'Logged in successfully!' });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server error' });
}
});
bcrypt.compare(password, user.password): Verifies if the hashed password matches the one stored in the database.
jwt.sign(): Creates a JWT that includes user information (e.g., ID, name, and email). The token expires in 1 hour. jwt.sign() method takes two arguments payload, JWT_SECRET, options(optional)
res.cookie(): Sets a cookie with the JWT, secured by httpOnly (only accessible by the server) and sameSite settings.
7. JWT Verification Middleware
The verifyToken middleware ensures that only requests with a valid JWT token can access protected routes.
const verifyToken = (req, res, next) => {
const token = req.cookies.token;
if (!token) return res.status(403).json({ message: 'Token is missing.' });
try {
const decoded = jwt.verify(token, JWT_SECRET);
req.user = decoded;
next();
} catch (err) {
res.status(401).json({ message: 'Invalid token.' });
}
};
req.cookies.token: Extracts the token from cookies.
jwt.verify(token, JWT_SECRET): Verifies the token using the JWT secret key. If valid, decoded **contains the token’s payload, which is assigned to **req.user.
next(): Proceeds to the next middleware if the token is valid.
8. Protected Route - /protected
A sample protected route accessible only to authenticated users. It returns a personalized greeting using the user’s name from the token.
app.get('/protected', verifyToken, (req, res) => {
res.json({ message: `Hello, ${req.user.name}! This is a protected route.` });
});
verifyToken: Middleware applied to check the user’s authentication status.
req.user.name: Accesses the user’s name from the decoded JWT payload.
9. Start the Server
The server listens on the defined PORT.
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Full Code
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const cookieParser = require('cookie-parser');
const mysql = require('mysql2/promise');
const app = express();
const PORT = 3000;
const JWT_SECRET = 'your_jwt_secret_key';
// MySQL connection setup (async function to allow using await)
const initializeDatabase = async () => {
return mysql.createConnection({
host: 'localhost',
user: 'your_mysql_user',
password: 'your_mysql_password',
database: 'user_auth'
});
};
// Middleware
app.use(express.json());
app.use(cookieParser());
// Register Route
app.post('/register', async (req, res) => {
const { name, email, password } = req.body;
try {
const db = await initializeDatabase();
// Check if user already exists
const [rows] = await db.execute('SELECT * FROM users WHERE email = ?', [email]);
if (rows.length > 0) {
return res.status(400).json({ message: 'User already exists' });
}
// Hash the password
const hashedPassword = await bcrypt.hash(password, 10);
// Save the user in the database
await db.execute('INSERT INTO users (name, email, password) VALUES (?, ?, ?)', [name, email, hashedPassword]);
res.status(201).json({ message: 'User registered successfully!' });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server error' });
}
});
// Login Route
app.post('/login', async (req, res) => {
const { email, password } = req.body;
try {
const db = await initializeDatabase();
// Find user
const [rows] = await db.execute('SELECT * FROM users WHERE email = ?', [email]);
const user = rows[0];
if (!user) {
return res.status(400).json({ message: 'User not found' });
}
// Check password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ message: 'Invalid credentials' });
}
// Create JWT token
const token = jwt.sign({ id: user.id, name: user.name, email: user.email }, JWT_SECRET, { expiresIn: '1h' });
// Set JWT in cookie
res.cookie('token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'Strict',
maxAge: 3600000 // 1 hour
});
res.json({ message: 'Logged in successfully!' });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server error' });
}
});
// Middleware to verify JWT
const verifyToken = (req, res, next) => {
const token = req.cookies.token;
if (!token) return res.status(403).json({ message: 'Token is missing.' });
try {
const decoded = jwt.verify(token, JWT_SECRET);
req.user = decoded;
next();
} catch (err) {
res.status(401).json({ message: 'Invalid token.' });
}
};
// Protected Route
app.get('/protected', verifyToken, (req, res) => {
res.json({ message: `Hello, ${req.user.name}! This is a protected route.` });
});
// Start server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Summary
This application:
- Allows user registration by hashing passwords and storing user data in MySQL.
- Supports secure login with JWT authentication.
- Uses cookies to store the JWT on the client side.
- Provides middleware for verifying JWTs before granting access to protected routes.
SOCIAL SHARE CARD GENERATOR