0

I am making a login route with jwt token and express. When I create an account, the password is hashed by bcrypt. When I log in, I need to compare them. I tried with simplest password but it didn't work. So here is my try :

const express = require("express"); const bcrypt = require("bcryptjs"); const jwt = require("jsonwebtoken"); const User = require("../models/User"); const { verifyAdmin } = require("../middleware/authMiddleware"); const router = express.Router(); router.post("/login", async (req, res) => { const { username, password } = req.body; try { const user = await User.findOne({ username }); if (!user) { return res.status(400).json({ message: "Invalid credentials" }); } // Log the received and hashed passwords for debugging console.log("Received password:", password); console.log("Stored hashed password:", user.password); const isMatch = await bcrypt.compare(password, user.password); console.log("Password match result:", isMatch); if (!isMatch) { return res.status(400).json({ message: "Invalid credentials" }); } const payload = { user: { id: user.id, userType: user.userType, }, }; jwt.sign( payload, process.env.JWT_SECRET, { expiresIn: "1h" }, (err, token) => { if (err) throw err; res.json({ token, user }); } ); } catch (err) { console.error(err.message); res.status(500).send("Server error"); } }); // Create User router.post("/create", async (req, res) => { const { name, username, password, userType, process } = req.body; try { const hashedPassword = await bcrypt.hash(password, 10); const newUser = new User({ name, username, password: hashedPassword, userType, process: userType === "Process Department" ? process : undefined, }); await newUser.save(); res.status(201).json({ message: "User created successfully" }); } catch (error) { res.status(500).json({ error: error.message }); } }); module.exports = router; 

The problem is, my route returns "Invalid credentials".

Create user frontend -->

// src/redux/reducers/userSlice.js import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; import api from "../../api/axiosConfig"; export const createUser = createAsyncThunk( "user/createUser", async (userData, thunkAPI) => { try { const response = await api.post("/auth/create", userData ); return response.data; } catch (error) { return thunkAPI.rejectWithValue(error.response.data.message); } } ); const userSlice = createSlice({ name: "user", initialState: { isLoading: false, success: false, error: null, }, reducers: { resetState: (state) => { state.isLoading = false; state.success = false; state.error = null; }, }, extraReducers: (builder) => { builder .addCase(createUser.pending, (state) => { state.isLoading = true; state.success = false; state.error = null; }) .addCase(createUser.fulfilled, (state) => { state.isLoading = false; state.success = true; state.error = null; }) .addCase(createUser.rejected, (state, action) => { state.isLoading = false; state.success = false; state.error = action.payload; }); }, }); export const { resetState } = userSlice.actions; export default userSlice.reducer; 

Login frontend -->

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; import api from "../../api/axiosConfig"; export const login = createAsyncThunk( "auth/login", async ({ username, password }, thunkAPI) => { try { const response = await api.post("/auth/login", { username, password, }); return response.data; } catch (error) { return thunkAPI.rejectWithValue(error.response.data.message); } } ); export const logout = createAsyncThunk("auth/logout", async (_, thunkAPI) => { // perform any necessary cleanup here return true; }); const authSlice = createSlice({ name: "auth", initialState: { isLoading: false, user: null, error: null, }, reducers: {}, extraReducers: (builder) => { builder .addCase(login.pending, (state) => { state.isLoading = true; state.error = null; }) .addCase(login.fulfilled, (state, action) => { state.isLoading = false; state.user = action.payload.user; state.error = null; }) .addCase(login.rejected, (state, action) => { state.isLoading = false; state.user = null; state.error = action.payload; }) .addCase(logout.fulfilled, (state) => { state.user = null; state.error = null; }); }, }); export default authSlice.reducer; 

My console information

 Received password: vishesh Stored hashed password: $2a$10$xxZgmq63qYyIRZ5DypwjbOF4fthtMm/m4qJE6sOytsCVxJzn2SRQy Password match result: false 
7
  • 1
    added please check Commented Jul 26, 2024 at 23:28
  • 1
    The hash $2a$10$xxZgmq63qYyIRZ5DypwjbOF4fthtMm/m4qJE6sOytsCVxJzn2SRQy does not appear to be valid for your password vishesh: When using bcrypt to generate a hash from password and salt, the hash is different, namely $2a$10$xxZgmq63qYyIRZ5DypwjbO9sI.9V5Gs/loT0eWMO.0xFtGCTUEOYa (see here), which can be verified with a third library, e.g. CyberChef (see here). So check your data please. Commented Jul 27, 2024 at 7:47
  • Do you have a pre('save') hook set-up? For example if(this.isModified('password')) where you hash the password? If so you don't need to manually hash the password in your router.post("/create") route. The middleware will handle it on user creation. You might be unwittingly hashing the password twice. Commented Jul 27, 2024 at 8:37
  • @Topaco The hash will be different every time, for the same input. That's the entire point of using a salt. Commented Jul 31, 2024 at 4:48
  • @user229044 - You misunderstood my comment. The OP is asking why the compare() call is failing. The reason is that the OP's data is inconsistent. If you use the posted password and the salt of the posted hash, the result is a different hash than the posted one. So the data is inconsistent (for whatever reason), which is the reason for the failed verification. Commented Jul 31, 2024 at 6:53

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.