Аутентификация пользователя с использованием Passport.js, express-session и express-mysql-session

Я пытаюсь создать аутентификацию пользователя с помощью Node.js, Express, Passport.js и базы данных MySql. Я могу регистрировать пользователей (исключены из кода для облегчения чтения), а также могу войти в систему (я получаю SuccesscesRedirect из паспорта), но я не могу сериализовать пользователя, и я почти уверен что-то не так с моим сеансом.

Когда я запускаю свой код, я получаю следующую ошибку:

Ошибка: не удалось сериализовать пользователя в сеанс

Вот мой код:

var express             = require('express'),
    app                 = express(),
    bodyParser          = require('body-parser'),
    mysql               = require('mysql'),
    generator           = require('generate-password'),
    cookieParser        = require('cookie-parser'),
    expressValidator    = require('express-validator'),
    session             = require('express-session'),
    passport            = require('passport'),
    MySQLStore          = require('express-mysql-session')(session),
    LocalStrategy       = require('passport-local').Strategy,
    bcrypt              = require('bcrypt');

const saltRounds = 10;

app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
app.use(bodyParser.urlencoded({extended: true}));
app.use(expressValidator());
app.use(cookieParser());
var options = {
   host     : 'localhost',
   user     : 'MY-USER',
   database : "c9",
   password : "",
   multipleStatements: true
};

var sessionStore = new MySQLStore(options);

app.use(session({
   secret: 'dfsfjdssdvsdvawdslepsv',
   resave: true,
   store: sessionStore,
   saveUninitialized: true
}));

app.use(passport.initialize()); 
app.use(passport.session());

//Start MYSQL database
var connection = mysql.createConnection({
   host     : 'localhost',
   user     : 'MY-USER',
   database : "c9",
   password : "",
   multipleStatements: true
});
connection.connect(function(err){
    if(!err) {
        console.log("Database is connected ...");
    } else {
        console.log("Error connecting database ...");
    }
});

app.get("/", isAuthenticated, function(req, res, next){
    res.render('dashboard');
});

//show login form
app.get("/login", function(req, res){
    res.render("login");
});

//login
app.post("/login", passport.authenticate(
    'local', {
        successRedirect: '/',
        failureRedirect: '/login'
}));

//create new user
app.post("/users", function(req, res){
    var today = new Date();
    //generate password + salt
    var password = generator.generate({
                length: 8,
                numbers: true,
                symbols: false
    });
    var salt = bcrypt.genSaltSync(saltRounds);
    var hash = bcrypt.hashSync(password, salt);
    console.log(salt);
            
    //create user object
    var user = {
        first_name  : req.body.first_name,
        last_name   : req.body.last_name,
        email       : req.body.email,
        password    : hash,
        salt        : salt,
        created     : today,
        modified    : today,
        user_role   : req.body.user_role
    };

    //check if email already exists in database
    connection.query('SELECT email FROM users WHERE email=?', user.email, function(error, results, fields){
        if(error) {
            throw error;
        }
        if(results.length > 0) {
            //email already exists in database
            res.redirect("/");
            return;
        } else {
            //email does not exist from before
            //add user to database
            connection.query('INSERT INTO users SET ?', user, function(err, result) {
            if(err) throw err;
            
            connection.query('SELECT LAST_INSERT_ID() as user_id', function(error, results, fields){
               if(error) throw error;
               
            });
            
            //Send registration email
            res.redirect("users");
            });
        }
    });
});

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

passport.deserializeUser(function(id, done){
    connection.query('SELECT * FROM users WHERE id = ?', id, function (err, rows){
        done(err, rows[0]);
    });
});

//Authenticate users
passport.use(new LocalStrategy(
    function(username, password, done) {
        connection.query('SELECT password, salt FROM users WHERE email = ?', [username], function(err, results, fields){
            //DB error
            if(err) {done(err)};
            
            //no user was found
            if(results.length === 0) {
                done(null, false);
            }
            
            var salt = results[0].salt;
            if(bcrypt.hashSync(password, salt) === results[0].password) {
                //Success
                return done(null, true);
            } else {
                //Wrong password
                return done(null, false);
            }
        });
    }
));

function isAuthenticated(req, res, next) {
    if (req.isAuthenticated())
        return next();
    res.redirect('/login');
}

app.listen(process.env.PORT, process.env.IP, function(){
    console.log("Server started...");
});

Мне кажется, что я делаю именно то, что смог прочитать из различных руководств и документации. Кто-нибудь может увидеть, где я терплю неудачу?

База данных пользователей выглядит так:

CREATE TABLE `users` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `first_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
 `last_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
 `email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
 `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `salt` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `created` datetime NOT NULL,
 `modified` datetime NOT NULL,
 `user_role` varchar(100) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

База данных сеанса выглядит так:

CREATE TABLE IF NOT EXISTS `sessions` ( 
`session_id` varchar(128) COLLATE utf8mb4_bin NOT NULL, 
`expires` int(11) unsigned NOT NULL, 
`data` text COLLATE utf8mb4_bin, 
PRIMARY KEY (`session_id`) 
) ENGINE=InnoDB


person Elias    schedule 11.05.2018    source источник


Ответы (1)


Нашел проблему.

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

Следует взять и отправить идентификатор пользователя. В моем коде это был пользователь.

Теперь это решено!

person Elias    schedule 11.05.2018