passport.deserializeUser function never getting called

I am losing my mind here, guys. I took my time to go through several similar questions that have been asked in the past and none of the answers have been helpful, and some of the answers already had been implemented in my setup such as adding “credentials: include” but the problem remains.

I would be really elated if someone can help me figure this solution out. I have thought of abandoning the project already.

passport’s deserialization just does not work no matter what I do.

This is my passport.js –

const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const User = require('../models/User');

module.exports = function(passport) {
  passport.use(new GoogleStrategy({
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      callbackURL: 'https://messenger-tu85.onrender.com/auth/google/callback',
    },
    (accessToken, refreshToken, profile, done) => {
      User.findOne({ googleId: profile.id })
        .then(existingUser => {
          if (existingUser) {
            console.log('Existing user found:', existingUser);
            return done(null, existingUser);
          } else {
            const tempUser = {
              googleId: profile.id,
              email: profile.emails[0].value
            };
            console.log('Creating new temp user:', tempUser);
            return done(null, tempUser);
          }
        })
        .catch(err => {
          console.error('Error finding user:', err);
          return done(err);
        });
    }
  ));

  passport.serializeUser((user, done) => {
    console.log('Serialize user:', user);
    if (user._id) {
      done(null, user._id);
    } else {
      done(null, user.googleId);
    }
  });

  passport.deserializeUser(async (id, done) => {
    try {
      // If id is an object and contains googleId, it’s a temporary user
      if (typeof id === 'object' && id.googleId) {
        done(null, id);
      } else {
        // If id is an _id, fetch the user from the database
        const user = await User.findById(id);
        done(null, user);
      }
    } catch (err) {
      done(err);
    }
  });
  
};

As you can see, when a user signs in with their Google account, if a user matching their google id does not exist in the database, then a temporary session is created for the user. This part works smoothly.

The user is serialized successfully and the console statement reads –

Creating new temp user: { googleId: 'my google id', email: 'my gmail' }
Serialize user: { googleId: 'my google id', email: 'my gmail' }

the point of creating the temporary session is so that they can continue their registration in another page.

This is my authRoutes.js –

const express = require('express');
const passport = require('passport');
const router = express.Router();

router.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));

router.get('/auth/google/callback',
  passport.authenticate('google', { failureRedirect: 'https://svelte-of1p.onrender.com/signin' }),
  (req, res) => {
    if (req.user) {
      // Manually set the cookie
      res.cookie('connect.sid', req.sessionID, {
        maxAge: 24 * 60 * 60 * 1000, // 1 day
        secure: process.env.NODE_ENV === 'production', // True in production
        httpOnly: false, // Allow client-side access
        sameSite: 'None' // Allow cross-site cookies
      });
      if (req.user.username) {
        res.redirect('https://svelte-of1p.onrender.com');
      } else {
        res.redirect('https://svelte-of1p.onrender.com/select');
      }
    } else {
      res.redirect('https://svelte-of1p.onrender.com/signin');
    }
  }
);

module.exports = router;

As can be seen, if the user does not have a username (they can’t have a username yet since they have not finished their registration) they are redirected to the /select page where they are to choose a unique username.

Notice that i am sending a cookie to the client. I didnt do this initially but i had to do it because i realized that no cookie was ever sent to the client, so by manually setting the cookie myself, the problem was fixed and cookie is now getting sent to the client after the user signs in with their Google account. Everything is working fine so far.

Now, the user without a username is redirected to the select page which is handled by SvelteKit –

And on the select/+page.svelte I have this –

const checkUserStatus = async () => {
    try {
        console.log('checkUserStatus function called');
        
        const response = await fetch('https://messenger-tu85.onrender.com/api/check-new-user', {
            credentials: 'include'
        });

        console.log('Response status:', response.status);

        if (response.status === 401) {
            console.log('Unauthorized: Redirecting to sign-in page');
            window.location.href = '/signin';
            return;
        }

        const data = await response.json();
        console.log('Response data:', data);
        
        userExists = data.exists;

        if (userExists) {
            console.log('User exists: Redirecting to messages');
            window.location.href = '/messages';
        } else {
            console.log('User does not exist: Enabling form');
            errorMessage = '';
            successMessage = '';
            formDisabled = false;
        }
    } catch (error) {
        console.error('Error checking user status:', error);
    }
};

    onMount(checkUserStatus); 

