I'm making both front and back-end of my e-commerce. I'm using express and passport to make a little login and register system. My problem is that whenever I enter any page of my site that involves a request, a new session is created and therefore, sent to my MongoDB server. Let's say I navigate through 3 sections of my site, 3 different sessions are created.
My intention is for the session to be created ONLY after the user logs in.
Here is my code:
app.js:
import express from "express"
import mongoose from "mongoose"
import { Server } from "socket.io"
import { boxRouter } from "./routes/box.router.js"
import { productRouter } from "./routes/product.router.js"
import { cartRouter } from "./routes/cart.router.js"
import { userRouter, isLoggedIn } from "./routes/user.router.js"
import passport from "passport"
import initializePassport from "./passport.config.js"
import cors from 'cors'
import MongoStore from "connect-mongo"
import cookieParser from "cookie-parser"
import session from "express-session"
// const hostname = '0.0.0.0'
// const port = '10000'
export var app = express()
// const httpServer = app.listen(port, hostname, ()=>{ console.log("Server Up")})
const httpServer = app.listen(8080, ()=>{ console.log("Server Up")})
export const socketServer = new Server(httpServer)
app.use(cookieParser("mostsecretsecret"))
app.use(session({
store: MongoStore.create({
mongoUrl: 'blablabla',
mongoOptions: {useNewUrlParser: true, useUnifiedTopology: true},
ttl: 15
}),
cookie:{
maxAge: 7 * 24 * 60 * 60 * 1000,
},
secret: 'mysecret',
resave: true,
saveUnitialized: false
}))
initializePassport()
app.use(passport.initialize())
app.use(passport.session())
app.use(cors())
app.use(express.urlencoded({extended:true}))
app.use(express.json())
app.use('/api/boxes', boxRouter)
app.use('/api/products', productRouter)
app.use('/api/carts', cartRouter)
app.use('/api/users', userRouter)
var connectionString = "blablabla"
mongoose.set('strictQuery', false)
mongoose.connect(connectionString)
socketServer.on('connection', socket=>{
console.log("Nuevo cliente conectado.")
})
passport.config.js:
import passport from "passport";
import local from 'passport-local';
import { userModel } from './models/user.model.js'
import { createHash, isValidPassword } from "./utils.js";
import { cartManager } from "./managers/CartManager.js";
const LocalStrategy = local.Strategy
const initializePassport = ()=>{
passport.use('register', new LocalStrategy(
{passReqToCallback: true, usernameField: 'email'}, async(req, username, password, done)=>{
const { first_name, last_name, email, newsletter } = req.body
try{
let user = await userModel.findOne({email: username})
if(user){
console.log("El usuario ya existe")
return done(null, false)
}
let newCart = await cartManager.createCart()
const newUser = {
first_name,
last_name,
email,
password: createHash(password),
cartId: newCart.id,
newsletter,
role: 'user'
}
let result = await userModel.create(newUser)
return done(null, result)
}catch(err){
return done("Error al obtener el usuario: " + err)
}
}
))
passport.use('login', new LocalStrategy(
{usernameField: 'email'}, async(username, password, done)=>{
try{
const user = await userModel.findOne({email: username})
if(!user){
console.log("El usuario no existe")
return done(null, false)
}
if(!isValidPassword(user,password)) return done(null, false)
return done(null, user)
}catch(err){
return done(err)
}
}
))
passport.serializeUser((user, done)=>{
done(null, user._id)
})
passport.deserializeUser(async(id, done)=>{
let user = await userModel.findById(id)
done(null, user)
})
}
export default initializePassport
user.router.js:
import { Router } from 'express';
import passport from 'passport';
export const userRouter = Router()
export function isLoggedIn(req, res, next){
if(req.session.user){
return next()
}
return res.status(401).send('Error de autorización.')
}
userRouter.post('/register', passport.authenticate('register', {}), async (req, res)=>{
try {
res.send('Success')
} catch (error) {
res.status(400).send({
status: 'error',
message: error.message
})
}
})
userRouter.post('/login', passport.authenticate('login', {}), async (req, res)=>{
try {
if(!req.user){
return res.status(401)
}
req.session.user = {
first_name: req.user.first_name,
last_name: req.user.last_name,
email: req.user.email,
role: req.user.role
}
res.send('Success')
} catch (error) {
res.status(400).send({
status: 'error',
message: error.message
})
}
})
userRouter.get('/logout', (req, res)=>{
try {
req.session.destroy(err=>{
if(err) res.status(500)
})
} catch (error) {
res.status(400).send({
status: 'error',
message: error.message
})
}
})
userRouter.get('/check-login', isLoggedIn, (req, res) => {
try {
res.status(200).send('Usuario logueado');
} catch (error) {
res.status(400).send({
status: 'error',
message: error.message
})
}
});
I've read multiple posts here and some said to use withCredentials whenever using axios request, but that's not working. Also, saveUninitalized doesn't work either because passport inserts an empty object into the cookie(i think? smth like that) and that makes them "modified".
This is my database after browsing through 3 pages of my site: https://i.sstatic.net/4rki3.png
OK I fixed it after reading through several posts.
I included this in my app.js file:
const corsOptions = {
origin: 'http://localhost:3000',
credentials: true,
}
app.use(cors(corsOptions));
And also added "withCredentials: true" to every axios request (I guess there's an option to set it as default but nevermind.)
let response = await axios.get("http://localhost:8080/api/boxes", {withCredentials: true })