I've been trying to store a user's email in the session for my express.js file. But everytime I try something, and call another function, the session remains undefined. Been working on this for weeks now, and I can't seem to find the answer.
server.js file:
import express from 'express';
import cookieParser from 'cookie-parser';
import session from 'express-session';
const app = express();
app.use(cookieParser());
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: {
maxAge : 1000 * 60 * 60 * 3, // if 1 day * 24 but since *3 its for 3 hours only
},
}))
app.post('/user/login', (req, res) => {
const loginUser = req.body;
const email = loginUser['email'];
const password = loginUser['password'];
if (!email || !password){
res.status(400).json({success: false, error: "Please provide email and password"});
}
try {
Users.findOne({ email: email }, (err, user) => {
if (password == user['password']){
req.session.user(user['email']);
res.status(200).send(user_email);
} else {
res.status(400).json({success: false, error: "incorrect password"});
}
});
} catch {
}
})
Calling the Login file from the frontend (react js)
import React, { useState } from 'react';
import { Grid, TextField, Button } from '@mui/material';
import "./SignUpLogin.css";
import axios from '../../axios';
import useForm from './useForm';
import { Form } from './useForm';
const initialValues = {
email: '',
password: ''
}
function Login({ modalFunc }) {
const LoginUser = e => {
console.log("INSIDE LOGIN USER");
modalFunc();
e.preventDefault();
axios.post('/user/login', values, {withCredentials: true})
.then(response => {
console.log("in login user");
console.log(response.data);
})
}
const {
values,
setValues,
handleInputChange
} = useForm(initialValues);
return (
<div className="Login">
<Form>
<Grid item>
<TextField
required
variant="outlined"
label="Email"
name="email"
color="secondary"
fullWidth
value={ values.email }
onChange={ handleInputChange }
/>
</Grid>
<Grid item>
<TextField
required
variant="outlined"
label="Password"
name="password"
type="password"
color="secondary"
fullWidth
value={ values.password }
onChange={ handleInputChange }
/>
</Grid>
<Grid item>
<Button
variant="contained"
fullWidth
onClick = { LoginUser }>
Login
</Button>
</Grid>
</Form>
</div>
)
}
export default Login
But when I call server.js again in another get function, session is undefined.
app.get('/user/loggedIn', (req, res) => {
console.log(req.session.user);
user_email = req.session.user;
if (req.session.user) {
Users.findOne({ email: user_email }, (err, user) => {
// console.log("in logged in, in server!!!");
// console.log(user);
res.status(200).send(user);
})
} else {
console.log("no session");
res.status(400);
}
})
Calling app.get('/user/loggedIn') in react.js file:
function Header() {
const [modalOpen, setModalOpen] = useState(false);
const changeModal = () => {
setModalOpen(!modalOpen)
}
const [user, setUser] = useState(null);
useEffect(() => {
// axios.get('/user/loggedIn', {}, {withCredentials: true})
axios.get('/user/loggedIn', {}, {withCredentials: true})
.then(response => {
// console.log("RESPONSE FROM LOGGED IN");
// console.log(response.data);
setUser(response.data);
})
})
CodePudding user response:
Here is my working solution,
const bodyParser = require('body-parser');
const MongoStore = require('connect-mongo');
const cors = require('cors');
const express = require('express');
const { connect } = require('mongoose');
const UserModel = require('./models/UserMode');
const session = require('express-session');
(async () => {
try {
let response = await connect('mongodb://localhost:27017/test');
console.log('connected');
} catch (error) {
console.log(error);
}
})();
const app = express();
app.all('/*', function (req, res, next) {
res.header('Access-Control-Allow-Credentials', true); //this is you are missing
next();
});
const corsOpts = {
origin: ['http://localhost:3001'], // you have to provide list of whitelisted urls. In this case url of your frontend react app.
//you cant use * because you are using {withCredentials: true} in axios
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type'],
};
app.use(cors(corsOpts)); //this is you are missing
app.use(bodyParser.json());
app.use(
session({
cookie: { secure: false, httpOnly: false },
secret: 'Your_Secret_Key',
resave: true,
saveUninitialized: true,
name: 'some name',
store: MongoStore.create({
mongoUrl: 'mongodb://localhost:27017/test', // you have to provide some storage to store session data
}),
})
);
app.get('/login_check', async (req, res) => {
console.log(req.session); // just check if session is getting stored or not
res.json('check');
});
app.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
let userDetails = await UserModel.findOne({ email, password });
req.session.user = userDetails; // here pass any details that you want to send to session
console.log(userDetails);
res.send(userDetails);
} catch (error) {
console.log(error);
res.status(500);
}
});
const server = app.listen(5000, () =>
console.log(`Server started on port ${5000}`)
);
Also couple of things that you are doing wrong, after this line
res.status(400).json({success: false, error: "Please provide email and password"});
you should write it this way, or else it would throw an error.
return res.status(400).json({success: false, error: "Please provide email and password"});
// or this way
res.status(400).json({success: false, error: "Please provide email and password"});
return;
CodePudding user response:
Here is the clean solution:
first you've to import 2 packages and add those line of code in server.js file:
const session = require('express-session');
const MongoSessionStore = require('connect-mongodb-session')(session);
const MongoDBStore = new MongoSessionStore({
uri: process.env.MONGODB_URL,
collection: 'sessions',
});
app.use(
session({
secret: 'my-secret',
resave: false,
saveUninitialized: false,
store: MongoDBStore,
})
);
then store the session in this route:
app.post('/user/login', (req, res) => {
req.session.user = user;
}
