skip to Main Content

Hey I am trying to make a simple auth login system using mongodb and passport.js, the signup works, the problem is with the login. I have searched the world wide web for an answer but can’t seem to find anything that fits my problem.

When trying to login with correct credentials I get this error message => enter image description here

Login.jsx =>

=> import { useState } from "react";

const Login = () => {
  const [error, setError] = useState("");
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [data, setData] = useState(null);

  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
      const response = await fetch("http://localhost:3000/auth/login", {
        method: "POST",
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          username: username,
          password: password,
        }),
      });

      console.log("Response from server:", response);

      if (response.ok) {
        const data = await response.json();
        console.log("Login successful");
      } else {
        const errorData = await response.json();
        console.log("Login failed:", error, errorData)
      }
    } catch (error) {
      console.error("Login error:", error);
      setError("An error occurred")
    }
  }

  return (
    <form method="post" onSubmit={handleSubmit}>
      <div id="create-account" className="flex flex-col items-center pt-12">
        <div id="signup-text" className="pr-24">
        <div id="signup-text" className="flex items-center">
          <h1 className="font-semibold text-2xl">Login</h1>
          <span className="text-2xl ml-2">🔐</span>
        </div>
          <h2 className="">Enter your details below to login</h2>
        </div>
        <div id="signup-container" className="pr-2">
        <div id="username" className="flex pt-2 space-y-3">
            <input
              type="username"
              onChange={(e) => setUsername(e.target.value)}
              id="email-user"
              className="border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-80 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
              placeholder="Email or Username"
              required
            />
          </div>
          <div id="password" className="flex items-center pt-2">
          <input
              type="password"
              id="pass"
              onChange={(e) => setPassword(e.target.value)}
              className="border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-80 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
              placeholder="Password"
              required
            />
          </div>
            <button 
            type="submit" 
            className="mt-2 text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700">Login</button>
        </div>
        <div id="or" className="flex items-center pt-6">
          <hr className="flex-grow border-t border-gray-400" />
          <h2 className="px-4">Or</h2>
          <hr className="flex-grow border-t border-black-400" /> 
        </div>
      </div>
    </form>
  )
};

export default Login;

I also get this error from my server => enter image description here

Server.js =>

import express from "express";
import mongoose from "mongoose";
import UserModel from "./database/models/user.js";
import mongoConnection from "./database/index.js";
import cors from "cors";
import bodyParser from "body-parser";
import session from "express-session";
import bcrypt from "bcrypt";
import passport from "passport";
import passportConfig from "./config/passport-config.js";
import jwt from "jsonwebtoken"; 
import { Strategy } from "passport-local";

const app = express();
const PORT = 3000;

// Middleware ----------------------
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// making sure requests from the client side work
app.use(cors({
  origin: "http://localhost:5173",
  credentials: true,
}));

// session cookies
app.use(
  session({
    secret: "secretcode",
    resave: true,
    saveUninitialized: true
  })
);

// ---- end of middleware

// signup
app.post("/user", async (req, res) => {
  try {
    // check if user or email already exists
    const existingUser = await UserModel.findOne({ username: req.body.username });
    const existingEmail = await UserModel.findOne({ email: req.body.email });

    if (existingUser) {
      return res.status(400).send("Username already exists");
    } if (existingEmail) {
      return res.status(400).send("Email already exists");
    }

    // hash password before save
    const hashedPassword = await bcrypt.hash(req.body.password, 10);
    const user = new UserModel({
      username: req.body.username,
      email: req.body.email,
      password: hashedPassword,
    });

    // saving users to db/mongo
    await user.save();
    res.send(user);
    console.log("saved user: ", user)
  } catch (error) {
    console.error(error);
    res.status(500).send(error);
  }
});

passportConfig(passport);

// login
app.post("/auth/login", (req, res, next) => {
  console.log("Recieved login request:", req.body);
  
  passport.authenticate("login", (err, user) => {
    if (err) throw err;
    console.log("User found in the db:", user);

    if (!user) {
      res.status(401).json({ message: "No user exists" })
    }
    else {
      req.logIn(user, (err) => {
        if (err) throw err;
        res.send("Successfully Authenticated");
        console.log(req.user);
      });
    }
  })(req, res, next);
});
 
// starting server
app.listen(PORT, function(err) {
  if (err) {
    console.log("server could not start", err) 
  } else {
    console.log("Server listening on Port:", PORT)
  }
})

User.js =>

import { Schema, model } from "mongoose";
import bcrypt from "bcrypt";

// defining schema
const userSchema = new Schema({
  username: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
});


// comparing password, if true match
userSchema.methods.matchPassword = async function (password) {
  try {
    return await bcrypt.compare(password, this.password);
  } catch (error) {
    console.error(error);
  }
}

const UserModel = model("User", userSchema);

export default UserModel;

Passport-config.js =>

  import passport from "passport";
import UserModel from "../database/models/user.js";
import bcrypt from "bcrypt";
import { Strategy as LocalStrategy } from "passport-local";

export default (passport) => {
  // signup stratergy
  passport.use(
    "local-signup",
    new LocalStrategy(
      {
        usernameField: "email",
        passwordField: "password",
      },
      async (email, password, done) => {
        try {
          // Check if user already exists
          const userExists = await UserModel.findOne({ email: email });
          if (userExists) {
            return done(null, false);
          }

          // Create a new user with the provided data
          const user = await UserModel.create({ email, password });
          return done(null, user);
        } catch (error) {
          return done(error);
        }
      }
    )
  );

  // login stratergy
  passport.use(
    "login",
    new LocalStrategy(
      {
        usernameField: "username",
        passwordField: "password",
      },
      async (username, password, done) => {
        try {
          const user = await UserModel.findOne({ username: username });
          if (!user) {
            return done(null, false, { message: "User not found" });
          }
          
          const isMatch = await bcrypt.compare(password, user.password);
          if (!isMatch) {
            return done(null, false, { message: "Invalid password" });
          }

          // If passwords match, return the user
          return done(null, user);
        } catch (error) {
          console.log(error);
          return done(error, false);
        }
      }
    )
  );
};

passport.serializeUser((user, done) => {
  done(null, user.id)
});

passport.deserializeUser(async (id, done) => {
  try {
    const user = await UserModel.findById(id);
    done(null, user);
  } catch (err) {
    done(err);
  }
});

Would greatly appreciate any help as I have been stuck on this for a while now!

2

Answers


  1. Chosen as BEST ANSWER

    The issue was as phil described. My

    usernameField: "username",
    passwordField: "password"
    

    Was not the same as the code being sent in the client.


    1. the Cors issue
      In relation to your cors issue, first open it up to all origins to test if that works for you. You can do that by
    // making sure requests from the client side work
    app.use(cors());
    
    or
    
    // making sure requests from the client side work
    app.use(cors({
      origin: "*"
    }));
    1. In relation to the user found in db:false. it could be one of many things
      To list a few:

    2. Password hash comparison: Verify the password passed in the login route is being compared correctly

    3. DB Query: Check what is return from the

      User.findOne({…})

    Tip:
    In the deserializeUser function, you have a typo. Replace await

    user.findById(id); with await UserModel.findById(id); 
    

    to correctly retrieve the user by ID.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search