req.user undefined, несмотря на успешную регистрацию с помощью Passport и сеанс Express на NodeJS - PullRequest
0 голосов
/ 09 июля 2020

Проблема

Я настраиваю свое приложение NodeJS и Express, используя Passport для аутентификации с помощью входа в Google и Facebook. При работе на локальном хосте все работает очень хорошо, но когда я развертываю свое приложение (на Vercel), я не могу заставить сеансы работать.

Процесс входа работает очень хорошо, и я могу видеть информацию о пользователе, прикрепленную к req.session и req.user содержат всю информацию о пользователе.

Однако сразу после этого при вызове любого маршрута req.user будет undefined

Код

//Setting up the app
const express = require('express');
//const https = require('https');

//Bodyparser to handle JSON
const bodyParser = require('body-parser');

//Mongoose to connect to MongoDB
const mongoose = require('mongoose');

//To handle environments
const keys = require('./keys')

//To handle user sessions
var session = require("express-session");
var MongoDBStore = require('connect-mongodb-session')(session);


//Passport to hangle Google Sign In
var passport = require('passport');
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;

//Authentication: serialize and deserialize user
passport.serializeUser(function(user, done) {
  console.log(`serialize: user:${user}`); 
  done(null, user._id);
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    console.log(`deserialize user:${user}`)
    done(err, user);
  });
});

//Authentication: Google Sign In
passport.use(new GoogleStrategy({
    clientID: keys.GOOGLE_CLIENTID,
    clientSecret: keys.GOOGLE_SECRET,
    callbackURL: keys.URL_GOOGLE_CALLBACK
  },
  function callback(accessToken, refreshToken, profile, done) {
    process.nextTick( ()=> {
        User.findOne({'googleId': profile.id}, (err,user)=> {
            if(err)
                return done(err,false);
            if(user){
                return done(null, user);
            }
            else{
                var newUser = new User();
                newUser.googleId = profile.id;
                newUser.googleToken = accessToken;
                newUser.firstName  = profile.name.givenName;
                newUser.email = profile.emails[0].value;
                newUser.authType = "Google";
                newUser.image = profile.photos[0].value;

                newUser.save((err)=> {
                    if(err)
                        throw err;
                    return done(null, newUser);
                });
            }
        });
      });
  }
));

//Importing the models used
const Country = require('./models/country');
const Place = require('./models/place');
const User = require('./models/user');
const Trip = require('./models/trip');

//Starting the app
const app = express();

//Using body parser as global middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }))

//Using cookie bodyParser
app.use(require('cookie-parser')('keyboard cat'))

//Using Cors for routes
//app.use(cors())

//Store for sessions
var storeSessions = new MongoDBStore({
  uri: keys.URI_MONGO,
  collection: 'sessions'
});

// Catch errors
storeSessions.on('error', function(error) {
  console.log(error);
});

//Added but not sure if useful
app.use(cors({credentials: true, origin: true}));


app.set('trust proxy', 1);

//Setting up a session
app.use(session({
  secret: 'keyboard cat',
  resave: true,
  saveUninitialized: false,
  proxy: true,
  store: storeSessions,
  cookie : {
    maxAge: 2419200000
  }
}));

//Using passport for authentication
app.use(passport.initialize());
app.use(passport.session());

//Solving CORS issues

app.use((req, res, next) => {
  let allowedOrigins = ['http://localhost:3000', 'http://localhost:8080', 'mywebsite.com'];
  let origin = req.headers.origin;
  if(allowedOrigins.indexOf(origin) > -1){
       res.setHeader('Access-Control-Allow-Origin', origin);
  }
  //res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
  res.header('Access-Control-Allow-Credentials', true);
  next();
});



//Connection to MongoDB
mongoose.connect(keys.URI_MONGO, {useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => console.log('Connection successful!'))
  .catch((error) => { console.error(error); });



//The API call from the Google sign in button
app.get('/authgoogle',
  passport.authenticate('google', { scope : ['profile', 'email'] }));

//Callback from Google Sign in
app.get('/authgoogleredirect', function(req, res, next) {
  passport.authenticate('google', {
      scope : ['profile', 'email']
    }, function(err, user, info) {
    if (err) { return next(err); }
    if (!user) { return res.redirect(keys.URL_SIGN_IN); }
    req.logIn(user, function(err) {
      if (err) { return next(err); }
      req.session.user = req.user;
      req.session.save(function(){
        console.log(`req.session.user in callback: ${req.session.user}`)
        console.log(`req.session in callback: ${JSON.stringify(req.session)}`)
        res.redirect(keys.URL_LOGGED_IN);
      });
    });
  })(req, res, next);
});



//Middleware to check if user is logged in
function isLoggedIn(req, res, next) {
  console.log(`req.session in isloggedin: ${JSON.stringify(req.session)}`);
  console.log(`req.user in isloggedin: ${JSON.stringify(req.user)}`);
  if (req.isAuthenticated()) {
    next();
  } else {
    data = {
      "redirect": true,
      "url": keys.URL_SIGN_IN
    }
    res.send(JSON.stringify(data));
  }
}


//--------------------USERS------------------------
//Getting the currently logged in user
app.get('/getcurrentuser', isLoggedIn, function(req, res, next) {
  res.send(req.user);
});

Что работает, а что нет

Вход в Google работает хорошо, а passport.serialize и passport.deserialize работают хорошо, я вижу объект пользователя.

Когда я пытаюсь для доступа к GET / getcurrentuser (вызов на всех страницах) я не получаю объект req.user и isAuthenticated() всегда возвращает false.

Это журналы промежуточного программного обеспечения isloggedin: req.session in isloggedin: {"cookie":{"originalMaxAge":2419200000,"expires":"2020-08-07T12:09:54.220Z","httpOnly":true,"path":"/"}} req.user in isloggedin: undefined

Сеансы правильно сохранены в коллекции сеансов в mongoDB.

Кажется, что сериализация и десериализация не вызываются после входа в систему, не уверен, что это нормально.

Что я пробовал

Я прочитал много ответов на похожие проблемы ems, но ничего не работает:

  • порядок инициализации паспорта и express сеанс : он должен быть правильным
  • прокси : добавлено, но ничего не изменилось
  • учетные данные : include всегда был включен в мой вызов выборки внешнего интерфейса
  • cook ie .secure: false : включил и выключил, безуспешно
  • повар ie сеанс пытался использовать его вместо express сеанса, безуспешно

Это должно быть что-то глупое, но я не могу его найти ... Меня беспокоит, почему это работает на localhost?

Большое спасибо за ваше время :)

Ответы [ 2 ]

0 голосов
/ 11 июля 2020

Хорошо, если кто-то столкнется с этой точной проблемой, я, наконец, решил ее:

req.user всегда обозначался как undefined, потому что мой внешний и задний конец имеют разные доменные имена (я использую уровень бесплатного героку) поэтому повар ie считался сторонним, заблокирован Google Chrome и никогда не отправлялся в мое express приложение !

Как только я отключил сторонний повар ie блокировка в настройках Chrome сеанс стал постоянным!

паспорт и конфигурации сеанса все время были правильными ...

Спасибо @abhinav за вашу помощь и время :)

0 голосов
/ 10 июля 2020

Passport имеет свой собственный код обработки сеанса, встроенный в его библиотеку, если вы хотите сохранить своего пользователя для входа в систему в базе данных сеанса, вы можете сделать

router.get("/redirect", passport.authenticate('google',{failureRedirect:'/fail',successRedirect:'/success'}, (req,res)=>{
   req.session.user = req.user;
});

и сохранить оставшийся код таким же, как и вы. , это сохранит ваш сеанс в базе данных

...