Passport + Sequelize не сохраняет req.user

У меня проблема с сохранением сеанса. Похоже, что вход и выход из системы работают нормально. Однако при внесении изменений в код или обновлении сервера nodemon он отображает нуль на маршруте current_user.

А потом эта ошибка при отправке почтовых запросов.

Cannot read property 'id' of undefined

router.get("/current_user", (req, res) => {
  if (req.user){
    res.status(200).send({ user: req.user});
  } else {
    res.json({ user:null})
  }

});

маршруты

const jwt = require('jsonwebtoken');
const passport = require('passport');

router.post('/loginUser',  passport.authenticate('login', {session: true}), (req, res, next) => {
  passport.authenticate('login', (err, user, info) => {
    if (err) {
      console.info(err);
    }

    if (info != undefined) {
      console.info(info.message);
      res.status(401).send(info.message);
    } else {
      req.logIn(user, err => {
       models.User.findOne({
          where: {
            username: req.body.username,
          },
        }).then(user => {
          const token = jwt.sign({ id: user.id  }, process.env.JWT_SECRET);
          // res.cookie("jwt", token, { expires: new Date(Date.now() + 10*1000*60*60*24)});
          jwt.verify(token, process.env.JWT_SECRET, function(err, data){
            console.info(err, data);
          })

          res.status(200).send({

            auth: true,
            token: token,
            message: 'user found & logged in',
          });
          // console.info(req.user)

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

паспорт.js

const bcrypt = require('bcrypt'),
      BCRYPT_SALT_ROUNDS = 12,
      JWTstrategy = require('passport-jwt').Strategy,
      ExtractJWT = require('passport-jwt').ExtractJwt,
      Sequelize = require('sequelize'),
      Op = Sequelize.Op,
      models = require( '../models/'),
      localStrategy = require('passport-local').Strategy;
      // passport = require("passport");

// serialize session, only store user id in the session information


module.exports = async (passport) => {

  passport.use(
    'register',
    new localStrategy(
      {
        usernameField: 'username',
        passwordField: 'password',
        passReqToCallback: true,
        session: false,
      },
      (req, username, password, done) => {
        try {
           models.User.findOne({
            where: {
              [Op.or]: [
                {
                  username: username,
                },
                { email: req.body.email },
              ],
            },
          }).then(user => {
            if (user != null) {
              console.info('username or email already taken');
              return done(null, false, {
                message: 'username or email already taken',
              });
            } else {
              bcrypt.hash(password, BCRYPT_SALT_ROUNDS).then(hashedPassword => {
                models.User.create({
                  username: req.body.username,
                  password: hashedPassword,
                  email: req.body.email
                }).then(user => {
                  console.info('user created');
                  return done(null, user);
                });
              });
            }
          });
        } catch (err) {
          done(err);
        }
      },
    ),
  );



passport.use(
  'login',
  new localStrategy(
    {
      usernameField: 'username',
      passwordField: 'password',
      session: false,
    },
    (username, password, done, req) => {
      try {
        models.User.findOne({
          where: {
            [Op.or]: [
              {
                username: username,
              }
            ],
          },
        }).then(user => {
          if (user === null) {
            return done(null, false, { message: 'Username doesn\'t exist' });

          } else {
            bcrypt.compare(password, user.password).then(response => {
              if (response !== true) {
                console.info('passwords do not match');
                return done(null, false, { message: 'passwords do not match' });
              }

              console.info('user found & authenticated');
              // note the return needed with passport local - remove this return for passport JWT
              return done(null, user);
            });


          }
        });
      } catch (err) {
        done(err);
      }
    },
  ),
);

const opts = {
  jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT'),
  secretOrKey: process.env.JWT_SECRET,
};




passport.use(
  'jwt',
  new JWTstrategy(opts, (jwt_payload, done) => {
    try {
       models.User.findOne({
        where: {
          username: jwt_payload._id,
        },
      }).then(user => {
        if (user) {
          console.info('user found in db in passport');
          // note the return removed with passport JWT - add this return for passport local
          done(null, user);
          // console.info(user);
        } else {
          console.info('user not found in db');
          done(null, false);
        }
      });
    } catch (err) {
      done(err);
    }
  }),
);

passport.serializeUser(function(user, done) {
   done(null, user.id);
   console.info(user.id); // gets user id
});

// from the user id, figure out who the user is...
passport.deserializeUser(function(id, done){
  models.User.findOne({
    where: {
      id,
    },
  }).then(user => done(null, user))
  .catch(done);
});

}

app.js

var express = require('express');
var app = express();
var userRoute = require('./routes/users');
var postRoute  = require('./routes/posts');
var bodyParser = require('body-parser');
var logger = require('morgan');
var session = require('express-session');
var cookieParser = require('cookie-parser') ;
var dotenv = require('dotenv');
var env = dotenv.config();
var cors = require('cors');
var models = require('./models/');
const host = '0.0.0.0';
const PORT = process.env.PORT || 8000;
const passport = require('passport');
const path = require('path');
// const allowOrigin = process.env.ALLOW_ORIGIN || '*'
// CORS Middleware
if (!process.env.PORT) {
  require('dotenv').config()
}

// console.info(process.env.DATABASE_URL);
if (!process.env.PORT) {
  console.info('[api][port] 8000 set as default')
  console.info('[api][header] Access-Control-Allow-Origin: * set as default')
} else {
  console.info('[api][node] Loaded ENV vars from .env file')
  console.info(`[api][port] ${process.env.PORT}`)
  console.info(`[api][header] Access-Control-Allow-Origin: ${process.env.ALLOW_ORIGIN}`)
}

app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'build')));
app.use(cookieParser());
app.use(session({
  secret : process.env.JWT_SECRET,
}));

require('./config/passport.js')(passport); // PASSPORT Init
app.use(passport.initialize());
app.use(passport.session());


app.use(bodyParser.urlencoded({ extended:false})); 
app.use(bodyParser.json());
// this code may be useless or useful, still trying to understand cors. 
app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Credentials',  true);
  res.header("preflightContinue", false)
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});


app.use(cors({
  origin: process.env.ALLOW_ORIGIN,
  credentials: true,
  allowedHeaders: 'X-Requested-With, Content-Type, Authorization',
  methods: 'GET, POST, PATCH, PUT, POST, DELETE, OPTIONS'
}))

app.use('/api/users', userRoute );
app.use('/api/posts', postRoute );

// In order to use REACT + EXPRESS we need the following code, alone with a build
// in the client folder we run a npm run build in the client folder then it is referred
// in the following code. 

app.use(express.static(path.join(__dirname, 'client/build')));

if (process.env.NODE_ENV === 'production') {
  app.use(express.static(path.join(__dirname, 'client/build')));
  //
  app.get('*', (req, res) => {
    res.sendfile(path.join(__dirname = 'client/build/index.html'));
  })
}
//build mode
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname+'/client/public/index.html'));
})



