node.js - Passport not persisting across browser requests, works with Postman

倖福魔咒の 提交于 2020-01-03 03:38:06

问题


I am currently using the create-react-app boiler plate and have been attempting to add auth. I am using axios as my promise based HTTP libray with React.js. I have been using node with express, express-session, passport and passport-local on the backend.

Here is my server.js file with some exlusions:

const express = require('express');
const mysql = require('mysql');
const app = express();
const cors = require('cors');
const session = require('express-session');
const passport = require('passport');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const LocalStrategy = require('passport-local').Strategy;

// Express only serves static assets in production
if (process.env.NODE_ENV === 'production') {
  app.use(express.static('client/build'));
}

app.set('port', (process.env.PORT || 3001));

app.use(cors({
  credentials: true,
  origin: 'http://localhost:3000'
}));
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(session({
  secret: 'topsecretpassword',
  resave: true,
  saveUninitialized: false,
  cookie: {
    path: '/',
    originalMaxAge: 1000 * 60 * 60 * 24,
    httpOnly: true,
    secure: false
  }
}));
app.use(passport.initialize());
app.use(passport.session());


// Setup Database connection
const connection = mysql.createConnection({
  host : 'localhost',
  user : 'root',
  password : '',
  database : 'mvy_db'
});

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

passport.deserializeUser(function(user, done) {
  connection.query('SELECT * FROM users WHERE id=?', user, function(err, userId) {
    if (err) {
      res.status(400).json({
        error: 'Database Error',
        id: userId[0]
      });
    }

    done(err, userId[0]);
  });
});

passport.use(new LocalStrategy({
  usernameField: 'email',
  passwordField: 'password',
  },
  function(email, password, done) {
    connection.query('SELECT * FROM users WHERE email=?', email, function(err, user) {
      if (err) {
        return done(err);
      }
      if (!user.length) {
        return done(null, false, { message: 'Incorrect email.' });
      }
      if (user[0].password !== password) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user[0]);
    });
  }
));

app.post('/signin', passport.authenticate('local'), function(req, res) {
  console.log(req.session);
  return res.send('login success!');
});

function isAuthenticated (req,res,next){
  console.log(req.session);
  if(req.session.passport.user)
     return next();
  else
     return res.status(401).json({
       error: 'User not authenticated'
     })

}

app.get('/checkauth', isAuthenticated, function(req,res) {
  res.status(200).json({
    status: 'User Authenticated!'
  });
})

app.get('/signout', function(req,res) {
  req.session.destroy();
  res.status(200).json({ success: 'successfully signed out' });
})

Using postman (and even on the browser), I am able to successfully login and the following is held in the req.session object :

   cookie:
    { path: '/',
      _expires: null,
      originalMaxAge: 86400000,
      httpOnly: true,
      secure: false },
      passport: { user: 1 } }

my login request using axios:

return axios.post(ROOT_URL + 'signin', {
      email: e.target.email.value,
      password: e.target.password.value
    }).then((response) => {
      if (response.status === 200) {
        console.log(response);
      }
    })

My checkAuth request using axios (this is where I get a 500 error returned):

  axios.get(ROOT_URL + 'checkauth', { withCredentials: true })
    .then((response) => {
      if (response.status === 200) {
        return true;
      } else {
        return false;
      }
    });

The req.session object after checking authentication before the error message, note that the passport object doesn't exist anymore:

 Session {
   cookie:
    { path: '/',
      _expires: null,
      originalMaxAge: 86400000,
      httpOnly: true,
      secure: false } }

This is the error message I get on the console when I attempt to check that the user is authorized:

 TypeError: Cannot read property 'user' of undefined
     at isAuthenticated (/server.js:94:26)

I've been banging my head for hours, trying to resolve this issue. I thought it might have something to do with CORS, but after hours of playing around with it that doesn't seem to be the case. It's still plausible that it's a CORS issue, but what's really flustering me is that it works full well with Postman but not on my Chrome browser. Any help is appreciated!


回答1:


Alright, so I found the solution to my problem. It appeared to be an issue with axios and the configuration of my get requests. For some reason, using the structure axios.get(URL) .then(response) doesn't work with the withCredentials property.

Instead, I had to send my request as:

axios(ROOT_URL + 'checkauth', { method: 'get', withCredentials: true }) .then((response) => { if (response.status === 200) { return true; } else { return false; } });




回答2:


Oh because I forgot that axious doesn’t send credentials by default I had to stick with jwt and completely removed session.

You can define an instance of axious which will allow you to make requests much more simply

const $axios = axios.create({
  baseURL: 'https://some-domain.com/api/',
  withCredentials: true
});


来源:https://stackoverflow.com/questions/45968661/node-js-passport-not-persisting-across-browser-requests-works-with-postman

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!