So I am sending a fetch request to the server to confirm if the user making the request should be allowed to be on the page.

The following is the endpoint on the server that the client calls –

const User = require('../models/User');

const checkNewUser = async (req, res, next) => {
  try {
    console.log('checkNewUser middleware called');
    console.log('Request received:', {
      headers: req.headers,
      body: req.body,
      user: req.user
    });

    // Correctly check for req.user.googleId directly
    if (!req.user || !req.user.googleId) {
      console.log('Unauthorized: No user or user ID found');
      return res.status(401).json({ error: 'Unauthorized' });
    }

    const googleId = req.user.googleId;
    console.log('Checking existing user with Google ID:', googleId);
    const existingUser = await User.findOne({ googleId });

    if (existingUser) {
      console.log('Existing user found:', existingUser);
      if (existingUser.username) {
        console.log('User has a username');
        return res.json({ exists: true });
      } else {
        console.log('User does not have a username');
        return res.json({ exists: false });
      }
    } else {
      console.log('No existing user found');
      return res.json({ exists: false });
    }
  } catch (error) {
    console.error('Error checking user:', error);
    res.status(500).json({ error: 'Server error' });
  }
};

module.exports = checkNewUser;

And this is where the problem is. the request headers being consoled out shows that –

user: undefined

it now occurs to me that after the user signed in with their Google account they were correctly serialized, but they were never deserialized! the function was NEVER called and I am assuming that is why req.user is undefined and it has brought my project to a standstill!

Based on my understanding, deserializeUser is what would populate req.user but this does not happen for reasons I cannot figure out.

I have attempted to use cookie-session, cookie-parser, removing secure in my cookie setup, forcing req.login(), and a plethora of other “answers” I have found while browsing this forum, but they have not helped. I have even ensured that my middlewares are ordered correctly, but it does not help either.

I built a custom deserializer where I extracted the cookie from the request header (the cookie is being sent back to the server as i explained earlier) and then extracted the session id and then tried to know which user has the session id, it worked, but i ran into problems later trying to modify this my custom deserializer middleware to handle temporary users and fully registered users.

The problem, in summary, is i would rather not use my custom deserializer middleware and would like to use the one that comes with passport, but why is it not getting called?

this is my server.js to show that my ordering of my middlewares are correct, i have removed codes not relevant to the problem –

const express = require('express');
const WebSocket = require('ws');
const app = express();
const port = 3000;
const { createServer } = require('http');
const dotenv = require('dotenv');
const passport = require('passport');
const selectUser = require('./controllers/selectUser');
const checkNewUser = require('./middleware/checkNewUser'); 
const cors = require('cors');
const session = require('express-session');
const MongoStore = require('connect-mongo');

dotenv.config();

const connectDB = require('./config/mongoose');
connectDB();

// Use CORS middleware before any other middleware
app.use(cors({
  origin: 'https://svelte-of1p.onrender.com',
  credentials: true
}));

// Use session middleware before Passport initialization
app.use(session({
  secret: process.env.SECRET,
  resave: false,
  saveUninitialized: false,
  store: MongoStore.create({
    mongoUrl: process.env.MONGODB_URI,
    collectionName: 'sessions'
  }),
  cookie: {
    maxAge: 24 * 60 * 60 * 1000, // 1 day
    httpOnly: false,
    sameSite: 'none'
  }
}));

// Initialize Passport after session middleware
const initializePassport = require('./config/passport');
initializePassport(passport);

app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(passport.initialize());
app.use(passport.session());

app.use('/', require('./controllers/authControllers/authRoutes'));
app.use('/', require('./controllers/authControllers/usernameRoutes'));
app.use('/api/users', require('./controllers/users'));
app.use('/api/messages', require('./controllers/messageController'));
app.use('/api/select-user', selectUser.selectUser);
app.use('/api/selected-users', require('./controllers/selectedUsers'));
app.use('/api/check-new-user', checkNewUser);

Hopefully, that wasn’t too much code and someone can help me out here.

Thanks in advance.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật