Search code examples
mysqlnode.jsexpressbcrypt

How to compare using bcrypt in a db query using node.js and express


First off, I'm new to using express and this is my first attempt at creating an authentication page. I've connected to a MySQL database and successfully queried the database unhashed passwords, but as soon as I attempt to use a hashed password and compare with bcrypt.compare I get an "app crashed - waiting for file changes before starting" error.

Here's my code:

const express = require("express");
const mysql = require("mysql");
const cors = require("cors");
const bcrypt = require('bcryptjs')

const app = express();

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

const db = mysql.createConnection({
  host: "localhost",
  user: "useraccount",
  password: "useraccount",
  database: "users",
});

app.post('/login', (req, res) => {
  const sql = 'SELECT password FROM auth_table WHERE email = ?'

  db.query(sql, req.body.email, (err, data) => {
    if (err) return res.json("Error.");
    if (data.length > 0) {
      bcrypt.compare(req.body.password, res.json(data), function (err, result) {
        if (err) throw err;
        if (result) {
          return res.json("Login Successful.");
        }
      })
    } else {
      return res.json("Login Failed.")
    }

  })
})

app.listen(8081, () => {
  console.log("Listening....");
});

I've commented out the bcrypt logic and it works fine, so I'm pretty sure it down to that snippet. And when I check the http response in the inspector I get [{"password":"$2a$13$kZX7p1/gfjWRnGHf8gcWouqWKQsOjKrCfheG.owf93OWfygFZJzye"}].


Solution

  • You're sending the database query result as a response before bcrypt.compare executes. Since res.json(data) immediately returns the response, the password comparison process doesn't get a chance to run.

    Also, I think the query returns an array of objects ([{"password":"hashed_value"}]), but instead of extracting the hashed password, you're passing the entire response object.

    I hope this would work:

    app.post('/login', (req, res) => {
      const sql = 'SELECT password FROM auth_table WHERE email = ?';
    
      db.query(sql, [req.body.email], (err, data) => {
        if (err) return res.json({ error: "Database error" });
        
        if (data.length > 0) {
          const hashedPassword = data[0].password; // Extract the hashed password from the first row
    
          bcrypt.compare(req.body.password, hashedPassword, (err, result) => {
            if (err) return res.json({ error: "Bcrypt error" });
    
            if (result) {
              return res.json({ message: "Login Successful" });
            } else {
              return res.json({ message: "Invalid Credentials" });
            }
          });
        } else {
          return res.json({ message: "User not found" });
        }
      });
    });