I’m trying to deploy a MERN stack website that I’ve been working on locally. While everything works fine locally, after deploying to Render and Vercel, I can’t access session data through req.session. I will share the code details below.
Some of app.ts file for backend:
const app = express()
app.set("trust proxy", 1)
app.use(cors({
origin: ["https://frontend.vercel.app", "http://localhost:3000"],
credentials: true
}))
app.use(morgan("dev"))
app.use(express.json())
export const Session = session({
secret:env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
maxAge: 720 * 60 * 60 * 1000,
httpOnly: true,
secure: env.EGE === "production",
sameSite: env.EGE === "production" ? "none" : "lax"
},
rolling: true,
store: MongoStore.create({
mongoUrl: env.MONGO_CONNECTION_STRING
}),
})
app.use(Session)
login:RequestHandler function for backend:
export const login:RequestHandler<unknown, unknown, loginBody, unknown>= async(req, res, next) => {
const username= req.body.username
const password= req.body.password
try {
if(!username || !password){
throw createHttpError(400, "missing parameters")
}
const user= await UserModel.findOne({username: username}).select("password").exec()
if(!user){
throw createHttpError(400, "invalid credentials")
}
const passwordMatch = await bcrypt.compare(password, user.password)
if(!passwordMatch){
throw createHttpError(400, "invalid credentials")
}
req.session.userId= user._id
req.session.save(err => {
if (err) return next(err);
res.status(200).json(user);
})
// res.status(200).json(user)
} catch (error) {
next(error)
}
}
login fetch function for frontend:
async function fetchData(input: RequestInfo, init?: RequestInit) {
const response = await fetch(input, init)
if(response.ok){
return response
}
else{
try {
const errorBody= await response.json()
const errorMessage= errorBody.error
throw new Error(errorMessage)
} catch (error) {
throw new Error("failed to parse error")
}
}
}
export async function login(credentials:LoginCredentials): Promise<User> {
const response = await fetchData(`${process.env.REACT_APP_BACKEND_URL}/api/users/login`,{
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify(credentials)
})
return response.json()
}
After deploying via Vercel and Render, I login to the site and the login function returns the correct response. Then I use console.log(req.session) to check if I can see the userId data, but I can only see the cookie inside req.session. In the MongoDB sessions collection, the stored data includes the userId, but in the Render logs, the session does not contain the userId. When I login locally, req.session contains both the cookie and the userId.
Render/Vercel log session + mongodb session
local log session + mongodb session
As seen in the images above, the session in the Render logs does not include the userId, but the userId is visible in the MongoDB session data. When I run the site locally, the userId appears in both the Node.js logs and the MongoDB session data. I have tried adjusting CORS and proxy settings but couldn’t find a solution. I would appreciate any help.