0

No matter what I change the user login will keep redirecting to failure instead of success. I don't know if I'm missing something or if I did something wrong. I tried to read the documentation for passport but, I found it pretty confusing. Here is my github link if you need to see the rest of the code. The node files are in app.js and passport-config.js.The sign up part of the website is working. https://github.com/gego144/to-do-list-website/tree/main

const customFields = {
    usernameField: 'email',
    passwordField: 'password'
}

const verifyCallback = (username, password, done) => {
          user_exists = userName_Checker(username), function (err, user) {
            if (err) { return done(err); }
            if (userName_Checker(username) == false) {
                console.log('wrong user');
              return done(null, false, { message: 'Incorrect username.' });
            }
            if (password_finder(username, password)) {
                console.log('wrong pass');
              return done(null, false, { message: 'Incorrect password.' });
            }
            console.log('wtf');
            return done(null, user);
          };  
      ;

}

const strategy = new LocalStrategy(customFields, verifyCallback);

passport.use(strategy);

passport.serializeUser(function(user, done) {
    done(null, user);
});


passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
      done(err, user);
    });
});


// function that checks to see if the users email is in the database
function userName_Checker(email_name){
    
    var sql = "select * from info where email = ?";
    var user_email = [[email_name]];

    db.query(sql, [user_email],function (err,result){
        if (err) throw err;
        var not_unique = result.length;
        if(not_unique == 0){
            return false;
        }
        else{
            return true;
        }
    }
    )}


// function that checks to see if the password in the database matches with the email
function password_finder(email_name, pass){
    var sql = "SELECT password FROM info WHERE email = ?";
    var user_email = [[email_name]];
    db.query(sql, [user_email],function (err,result){
        if (err) throw err;
        
        bcrypt.compare(result, pass, function(err, res){
            if(err){ throw err};
            if(res){
                return true;
            }
            else{
                return false;
            }
        })
    }
)}

My post method in my other file.

app.post('/login', passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect:'/index.html',
    failureFlash: true
}))

Edit 1. I just want to mention that the console.logs you see in verify Callback all don't log anything for some reason too.

gego144
  • 13
  • 4

1 Answers1

0

The problem might be in the serialization logic.

In passport.serializeUser, you are passing in the whole user object, but when deserializing you are passing the id

Though I am not using SQL, the logic should be similar.

So the code should be something like this:

//  Session
// Pass in user id => keep the session data small
passport.serializeUser((id, done) => {
    done(null, id);
});

// Deserialize when needed by querying the DB for full user details
passport.deserializeUser(async (id, done) => {
    try {

        const user = await User_DB.findById(id);
        done(null, user);
    } catch (err) {

        console.error(`Error Deserializing User: ${id}: ${err}`);
    }

});
// Export the passport module
module.exports = (passport) => {

    passport.use(new LocalStrategy({ usernameField: 'email', }, async (email, password, done) => {

        try {

            // Lookup the user 
            const userData = await User_DB.findOne({ email: email, }, { 
            password: 1, }); // Return the password hash only instead of the whole user object

            // If the user does not exist
            if (!userData) {

                return done(null, false);
            }

            // Hash the password and compare it to the hash in the database
            const passMatch = await bcrypt.compare(password, userData.password);

            // If the password hash does not match
            if (!passMatch) {
                return done(null, false);
            }

            // Otherwise return the user id
            return done(null, userData.id);

        } catch (err) {
            passLog.error(`Login Error: ${err}`);
        }

    }));
};

These options for passport seems to malfunction a lot or exhibit weird behaviors, so I suggest you handle the redirection logic like in my controller.

{ successRedirect: '/good',
 failureRedirect: '/bad' }

Login controller logic: (I am omitting the code here for session storage and made some modifications, but this code should work for what you need)

const login = (req, res, next) => {

    //Using passport-local
    passport.authenticate('local', async (err, user) => {


        //If user object does not exist => login failed
        if (!user) { return res.redirect('/unauthorized'); }


        //If all good, log the dude in
        req.logIn(user, (err) => {

            if (err) { return res.status(401).json({ msg: 'Login Error', }); }

            // Send response to the frontend
            return res.redirect('/good');
        });

      
        });
    })(req, res, next);


};

The actual route:

//  Import the controller
const {login} = require('../controllers/auth');

// Use it in the route
router.post('/auth/login', login);
Algo7
  • 2,122
  • 1
  • 8
  • 19
  • I tried to copy and paste ur code replacing my user serialization and it still redirects to failure. – gego144 Jan 12 '21 at 00:43
  • I get the error "Error: Cannot find module '../controllers/auth". Is ''../controllers/auth" part of passport? – gego144 Jan 12 '21 at 02:04
  • No. My bad. Should have clarified `../controllers/auth` is where I store the controller file. You know about controllers right? Instead of putting everything under the route. You can put all those functions in a separate file and load them as a middleware. It just a way to make the code simpler and modular. It has nothing to do with passport directly. – Algo7 Jan 12 '21 at 02:09
  • Should I put both the module.export method and the log in method inside 'controllers/auth'? I was wondering that because if I do isn't the log in one never being called? Or should I put the log in method inside of my app.js and change the variable name? – gego144 Jan 12 '21 at 02:56
  • Put the passport itself (module.export) in to a file by itslef. The controller with the loging logic in a file. and the route in a file. – Algo7 Jan 12 '21 at 07:20
  • How do I import the controller with the logging logic? When you say router are you talking about the variable I use for express? Mine is 'const app = express();'. So just replace where you say router with app? – gego144 Jan 12 '21 at 19:55