Паспорт deserializeUser метод никогда не назывался

У меня есть ответ 200 для запроса на вход, но 401 для любых последующих запросов проверки проверки подлинности, потому что deserializeUser никогда не вызывал. Я погрузился в источник паспорта и заметил, что паспорт проверяет, существует ли req._passport.session.user, и если нет, он не вызывает deserializeUser.

Я просмотрел другие вопросы о stackoverflow, кажется, у меня есть конкретный случай.

Существует один тип локального стратегического типа, я использую запрос Ajax для запросов на вход, настройки CORS настроены, http://localhost:8080 - frontend, http://localhost:3000)

Я использую bodyParse, cookieParser, экспресс-сессию, инициализацию паспорта и сессии паспорта. Экспресс-сеанс защищен: false настроен, поскольку я запускаю запросы auth через http.

Здесь вы можете найти мой проект (backend package.json - это хорошо, поэтому вы можете его использовать, у него нет отсутствующих зависимостей, поскольку для frontend не уверены), по крайней мере, вы можете проверить код там.

Backend https://github.com/rantiev/template-api Frontend https://github.com/rantiev/template-angular

Конфигурация экспресс-сессии и CORS здесь https://github.com/rantiev/template-api/blob/master/modules/appConfigure.js

var path = require('path');
var bodyParser = require('body-parser');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var MongoStore = require('connect-mongo')(session);

module.exports = function (app, express, config, mongoose) {

    app.use(cookieParser());
    app.use(bodyParser.urlencoded({
        extended: true
    }));
    app.use(bodyParser.json());

    app.use(function (req, res, next) {

        // Website you wish to allow to connect
        res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');

        // Request methods you wish to allow
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

        // Request headers you wish to allow
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, X-AUTHENTICATION, X-IP, Content-Type, Origin, Accept, Cookie');

        // Set to true if you need the website to include cookies in the requests sent
        // to the API (e.g. in case you use sessions)
        res.setHeader('Access-Control-Allow-Credentials', true);

        // Pass to next layer of middleware
        next();
    });

    /*app.use(function (req, res, next) {
        console.log('coockie is:', req.cookies);
    });*/

    app.use(session({
        saveUninitialized: false,
        resave: false,
        secret: config.sessionsSecretToken,
        cookie: {
            secure: false
        },
        store: new MongoStore({ mongooseConnection: mongoose.connection })
    }));

    app.use(express.static(path.join(__dirname, '..' , 'public')));

};

Конфигурация паспорта находится здесь https://github.com/rantiev/template-api/blob/master/api/authentication/authenticationR.js

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var rememberMe = require('../../modules/rememberMe');
var createAccessToken = require('../../modules/createAccessToken');

var bcrypt = require('bcrypt-nodejs');

var UserM = require('../users/userM');

module.exports = function (app, mainRouter, role) {

    passport.use(new LocalStrategy({
        usernameField: 'email',
        passwordField: 'password'
    }, function (username, password, done) {

        UserM.findOneQ({email: username})
            .then(function(user){

                if (user && bcrypt.compareSync(password, user.password)) {
                    done(null, user);
                } else {
                    done(null, false);
                }

            })
            .catch(function(err){
                done(err);
            });

    }));

    passport.serializeUser(function (user, done) {

        console.log('serialize');

        if (user) {
            createAccessToken(user, done);
        } else {
            done(null, false);
        }
    });

    passport.deserializeUser(function (token, done) {

        console.log('deserialize');

        UserM.findOneQ({accessToken: token})
            .then(function(user){

                if (user) {
                    done(null, user);
                } else {
                    done(null, false);
                }

            })
            .catch(function(err){
                done(err);
            });

    });

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

    mainRouter.post('/me', passport.authenticate('local'), function (req, res) {
        res.status(200).send();
    });

    mainRouter.get('/logout', function (req, res) {
        req.logout();
        res.redirect('/');
    });

    mainRouter.get('/me', function (req, res) {

        if (!req.user) {
            res.status(401).send('Please Login!');
            return;
        }

        var currentUser = {
            id: req.user._id,
            role: req.user.role
        };

        res.status(200).json(currentUser);
    });

};

Ответ 1

Если вы посмотрите в стек вызовов и обнаружите, что deserializeUser не вызывается, потому что req._passport.session.user не установлен, ваша проблема следующая. Оскорбительные строки находятся в модуле express-session:

if (!req.sessionID) {
  debug('no SID sent, generating session');
  generate();
  next();
  return;
}

Если параметр sessionID установлен, generate никогда не вызывается:

store.generate = function(req){
 req.sessionID = generateId(req); 
 req.session = new Session(req); // THIS
 req.session.cookie = new Cookie(cookieOptions);

 if (cookieOptions.secure === 'auto') {
  req.session.cookie.secure = issecure(req, trustProxy);
 }
};

Но возможно установить req.sessionID, тогда как req.session равно null, что объясняет, что req._passport.session.user имеет значение null - req.session никогда не устанавливается.

Я продолжал отслеживать еще дальше, когда установлен req.sessionID, который с новыми куками иногда устанавливался, а иногда и нет.

Почему? Я не знаю, и мне бы хотелось, чтобы кто-то исследовал дальше, но в основном этот урок пытается использовать модуль cookie-session.

Ответ 2

Вы пробовали maxAge?

app.use(express.session({   store: sessionStore,
                            cookie: { maxAge : 3600000 } //1 Hour
                            }));