Tips for maintaining a user's session post-login with Passport and Express JS

I recently set up a node backend using express and integrated Passport for authentication purposes. My application has a route called /login for logging in and another route called /me to retrieve information about the currently logged in user.

Below is the code snippet for these routes:

//auth_routes.js
const express = require('express');
const { Users } = require('../database/models');

const router = express.Router();

router.post("/login", async (req, res, next) => {
  try {
    const user = await Users.findOne({ where: { email: req.body.email } });
    if (!user) {
      res.status(401).send("Incorrect username and/or password");
    }
    else if (!await user.correctPassword(req.body.password)) {
      res.status(401).send("Incorrect username and/or password");
    }
    else {
      console.log("LOGIN", req.sessionID)
      req.login(user, err => {
        (err ? next(err) : res.json(user))
      });
    }
  }
  catch (err) {
    next(err);
  }
});


router.get('/me', (req,res) => {
  console.log("ME SESSION", req.sessionID)
  if (req.user) {
    res.json(req.user);
  } else {
    res.status(401).send("Not logged in");
  }
});

module.exports = router;

This is how I initialize passport:

const express = require('express')
const cors = require('cors')
const morgan = require('morgan')
const passport = require('passport')
const bodyParser = require('body-parser')
const session = require('express-session')

const db = require('./database')
const api_routes = require('./routes/api_routes')

const SequelizeStore = require('connect-session-sequelize')(session.Store)
const sessionStore = new SequelizeStore({ db })
const app = express()
const PORT = process.env.PORT || 5000

passport.serializeUser((user,done) => {
  console.log("in serialize", user.id)
  return done(null,user.id);
});

passport.deserializeUser(async (id,done) => {
  console.log("in deserialize", id)
  try {
    const user = await db.models.Users.findByPk(id);
    done(null,user);
  } catch (err) {
    done(err);
  }
});

const configureApp = () => {
    app.use(cors({origin:'http://localhost:3001',credentials: true}));
    app.use(function (req, res, next) {
      res.header('Access-Control-Allow-Credentials', true);
      res.header('Access-Control-Allow-Origin', req.headers.origin);
      res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
      res.header('Access-Control-Allow-Headers', 'Origin, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, X-Response-Time, X-PINGOTHER, X-CSRF-Token,Authorization');
      if (req.method === "OPTIONS") {
          return res.status(200).end();
      } else {
          next();
      }
  });
    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded({extended: true}))
    app.use(morgan('dev'))

    app.use(
      session({
        secret: process.env.SECRET || "SUPER SECRET",
        resave: false,
        saveUninitialized: false,
        store: sessionStore,
        cookie: {secure: false}
      })
    )
    app.use(passport.initialize())
    app.use(passport.session())
    app.use('/api', api_routes)

    app.use((err, req, res, next) => {
      console.error(err);
      console.error(err.stack);
      res.status(err.status || 500).send(err.message || "Internal server error");
    })
}

const startListening = () => {
  app.listen(PORT, () => console.log(`Listening on PORT ${PORT}`))
}

const syncdb = async () => {
  await db.sync({force: true});
}

const bootApp = async () => {
  await sessionStore.sync();
  await syncdb();
  await configureApp();
  await startListening();
}

bootApp();

My observation so far indicates that when I use Postman to send the post request to /login and the get request to /me, everything functions as expected with matching session IDs. However, upon testing from the frontend, users are successfully logged in but encounter a 401 error during the subsequent get request to /me. Additionally, the session IDs differ between the login request and the me request.

Here's some of my client-side code implemented with Redux and Axios:

