Passport sessions do not retain persistence

Having some trouble implementing OAuth 2.0 login where the sessions don't persist after authentication is a common issue. Additionally, there seems to be a problem with the app getting stuck in the routes/bnetauth.js file during the redirect in the callback function.

Below are the relevant files where Passport is being used:

app.js

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
//TOOLS
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session'); //Persistant sessions
var passport = require('passport');
//REQUIRE MODELS
require('./models/News');
require('./models/Application');
//REQUIRE ROUTES
var bnetauth = require('./routes/bnetauth')(passport);
var api = require('./routes/api');
var public = require('./routes/public');
var admin = require('./routes/admin');

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/karatechop');

require('./config/passport')(passport);

var app = express();

app.use(express.static('views'));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use(session({
    secret: 'ilovescotchscotchyscotchscotch', // session secret
    resave: true,
    saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

//Use Routes
app.use('/auth', bnetauth)
app.use('/api', api);
app.use('/admin', admin);
app.use('/', public);


// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
});

module.exports = app;

routes/bnetauth.js (Logging in through battle.net, hence the bnetauth name)

var express = require('express');
var router = express.Router();


module.exports = function(passport) {

    router.get('/bnet',
        passport.authenticate('bnet'));

    router.get('/bnet/callback',
        passport.authenticate('bnet', {
            failureRedirect: '/' }),
        function(req, res, next){
            console.log('Authenticated: ' + req.isAuthenticated())
           ####THIS IS WHERE IT GETS STUCK####
            res.redirect('https://localhost:3000/');
        });

config/passport.js

var BnetStrategy = require('passport-bnet').Strategy;


var BNET_ID = 'hidden'
var BNET_SECRET = 'hidden'

var User = require('../models/user')


// expose this function to our app using module.exports
module.exports = function(passport) {
    console.log('Entering passport')
    // =========================================================================
    // passport session setup ==================================================
    // =========================================================================
    // required for persistent login sessions
    // passport needs ability to serialize and unserialize users out of session

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        console.log('Serializing')
        done(null, user.id);
    });

    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            console.log('Deserializing')
            done(err, user);
        });
    });

    passport.use(new BnetStrategy({
        clientID: BNET_ID,
        clientSecret: BNET_SECRET,
        region: 'eu',
        callbackURL: "https://localhost:3000/auth/bnet/callback"
    }, function(accessToken, refreshToken, profile, done) {
        console.log(profile)
        console.log(accessToken)
        User.findOne({id: profile.id}, function(err, user){
            console.log("Trying!")
            if(err)
                return done(err);

            if(user) {
                return done(null, user);
            } else {
                var newUser = new User();

                newUser.id = profile.id,
                newUser.token = accessToken,
                newUser.battle_tag = profile.battletag

                newUser.save(function(err) {
                    if (err)
                        throw err;

                    return done(null, newUser);
                });
            }
        });
    }));
};

    return router;
}

Answer №1

Eureka! I finally cracked the code!

The culprit was lurking within my serialize and deserialize functions nestled inside config/passport.js

Within my user model, I realized there were two distinct forms of IDs.

  1. The _id assigned by mongo
  2. The ID sourced from the users object retrieved from battle.net (this represents the user's ID on battle.net).

During serialization, it dawned on me that the battle.net ID should be utilized instead of the mongo _id (as I was referencing user.id instead of user._id)

Subsequently, during deserialization when extracting data from the user object, I erroneously employed mongo's findById function, which operates based on ._id (distinct from .id in the user's object, thus leading to a return of 'undefined').

By simply converting .id to ._id in the serialize function, the issue was promptly resolved, paving the way for functioning persistent sessions.

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

What is causing the issue with using transition(myComponent) in this React 18 application?

Recently, I have been immersed in developing a Single Page Application using the latest version of React 18 and integrating it with The Movie Database (TMDB) API. My current focus is on enhancing user experience by incorporating smooth transitions between ...

Clicking within the text activates the dropdown menu, but clicking outside the text does not

My custom drop down menu is not functioning properly. When I click on the text, it successfully links to another place, but when I click beside the text, it does not link. Can you please help me identify what's wrong here? Your assistance would be gre ...

Progressive Web App with Vue.js and WordPress Rest API integration

When creating an ecommerce website using Wordpress, I utilized Python for scraping data from other websites to compare prices and bulk upload products through a CSV file. My next goal is to learn Vue and transform the website into a PWA as it will be esse ...

Mongoose: Unable to retrieve document files from the .chunk collection due to missing data field

