i'm have trouble with comparing stored hashed passwords with user entered password in my login endpoint to give users access, below is my server.js file where my signup and login endpoints are.
const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const mongoose = require('mongoose');
const cors = require('cors');
const secretKey = require('./jwt-token');
const app = express();
app.use(cors());
app.use(express.json());
// MongoDB connection URI
const uri = 'mongodb://localhost:27017/final-year-project';
// Connect to the MongoDB database
mongoose
.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log('Connected to the database');
app.listen(3000);
console.log('app connected on port 3000');
})
.catch((error) => {
console.error('Failed to connect to the database:', error);
});
// Define the user schema
const userSchema = new mongoose.Schema({
firstName: { type: String, required: true },
lastName: { type: String, required: true },
email: { type: String, required: true, unique: true },
role: { type: String, required: true },
password: { type: String, required: true },
}, { collection: 'users' });
// Define the user model
const User = mongoose.model('User', userSchema);
class AuthResponseData {
constructor(user) {
this.user = user;
}
}
// Signup endpoint
app.post('/signup', async (req, res) => {
try {
// Extract user data from request body
const {
firstName,
lastName,
email,
role,
password } = req.body;
// Check if email is already taken
const existingUser = await User.findOne({ email });
if (existingUser) {
return res.status(400).json({ message: 'Email already exists' });
}
// Set a default password if the provided password is empty
let plainTextPassword = password;
if (!plainTextPassword) {
plainTextPassword = 'defaultPassword123';
}
// Generate a salt asynchronously
bcrypt.genSalt(10, (saltError, salt) => {
if (saltError) {
console.error('Error generating salt:', saltError);
return res.status(500).json({ message: 'Internal server error' });
}
// Hash the password asynchronously
bcrypt.hash(plainTextPassword, salt, async (hashError, hashedPassword) => {
if (hashError) {
console.error('Error hashing password:', hashError);
return res.status(500).json({ message: 'Internal server error' });
}
try {
// Create a new user object
const newUser = new User({
firstName,
lastName,
email,
role,
password: hashedPassword,
});
// Save the user to the database
await newUser.save();
// Generate a JSON Web Token (JWT)
const token = jwt.sign({ email: newUser.email }, secretKey);
// Set token expiration date (e.g., 1 hour from now)
const expirationDate = new Date().getTime() + 3600000;
// Create a new user instance
const user = {
firstName: newUser.firstName,
lastName: newUser.lastName,
email: newUser.email,
role: newUser.role,
id: newUser._id,
_token: token,
_tokenExpirationDate: expirationDate,
};
// Return the authentication response with user details
const authResponse = new AuthResponseData(user);
res.status(201).json(authResponse);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Internal server error' });
}
});
});
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Internal server error' });
}
console.log(req.body)
});
// Login endpoint
app.post('/login', async (req, res) => {
try {
// Extract user data from request body
const { email, password } = req.body;
const userEmail = req.body.email;
const userPassword = req.body.password;
console.log(userEmail);
console.log(userPassword);
// Find the user in the database
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ message: 'Invalid email or password' });
};
console.log('user verified');
hashedPasswordFromDb = user.password;
console.log(hashedPasswordFromDb);
console.log(userPassword);
// Compare passwords
bcrypt.compare(userPassword, hashedPasswordFromDb, (passwordError, passwordMatch) => {
if (passwordError) {
console.error('Error comparing passwords:', passwordError);
return res.status(500).json({ message: 'Internal server error' });
}
console.log(passwordError);
console.log(passwordMatch);
if (!passwordMatch) {
return res.status(401).json({ message: 'Invalid email or password' });
}
console.log(passwordMatch);
// Generate a JSON Web Token (JWT)
const token = jwt.sign({ email: user.email }, secretKey);
// Set token expiration date (e.g., 1 hour from now)
const expirationDate = new Date().getTime() + 3600000;
// Create a new user instance
const loggedInUser = {
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
role: user.role,
id: user._id,
_token: token,
_tokenExpirationDate: expirationDate,
};
// Return the authentication response with user details
const authResponse = new AuthResponseData(loggedInUser);
res.status(200).json(authResponse);
});
} catch (error) {
console.error('Error:', error); // Log the detailed error message
console.error('Stack trace:', error.stack); // Log the stack trace
res.status(500).json({ message: 'Internal server error' });
}
});
i logged things onto the console at intervals to see where the error starts from cause an error isn't logged onto the console and the code breaks here:
if (!passwordMatch) {
return res.status(401).json({ message: 'Invalid email or password' });
}
I tried hashing the user entered password to compare with the stored hashed password and also comparing directly but to no avail.