Creating Secure Password Flows With Node.js And MySQL
- Published on
Creating secure password flows is crucial for any web application to protect user data and maintain trust. In this blog post, we'll walk through how to set up secure password flows using Node.js and MySQL. We'll cover user registration, password hashing, secure storage, and user authentication.
Prerequisites
Before we start, ensure you have the following installed:
- Node.js and npm
- MySQL
- A code editor (like VSCode)
Setting Up the Project
Step 1: Initialize the Node.js Project
First, create a new directory for your project and initialize it with npm.
mkdir secure-password-flow
cd secure-password-flow
npm init -y
Step 2: Install Dependencies
We'll need several npm packages to build our application:
express
: Web framework for Node.jsmysql2
: MySQL client for Node.jsdotenv
: Loads environment variables from a.env
filebcrypt
: Library to hash and compare passwords
npm install express mysql2 dotenv bcrypt
Step 3: Set Up MySQL
Create a new MySQL database and a users table.
CREATE DATABASE secure_password_flow;
USE secure_password_flow;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL
);
Building the Application
Step 4: Set Up Environment Variables
Create a .env
file in the root of your project to store your database credentials.
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=secure_password_flow
Step 5: Create the Database Connection
Create a file named db.js
to handle the MySQL connection.
// db.js
const mysql = require('mysql2');
require('dotenv').config();
const connection = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
});
connection.connect((err) => {
if (err) {
console.error('Error connecting to the database:', err.stack);
return;
}
console.log('Connected to the database');
});
module.exports = connection;
Step 6: Set Up Express Server
Create a file named server.js
to set up the Express server.
// server.js
const express = require('express');
const bodyParser = require('body-parser');
const bcrypt = require('bcrypt');
const connection = require('./db');
const app = express();
const port = 3000;
app.use(bodyParser.json());
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
});
Step 7: Implement User Registration
In server.js
, add a route to handle user registration.
// server.js
// ... previous code ...
app.post('/register', async (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).send('Username and password are required');
}
try {
const hashedPassword = await bcrypt.hash(password, 10);
const query = 'INSERT INTO users (username, password) VALUES (?, ?)';
connection.query(query, [username, hashedPassword], (err, results) => {
if (err) {
console.error('Error inserting user:', err.stack);
return res.status(500).send('Error registering user');
}
res.status(201).send('User registered successfully');
});
} catch (error) {
console.error('Error hashing password:', error);
res.status(500).send('Internal server error');
}
});
Step 8: Implement User Login
Add a route to handle user login.
// server.js
// ... previous code ...
app.post('/login', (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).send('Username and password are required');
}
const query = 'SELECT * FROM users WHERE username = ?';
connection.query(query, [username], async (err, results) => {
if (err) {
console.error('Error querying user:', err.stack);
return res.status(500).send('Internal server error');
}
if (results.length === 0) {
return res.status(400).send('Invalid username or password');
}
const user = results[0];
try {
const match = await bcrypt.compare(password, user.password);
if (!match) {
return res.status(400).send('Invalid username or password');
}
res.status(200).send('Login successful');
} catch (error) {
console.error('Error comparing passwords:', error);
res.status(500).send('Internal server error');
}
});
});
Step 9: Test the Application
Start your server:
node server.js
Use tools like Postman or cURL to test the /register
and /login
endpoints.
Register a new user:
POST /register
Content-Type: application/json
{
"username": "testuser",
"password": "password123"
}
Login with the registered user:
POST /login
Content-Type: application/json
{
"username": "testuser",
"password": "password123"
}
Conclusion
By following these steps, you've created a secure password flow for user registration and login using Node.js and MySQL. Remember to always hash passwords before storing them and never store plaintext passwords. Additionally, continuously update your security practices to protect your users' data.
Happy coding!