node.jsexpressmongoosepassport.jspassport-local

Unable to login a User with passport.js


I've decided to start getting seriously interested in NodeJS and I really can't figure out the problem I've stumbled upon. I obviously searched extensively on Google and tried multiple solutions but nothing worked.

To summarize, I wanted to create a login system via a MongoDB database and I used passport.js to manage the login itself. The problem is that after a valid login from a user, the value of req.isAuthenticated() is always false in the middleware. I also used passport-local-mongoose which allows to generate directly a valid authentication for passport from a mongoose model.

app.js :

const express = require('express');
const cookieParser = require('cookie-parser');
const cookieSession = require('cookie-session');
const bodyParser = require('body-parser');

const mongoose = require('mongoose');
const passport = require('passport');

const app = express();

app.use(cookieSession({
    name: 'session',
    secret: 'secretkey',
    secure: false
}));
app.use(cookieParser('secretkey'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(passport.initialize());
app.use(passport.session());

const User = require('./models/user.js');
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

// Connect to MongoDB
mongoose.connect('mongodb+srv://?retryWrites=true&w=majority')
    .then(() => console.log('Connecion à MongoDB réussie !'))
    .catch((error) => console.log('Connexion à MongoDB échouée !\n' + error));

// Configure routes
app.use((request, response, next) => {
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization');
    response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
    next();
});
app.use('/api', require('./routes/authentication.js'));
app.use('/api/projects', require('./routes/project.js'));
app.use('/api/users', require('./routes/user.js'));

module.exports = app;

models/user.js

const mongoose = require('mongoose');
const {Schema} = require("mongoose");
const uniqueValidator = require('mongoose-unique-validator');
const passportLocal = require('passport-local-mongoose');

const userSchema = new Schema({
    email: {type: String, required: false},
    picture: {type: String, required: false},
    roles: {type: [String]},
});

userSchema.plugin(uniqueValidator);
userSchema.plugin(passportLocal);

module.exports = mongoose.model('user', userSchema);

routes/authentication.js :

const express = require('express');
const router = express.Router();
const passport = require("passport");
const User = require('../models/user');

router.post("/login", (req, res, next) => {
    console.log('authentication attempt with username: ' + req.body.username);
    passport.authenticate('local', {username: req.body.username, password: req.body.password}, (err, user, info) => {
        if (err)
            return next(err);
        if (!user)
            return res.status(400).send([user, "Cannot log in", info]);
        req.login(user, {}, (error) => {
            if (error) {
                console.log('error: ' + error);
                res.send("Error while login");
            } else {
                console.log('=> authenticated ' + user.username + ': ' + req.isAuthenticated());
                res.send("Logged in");
            }
        });
    })(req, res, next);
});

router.get('/logout', function (req, res) {
    req.logout();
    console.log("logged out")
    return res.send();
});

const authMiddleware = (req, res, next) => {
    if (req.isAuthenticated()) {
        return next();
    } else {
        res.status(401).send('You are not authenticated')
    }
};

router.get("/user", authMiddleware, (req, res) => {
    let user = User.find({'id': req.session._passport._user});

    console.log([user, req.session])
    res.send({'user': user})
});

module.exports = router;

Thank you in advance for your answers!


Solution

  • I think the problem might be in this block of code,

    // Configure routes
    app.use((request, response, next) => {
        response.setHeader('Access-Control-Allow-Origin', '*');
        response.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization');
        response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
        next();
    });
    

    response.setHeader('Access-Control-Allow-Credentials', 'true'); should be added to this as well as it allows credentials i.e. cookie or session-info to be in the cross-origin requests which is set to false by default. Which maintain user sessions and authenticate subsequent requests.