I’m working on a MERN stack project and I’m facing this issue where my req object is not being persistent and holding the req.user
after it has been authenticated. when the /google/callback
enpoint is triggered the req.user seems to exist but the second my application tries to fetch /user
the req.user
is undefined
I’ve tried almost everything by now, I’ve checked my .env variables and I’ve set up a proper Session storage as well, but this thing just isn’t working on production , on local development environment it’s working absolutely fine.
googleStrategy.js
const User = require('../models/User')
const passport = require('passport')
const GoogleStrategy = require('passport-google-oauth20').Strategy
passport.use(
new GoogleStrategy(
{
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: process.env.CALLBACK_URL,
passReqToCallback: true,
},
async function (request, accessToken, refreshToken, profile, done) {
try {
// get the returned data from profile
let data = profile?._json
console.log(data)
let user = await User.findOne({ email: data.email })
if (!user) {
// create user, if user does not exist
const newUser = await User.create({
email: data.email,
googleId: data.id,
firstName: data.given_name,
lastName: data.family_name,
displayName: `${data.given_name} ${data.family_name}`,
photos: profile.photos.map((photo) => photo.value),
})
return await done(null, newUser)
}
return await done(null, user)
} catch (error) {
return done(error, false)
}
}
)
)
passport.serializeUser((user, done) => {
done(null, user)
})
passport.deserializeUser(async (id, done) => {
try {
const user = await User.findById(id)
done(null, user) // Deserialize user from the id
} catch (error) {
done(error, null)
}
})
auth.js
const express = require('express')
const router = express.Router()
const passport = require('passport')
const { Bookmark, Like } = require('../models/BlogStats')
const Profile = require('../models/Profile')
const { userAuthenticated } = require('../middleware/checkAuth')
router.get('/google', passport.authenticate('google', { scope: ['email', 'profile'] }))
router.get(
'/google/callback',
passport.authenticate('google', {
failureRedirect: process.env.CLIENT_URL,
failureMessage: true,
}),
async (req, res) => {
console.log('User authenticated:', req.user, 'Session:', req.session, 'isAuthenticated:', req.isAuthenticated())
await Bookmark.findOrCreate({ userId: req.user._id })
await Like.findOrCreate({ userId: req.user._id })
await Profile.findOrCreate({ userId: req.user._id })
res.redirect(`${process.env.CLIENT_URL}/home`)
}
)
router.get('/logout', (req, res) => {
req.logout((err) => {
if (err) res.sendStatus(500)
else {
res.clearCookie('connect.sid', { path: '/' })
res.json({ logout: 'successful' })
}
})
})
router.get(
'/user',
(req, res, next) => {
console.log(req.user, req.session, req.isAuthenticated())
if (req.isAuthenticated()) next()
else res.json({ error: 'unauthorized', loggedIn: false })
},
(req, res) => {
const user = {
...req.user,
loggedIn: true,
}
res.status(200).json(user)
}
)
module.exports = router
server.js
require('dotenv').config()
const express = require('express')
const mongoose = require('mongoose')
const connectDB = require('./config/dbConfig')
const session = require('express-session')
const MongoStore = require('connect-mongo')
const passport = require('passport')
const cors = require('cors')
const path = require('path')
const authRouter = require('./routes/auth')
const apiRouter = require('./routes/api')
const app = express()
connectDB()
app.use(
cors({
origin: process.env.CLIENT_URL,
credentials: true,
})
)
app.use(express.static(path.join(__dirname, 'public')))
app.use(express.json({ limit: '10mb' }))
app.use(express.urlencoded({ limit: '10mb', extended: false }))
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: { httpOnly: true, secure: process.env.NODE_ENV === 'Production', maxAge: 24 * 60 * 60 * 1000 },
store: MongoStore.create({ mongoUrl: process.env.MONGO_URI, collectionName: 'sessions' }),
})
)
console.log(process.env.NODE_ENV, process.env.NODE_ENV === 'Production')
app.use(passport.initialize())
app.use(passport.session())
require('./config/googleStrategy')
app.use('/auth', authRouter)
app.use('/api', apiRouter)
const PORT = process.env.PORT || 3000
mongoose.connection.once('open', () => {
console.log('Connected to MongoDB')
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
})
})