Creating Secure Password Flows With Node.js And MySQL

By Laraib Rabbani
Picture of the author
Published on
image alt attribute

Creating Secure Password Flows With Node.js And MySQL 🔐

Node.js, a popular JavaScript runtime environment, and MySQL, a widely used open-source relational database management system (RDBMS), are powerful tools for building web applications. However, handling user authentication and password management securely requires careful consideration of best practices and implementation techniques.

This guide will walk you through the process of creating secure password flows using Node.js, Express.js (a popular web framework for Node.js), and MySQL. It will cover essential aspects such as user registration, login, password hashing, and password reset.

Prerequisites 💻

Before you begin, ensure you have the following prerequisites:

  1. Node.js and npm installed on your system
  2. Basic understanding of Node.js, Express.js, and MySQL
  3. Familiarity with HTML, CSS, and JavaScript

Project Setup 🏗️

  1. Create a Node.js Project:
npx create-express-app my-secure-app

Install Necessary Dependencies:

npm install bcryptjs express-session mysql2

##Configure MySQL Connection: Create a .env file to store your MySQL connection details:

DB_HOST=localhost
DB_USER=root
DB_PASSWORD=password
DB_NAME=secure_app_db

Create Database and Tables:

Create the required tables in your MySQL database:

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  email VARCHAR(255) UNIQUE NOT NULL,
  password VARCHAR(255) NOT NULL,
  password_reset_token VARCHAR(255)
);

User Registration ✍️ Create User Registration Route:

  1. Create a route to handle user registration requests:
app.post('/register', async (req, res) => {
  const { email, password } = req.body;

  // Hash the password using bcryptjs
  const hashedPassword = await bcrypt.hash(password, 10);

  // Insert the user into the database
  await db.query('INSERT INTO users (email, password

User Registration ✍️

  1. Create User Registration Route: Create a route to handle user registration requests:
javascript
app.post('/register', async (req, res) => {
  const { email, password } = req.body;

  // Hash the password using bcryptjs
  const hashedPassword = await bcrypt.hash(password, 10);

  // Insert the user into the database
  await db.query('INSERT INTO users (email, password) VALUES (?, ?)', [email, hashedPassword]);

  // Send a success response
  res.status(201).send({ message: 'User registered successfully' });
});
  1. Password Hashing:

Password hashing is a crucial security measure that prevents passwords from being stored in plain text. bcryptjs, a popular password hashing library for Node.js, is used in this example to generate a secure hash of the user's password. The hashed password is stored in the database, and the original password is never stored or transmitted.

User Login 🔑

  1. Create User Login Route:

Create a route to handle user login requests:

javascript
app.post('/login', async (req) => {
  const { email, password } = req.body;

  // Retrieve the user from the database based on the provided email
  const user = await db.query('SELECT * FROM users WHERE email = ?', [email]);

  if (!user || !user.length) {
    return res.status(401).send({ message: 'Invalid email or password' });
  }

  // Compare the provided password with the stored hashed password
  const isPasswordValid = await bcrypt.compare(password, user[0].password);

  if (!isPasswordValid) {
    return res.status(401).send({ message: 'Invalid email or password' });
  }

  // Create a session and store the user's ID
  req.session.userId = user[0].id;

  // Send a success response
  res.send({ message: 'Login successful' });
});
  1. Password Comparison: When a user attempts to log in, the provided password is compared with the stored hashed password using bcryptjs's compare() method. This method securely compares the two passwords without revealing the original password. If the passwords match, the user is successfully logged in.

Password Reset 🔄

  1. Create Password Reset Request Route:

Create a route to handle password reset requests:

javascript
app.post('/request-password-reset', async (req) => {
  const { email } = req.body;

  // Generate a random password reset token
  const resetToken = generateToken();

  // Set the password reset token for the user
  await db.query('UPDATE users SET password_reset_token = ? WHERE email = ?', [resetToken, email]);

  // Send an email with the password reset link
  sendPasswordResetEmail(email, resetToken);

  // Send a success response
  res.send({ message: 'Password reset request sent successfully' });
});
  1. Password Reset Route: Create a route to handle password resets:
app.post('/reset-password', async (req) => {
  const { token, password } = req.body;

  // Verify the password reset token
  const user = await db.query('SELECT * FROM users WHERE password_reset_token = ?', [token]);

  if (!user || !user.length) {
    return res.status(401).send({ message: 'Invalid password reset token' });
  }

  // Hash the new password
  const hashedPassword = await bcrypt.hash(password, 10);

  // Update the user's password and clear the reset token
  await db.query('UPDATE users SET password = ?, password_reset_token = NULL WHERE id = ?', [hashedPassword, user[0].id]);

  // Send a success response
  res.send({ message: 'Password reset successful' });
});

Additional Considerations 🔐

  • Session Management: Express.js's express-session middleware is used in this example to manage user sessions. Sessions allow you to keep track of a user's logged-in state across requests.

  • Token-based Authentication: For more advanced security, consider implementing token-based authentication using JSON Web Tokens (JWTs).

  • Email Security: Use secure email practices

Laraib Rabbani Newsletter

Want to Stay Connected With Brown?
The best articles, links and news related to web development delivered once a week to your inbox.