app.use(function(req, res, next) {
  res.locals.user = req.user; // This is the important line
  // req.session.user = user
  console.info(res.locals.user);
  next();
});



models.sequelize.sync().then(function() {

  app.listen(PORT, host, () => {
    console.info('[api][listen] http://localhost:' + PORT)
  })

})
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
298
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вопрос не столько в сохранении req.user, сколько в отсутствии установленного хранилища.

app.use(session({
  store: '', // enter a store
  secret : process.env.JWT_SECRET,
}));

Вы используете Sequelize, поэтому я бы порекомендовал вам изучить это

https://github.com/mweibel/connect-session-sequelize

Если все работает хорошо, вам не придется беспокоиться о том, что req.id станет неопределенным каждый раз, когда вы вносите изменения в код. Надеюсь это поможет.

Вы можете сделать что-то вроде

const SequelizeStore = require('connect-session-sequelize')(session.Store);


const sequelize = new Sequelize(
  process.env.POSTGRES_DB, 
  process.env.POSTGRES_USER, 
  process.env.POSTGRES_PASSWORD,{
    "dialect": "sqlite",
    "storage": "./session.sqlite"
});

myStore = new SequelizeStore({
  db:sequelize,
})

app.use(session({
  store: myStore, 
  secret : process.env.JWT_SECRET,
}));

Другие вопросы по теме