Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React App with Express Backend & express-session

I currently have a React App (via create-react-app) and an Express server for my API calls. They are both running separately and have been working fine until I ran into this problem:

I'm also using express-session and passport for user authentication. I'm able to authenticate users but the session doesn't persist between API calls. If I successfully login, the next time I make an API call, req.sessionID will be different, and req.isAuthenticated() will return false.

Here is my server code:

'use strict'

var express         = require('express');
var path                = require('path');
var bodyParser      = require('body-parser');
var cookieParser    = require('cookie-parser');
var mongoose      = require('mongoose');
var passport      = require('passport');
var session       = require('express-session');
var cors          = require('cors');
var flash         = require('connect-flash');

var store         = require('./store');
var database      = require('./database');

var app     = express();
var port    = process.env.port || 3001;
var router  = express.Router();

var promise = mongoose.connect('mongodb://localhost:27017/lifeless-db', {useMongoClient: true});

//app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser('lifeless-secret-01890'));
app.use(session({
  secret: 'lifeless-secret-01890',
  saveUninitialized: true,
  cookie: {
    secure: false,
  }
}));
app.use(flash());

app.use(passport.initialize());
app.use(passport.session());
// Initialize Passport
var authinit = require('./auth/init');
authinit(passport);

// For debugging:
app.use(function(req, res, next) {
  console.log("SessionID: " + req.sessionID);
  console.log(req.isAuthenticated() ? "This user is logged in" : "This user is NOT logged in");
  next();
});



// GET

app.get('/items', function(req, res) {
  store.getAllItems((items) => {
    if(!items) return res.send({error: true, message: 'Error loading store :/', items: null});
    else return res.send({error: false, message: 'Success', items: items});
  });
});

app.get('/login', function(req, res) {
  console.log(req.flash());
  console.log("Login fail");
  res.send({error: true, message: 'Unknown error'});
});


// POST

app.post('/message', function(req, res) {
  database.submitMessage(req.body.email, req.body.message, (success) => {
    if (success) return res.send({error: false, message: 'Success'});
    else return res.send({error: true, message: 'Error sending message'});
  });
});


app.post('/login', passport.authenticate('local', {failureRedirect: '/login', failureFlash: true}), function(req, res) {
  console.log(req.flash());
  console.log("Login success");
  return res.send({error: false, message: 'Success'});
});



// SERVER

app.listen(port, function(){
  console.log('Server started.');
  console.log('Listening on port ' + port);
});

And here is an example of an API call from the React App (using axios):

login(e) {
    e.preventDefault();

    axios({
      method: 'post',
      url: 'http://localhost:3001/login',
      data: {
        username: this.state.username,
        password: this.state.password,
      }
    })
    .then((response) => {
      console.log(response.data);
      if (response.data.error) {
        this.setState({error: true, errmessage: response.data.message});
      } else {
        this.setState({redirect: true});
      }
    })
    .catch((error) => {
      this.setState({error: true, errmessage: 'Error logging in'});
    });
  }

I figure there must be some way to have React store the session somehow (?) but I'm fairly new to React and don't really know how to use it with an express backend.

like image 918
drewpel Avatar asked Dec 05 '17 00:12

drewpel


People also ask

Does React app have a backend?

In every React project, we manage data on the client through state and user interactions. However, many apps are not possible without data that comes from the backend. The backend takes care of getting or updating data in our application and it is hidden away from the user.

Which backend to use with React?

NodeJS. NodeJS is considered a perfect backend partner of React JS because of its great compatible features. Both front-end and backend libraries use the same JavaScript language that enables them to develop modern applications.

How do I connect React app with backend?

export default App; Now run the Nodejs process npm run dev in one terminal and in another terminal start Reactjs using npm start simultaneously. Output: We see react output we see a button “Connect” we have to click it. Now when we see the console server-side we see that the ReactJS is connected with NodeJS.


1 Answers

Your axios request from your React client needs to be sent withCredentials. To fix it, either do axios.defaults.withCredentials = true; or do axios.get('url', {withCredentials: true})...Also in your expressjs backend, set cors options credentials: true

like image 80
M312V Avatar answered Oct 05 '22 23:10

M312V