export const login = login => async dispatch => {
  try {
    let { data } = await axios.post('http://lacolhost.com:5000/api/auth/login', login);
    console.log(data);
    dispatch({type: 'SAVE_RESPONSE', payload: data});
  } catch (err) {
    console.error("Error logging in", err);
    dispatch({ type: 'SAVE_RESPONSE', payload: { message: 'Error communicating with server' }});
  }

export const getUser =  () =>  async (dispatch) => {
    try {

      const { data } = await axios.get('http://lacolhost.com:5000/api/auth/me', {withCredentials: true})
      dispatch({
        type: 'SELECT_USER',
        payload: data
      })
    } catch (err) {
      console.log(err);
    }
  }

If anyone has insights into what might be causing this discrepancy and how it can be resolved, I would greatly appreciate your assistance. Thank you!

Answer №1

If you are utilizing axios for API requests in your front-end, remember to include the {withCredentials: true} configuration.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In AngularJS, the process of delivering JavaScript files alongside HTML is known as routing

As I develop an AngularJS application, I am working on a service that generates a unique link for users to share, such as localhost:8080/sync/03afdbd66e7929b1. This link is intended to lead users to a form. However, upon configuring the route to handle thi ...

Utilize JSON parsing with AngularJS

My current code processes json-formatted text within the javascript code, but I would like to read it from a json file instead. How can I modify my code to achieve this? Specifically, how can I assign the parsed data to the variable $scope.Items? app.co ...

What is the functionality of an Angular service that retrieves an

It appears that Angularjs services are constructed by passing in a Contructor function: app.service('serviceName', function(){ this.var1 = 'foo'; this.method1 = function(){ } }); Angular executes this function using the new ...

Which HTTP headers pertain to the loading of iframes? nuxt-helmet

Can anyone explain which security headers are associated with iframe loading issues and may prevent the iframe from being loaded? I implemented nuxt-helmet to configure security headers in my nuxt project. However, after uploading my site to a server loca ...

Challenges encountered with Material-UI elements

Attempting to implement the http://www.material-ui.com/#/components/drawer (Docked Example) component from Material-UI in conjunction with ReactJS. An error is encountered with the "=" sign in this line: handleToggle = () => this.setState({open: !this ...

Exploring the bounds of self-invocation functions in JavaScript

Have you ever wondered why self-invocation functions inside another function in JavaScript don't inherit the scope of the outer function? var prop = "global"; var hash = { prop: "hash prop", foo: function(){ console.log(this.prop); ...

Is it possible to update JavaScript on mobile devices?

I'm currently working on a mobile site where I've implemented JavaScript to refresh a message counter. However, despite having JavaScript enabled on the device, the counter doesn't update on my Nokia e90. Interestingly, it works perfectly fi ...

Present Different Content for Visitors Using Ad-Blocking Software

I am currently working on a project that is supported by ads. These ads are subtle and relevant to the content, not obnoxious popups for questionable products. However, since the project relies on ad revenue, users with Ad Blockers unfortunately do not co ...

Customizing functions in JavaScript with constructor property

What is the best way to implement method overriding in JavaScript that is both effective and cross-browser compatible? function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; ...

Is there a way to automatically close all open sub-menus when clicking on a different parent menu item?

Check out this LINK for the code I am using. When I click on the Parent Menu, such as Services, the sub-menu of the Services menu will open. However, when I click on another menu, the sub-menu will also open. I want the previous sub-menu to close when I c ...

I'm attempting to create a text toggle button for displaying more or less content

I am currently working on implementing a show more/show less button feature. However, the current version is not very effective as I only used slicing to hide content when the state is false and display it all when true. Now, my goal is to only show the ...

React Ant Design: Toggle Visibility of Columns

Seeking a method to toggle the visibility of columns for the Table Component in Ant Design. The goal is to include a checkbox next to each column name. When unchecked, the column should be hidden. In my previous experience with react-table, accomplishing ...

The Express route path could not be retrieved while utilizing node.js and Angular.js

I've encountered a problem where I am unable to access external files in my index.html when using node.js with the front end. Below is the code I am currently working with: app.js: var createError = require('http-errors'); var express = re ...

Finding the measurement of a sofa using couch.get(data, headers, status)

After attempting to set up a node.js application with express.js by connecting to couchdb, I utilized the npm package called nodejs-couch. app.get('/', function(req, res) { couch .get(dbName, viewUrl) .then( function(data, heade ...

Enhance communication system by optimizing MySQL, JavaScript, and PHP chat functionality

I have created a chat application using Javascript, PHP, and MySQL for two users. Every 3 seconds, it makes an AJAX request to a PHP file to retrieve messages from the database and update the page. Currently, the PHP query used is: SELECT * FROM tmessages ...

The functionality to disable the ES lint max length rule is malfunctioning

In trying to disable an eslint rule in a TypeScript file, I encountered an issue with a regular expression that exceeded 500 characters. As a result, an eslint warning was generated. To address this, I attempted to add an eslint comment before declaring th ...

Tips for Sending an Ajax POST Request

I've been using the following code snippet to initiate a POST request to my node API in order to generate a PDF. However, upon execution, my node console displays the following errors: $('#renderPDF').click(function(){ var request = $ ...

Identify when the user clicks on the URL bar or types in the browser's address bar using Jquery or JavaScript

In my current project, I'm faced with the challenge of interacting with the browser's URL bar. Specifically, I need to detect events using jQuery/JS when a user clicks on the address bar, types in it, or switches tabs. Is there a way to achieve t ...

Is there a way to modify the color of a specific section of a font icon?

Currently, I am in the process of implementing an upvote button using fa fa signs. However, I have encountered an issue where the background color of the up vote button is bleeding outside of the sign (possibly due to padding on the icon), and I am strivin ...

Struggling to understand why I'm having trouble connecting my AJAX handler within WordPress

Following the instructions here as a guide seems to be leading me astray. After submitting the form below, a POST request to http://thesite/wp-admin/member-update results in a 404 error. I believed that this request should trigger my function member_update ...