I am attempting to remove the incomplete chunks from files that have not been fully uploaded to a MongoDB database. When uploading files directly to MongoDB, the Mongoose, Multer & GridFSBucket packages split media file data into two sub-collections for t ...

Caution: It is important for each child within a list to have a distinct "key" prop when using react-input

I'm currently facing an issue with the following code snippet: {array.map((item) => ( <> <input key={item.id} type="checkbox" /> ...

npm must patiently wait for a port or command to be ready before moving on to the next task

Currently in my npm package, I have this script: "start": "concurrently --kill-others \"npm run dev\" \"electron .\"" The issue is that when electron runs its command, the server isn't up yet so it displays a blank screen. I reso ...

Issue with Node/Express: Middleware addition to router does not function as expected

Here is the configuration of my router: app.get('/getReport', (req, res) => { res.send("This is the report"); }); Initially, this router functions properly and successfully displays the message This is the report in the browser However, ...

Progressively modifying related elements over time intervals

I have a specific list of p elements in my HTML code that I need to modify sequentially with a time interval of 1 second. Here is the HTML: <p>Changing first sentence!</p> <p>Second sentence ready!</p> <p>Third one coming up ...

Always display all options in MUI Autocomplete without any filtering

I am seeking to eliminate any filtering in the MUI Autocomplete component. My goal is for the text field popper to display all available options. The results are obtained from a server-side search engine. These results, or "hits," already provide a filter ...

Tackling the challenge of merging PDF files and designing a Table of Contents feature reminiscent of Acrobat in Node.js and JavaScript

I am currently implementing the following code snippet: const pdfmerger = require('pdfmerger') var pdfStream = pdfmerger(array_of_pdf_paths) var writeStream = fs.createWriteStream(final_pdf_path) pdfStream.pipe(writeStream) pdfmerger(array_of_pd ...

I am looking to have my page refresh just one time

I have created an admin page where I can delete users, but each time I delete a user, the page requires a refresh. I attempted to use header refresh, but this action caused my page to refresh multiple times. Is there a way to ensure that my page only refr ...

Adjusting the width of a nested iframe within two div containers

I am trying to dynamically change the width of a structure using JavaScript. Here is the current setup: <div id="HTMLGroupBox742928" class="HTMLGroupBox" style="width:1366px"> <div style="width:800px;"> <iframe id="notReliable_C ...

Number input in JavaScript being disrupted by stray commas

On my webpage, there are elements that users can control. One of these is a text input field for numbers. When users enter digits like 9000, everything functions correctly. However, if they use comma notation such as 9,000, JavaScript doesn't recogniz ...

Assign value to an element in an array using the value from another element

Is it possible in Javascript to set the value of one array element based on another without changing both elements? Specifically, how can I only modify arr[1] while leaving other elements unchanged? arr[0] = {i: 0}; arr[1] = arr[0]; arr[1]['summ&apos ...

The useMutation function trapped in an endless loop

I've been encountering an issue while running a query to save an entity in the database using usemutation. The saveVisa() mutation seems to be stuck in an infinite loop, creating the same element multiple times without any clear reason. import {React, ...

Reduce and combine JavaScript files without the need for Grunt or Gulp

My project involves working with over 50 JavaScript files that I want to combine and compress to optimize file size and minimize HTTP requests. The catch is, the client's system does not have Node or npm installed. How can I accomplish this task witho ...

Interactive Thumbnail Selection for HTML5 Video

Having trouble with creating thumbnails? I managed to solve the cross-domain issue using an html2canvas PHP proxy. No error messages in the Console, but the thumbnails are unfortunately not showing up - they appear transparent or white. Here is a snippet ...

The Owl-Carousel's MouseWheel functionality elegantly navigates in a singular, seamless direction

Issue at Hand: Greetings, I am facing a challenge in constructing a carousel using Owl-Carousel 2.3.4. My goal is to enable the ability to scroll through my images using the mousewheel option. Code Implementation: Incorporating HTML code : <div style ...

Leveraging the power of the three.js library on the client-side within a vue.js/n

I'm facing a challenge with incorporating the three.js library (installed via npm) to display 3D models on the client side within my nuxt.js application. Despite multiple attempts, I seem to be hitting a roadblock with the import not functioning prope ...

It is necessary to render React Native text strings within a text component

Greetings! The React Native code snippet below is responsible for rendering a user interface. However, upon running the code, an error occurred. How can I resolve this issue? The error message indicates that text strings must be rendered within a text comp ...