Connect-pg-simple not saving session to database - node.js

I am trying to implement simple authentication with Node, Express, Express-Session and Passport.js. As a storage middleware I'm using connect-pg-simple as I am using pg-promise in my project.
I managed to configure passport to work with my routers but for some reason sessions won't be saved to my database. None of the plugins return any errors, everything seems to be running smoothly but my sessions table is empty.
What could I be doing wrong? connect-pg-simple connects to the server, passport.js is holding sessions and express-session assigns configured maxAge to cookies.
server.js
const express = require('express');
const db = require('./database.js');
const cors = require('cors');
const helmet = require('helmet');
const session = require('express-session');
const passport = require('passport');
const port = process.env.PORT || 3000;
const app = express();
const pgSession = require('connect-pg-simple')(session);
const pgStoreConfig = {
pgPromise: db.conn
};
app.set('trust proxy', 1);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
session({
secret: REDACTED, // need to change it later to some proper hash
store: new pgSession(pgStoreConfig),
resave: true,
cookie: {
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days ;)
secure: app.get('env') === 'production'
},
saveUninitialized: false
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use(cors());
app.use(helmet());
app.get('/', (req, res) => {
if (req.session.views) {
req.session.views++;
} else {
req.session.views = 1;
}
//res.send(`Views: ${req.session.views}`);
res.json(req.session);
});
const userRouter = require('./routes/user.js');
app.use(userRouter);
config/passport.js
const passport = require('passport');
const local = require('passport-local');
const db = require('../database.js');
const statements = require('../routes/statements/user.js');
const cryptoUtils = require('../utils/crypto.js');
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
try {
let result = await db.conn.one(statements.getUserByIdStatement, [id]);
done(null, result);
} catch (error) {
console.log(`Error while deserializing user: ${error}`);
return done(error);
}
});
passport.use(
new local.Strategy(
{ usernameField: 'email', passwordField: 'password' },
async (username, password, done) => {
try {
let user = await db.conn.one(statements.loginUserStatement, [username]);
if (user == null) {
console.log(`Couldn't find user!`);
return done(null, false);
} else {
let passwordCheck = cryptoUtils.comparePasswords(
password,
user.password,
user.salt
);
if (passwordCheck) {
delete user.password;
delete user.salt;
console.log(`Successfuly logged in!`);
return done(null, user);
} else {
console.log(`Wrong password!`);
return done(null, false);
}
}
} catch (error) {
console.log(`Error during local strategy authentication: ${error}`);
return done(null, false);
}
}
)
);
module.exports = passport;
routes/user.js
router.post('/user/login', (req, res, next) => {
console.log('Authenticating');
passport.authenticate('local', (err, user, info) => {
if (err) {
res.status(500).json({ status: err });
}
if (!user) {
res.status(404).json({ status: 'User not found' });
}
if (user) {
req.logIn(user, function(err) {
if (err) {
res.status(500).json({ status: 'Error while logging in' });
}
res.redirect('/');
});
}
})(req, res, next);
});
router.get('/user/logout', userUtils.loginRequired, (req, res, next) => {
req.logout();
res.status(200).json({ status: 'Logged out' });
});
database.js
const pgp = require('pg-promise')(initOptions);
const conn = pgp(connectionConfig);
module.exports = {
pgp,
conn
};
Any help would be much appreciated.

Related

How to use connect-flash with passport-local

hello every one i was trying to use connect-flash with passport local but can not seem to find relevant info either on the docs and other sources,if any one can guide me on this and tell me what i went wrong ,thanks.And why does request to login-fail gives this error:-
ERROR is AxiosError: Request failed with status code 404
but when i test the route with rest client on vscode it responses perfectly like seen
here.
also when i check the database right after i click submit on the route
there will be two sessions stored consecutively one having the flash(the first) and the other not like this:-
session:
{"cookie":{"originalMaxAge":259200000,"expires":"2023-01-16T12:30:14.395Z","secure":false,"httpOnly":true,"path":"/"},"flash":{"error":["Incorrect password"]}}
session:
{"cookie":{"originalMaxAge":259200000,"expires":"2023-01-16T12:30:14.453Z","secure":false,"httpOnly":true,"path":"/"}}
why this is happening?
userRoutes.js
const router = require("express").Router();
const passport = require("passport");
const { ObjectID } = require("mongodb");
const LocalStrategy = require("passport-local");
const bcrypt = require("bcrypt");
const flash = require("connect-flash");
const User = require("../models/userModel.js");
router.route("/register").post(
(req, res, next) => {
User.findOne({ fullName: req.body.fullName }, (err, user) => {
if (err) {
next(err);
} else if (user) {
res.redirect("/");
} else {
const {
fullName,
email,
id,
department,
stream,
batch,
sex,
age,
phoneNumber,
password,
} = req.body;
const hash = bcrypt.hashSync(password, 12);
console.log(hash);
const newUser = new User({
fullName,
email,
id,
department,
stream,
batch,
sex,
age,
phoneNumber,
password: hash,
});
newUser.save((err, data) => {
if (err) res.redirect("/");
next(null, data);
});
}
});
},
passport.authenticate("local", { failureRedirect: "/" }),
(req, res, next) => {
res.json({ user: "i am josh" });
}
);
router
.route("/login")
.post(
passport.authenticate("local", {
failureRedirect: "/login-fail",
failureFlash: true,
}),
(req, res) => {
res.json({ user: "i am josh" });
}
);
router.route("/login-fail").get((req, res) => {
// console.log(req.flash('error'));
res.json({ user: "josh" });
});
router.route("/logout").get((req, res) => {
req.logout();
res.redirect("/");
});
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findOne({ _id: new ObjectID(id) }, (err, doc) => {
done(null, doc);
});
});
const customFields = {
usernameField: "email",
};
passport.use(
new LocalStrategy(customFields, (email, password, done) => {
User.findOne({ email }, (err, user) => {
//console.log(`User ${user.username} attempted to log in.`);
if (err) return done(err);
if (!user) return done(null, false, { message: "email does not exist" });
if (!bcrypt.compareSync(password, user.password)) {
return done(null, false, { message: "Incorrect password" });
}
return done(null, user);
});
})
);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.json({ msg: "You are not authorized to view this page" });
}
module.exports = router;
server.js
require("dotenv").config();
const express = require("express");
const app = express();
const flash = require("connect-flash");
const session = require("express-session");
const passport = require("passport");
const mongoose = require("mongoose");
const MongoStore = require("connect-mongo");
const cors = require("cors");
app.use(express.json());
// app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(flash());
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
store: MongoStore.create({
mongoUrl: process.env.DB,
collection: "sessions",
}),
cookie: { secure: false, maxAge: 1000 * 60 * 60 * 24 * 3 },
})
);
app.use(passport.initialize());
app.use(passport.session());
mongoose
.connect(process.env.DB)
.then(() => {
console.log("DB connection successful");
})
.catch((err) => {
console.log(`DB connection Error: ${err}`);
});
const usersRouter = require("./routes/userRoutes");
app.use("/user", usersRouter);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`server is running on port ${PORT}`);
});
module.exports = app;
ya,have seen the same question here on stack over flow but none of the answers work

req.isAuthenticated() always return false and req.session.passport is undefined

I know that there are some questions like this already, but i already tried every single response and nothing works, i don't know what the heck to add to app.js to make it work and store the sessions.
Here is my app.js:
const express = require("express");
const cors = require("cors");
const usersRouter = require("./routes/users");
const passport = require("passport");
const cookieParser = require("cookie-parser");
const session = require("express-session");
require("dotenv").config();
const app = express();
const connectDB = require("./db/connect");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser(process.env.SESSION_SECRET));
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true,
cookie: { secure: false },
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use(cors());
app.use("/api/v1/users", usersRouter);
const PORT = process.env.PORT || 5000;
const start = async () => {
try {
await connectDB(process.env.MONGO_URI);
app.listen(PORT, console.log(`Server is listening on port: ${PORT}....`));
} catch (error) {
console.log(error);
}
};
const notFound = require("./middleware/notFound");
app.use(notFound);
start();
My passport-config looks like this:
const localStrategy = require("passport-local").Strategy;
const bcrypt = require("bcryptjs");
const User = require("../models/user");
const initialize = (passport) => {
const authenticateUser = async (email, password, done) => {
let user = await User.findOne({ email: email });
User.findOne({ email: email });
if (!user) {
return done(null, false, {
message: "That email is not registered",
});
}
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user, { message: "User logged in" });
} else {
return done(null, false, { message: "Password incorrect" });
}
} catch (e) {
return done(e);
}
};
passport.use(new localStrategy({ usernameField: "email" }, authenticateUser));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (user, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
};
module.exports = initialize;
And my users router looks like this:
const express = require("express");
const router = express.Router();
const passport = require("passport");
const initializePassport = require("../config/passport-config");
initializePassport(passport);
const { postRegister } = require("../controllers/register");
router.route("/register").post(postRegister);
router.post("/login", function (req, res, next) {
passport.authenticate("local", function (err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json({ message: info.message });
}
console.log(req.session.passport);
res.status(200).json(user);
})(req, res, next);
});
module.exports = router;
I'm making a middleware to authorize or to not authorize the call to another endpoint based on if it is authenticated or if it isn't.
Here is how that middleware looks:
const checkAuthenticated = (req, res, next) => {
const isAuthenticated = req.isAuthenticated();
console.log(req.session.passport);
if (isAuthenticated) {
next();
}
next();
};
module.exports = checkAuthenticated;
const checkNotAuthenticated = (req, res, next) => {
const isAuthenticated = req.isAuthenticated();
if (!isAuthenticated) {
res
.status(401)
.json({ msg: "Not allowed to this path without credentials" });
}
};
module.exports = checkNotAuthenticated;
req.session.passport is undefined, isAuthenticated() is always false, i don't know what to add.
Your bug in the deserializer function:
It will work by changing your deserializer callback argument from user to id as shown below.
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
That was a very obvious bug to me, to be sure you are not missing any other thing, check the lengthy answer I gave to this on another thread a few minutes ago here: https://github.com/jaredhanson/passport/issues/914#issuecomment-1241921637
Good luck.

Cannot set headers after they are sent to the client/ Server crashes with this when page refreshes

Made a Question a few days ago on here, thought I had it figured out, even accepted the answer, because it was right regardless. but now I have the Same issue, same error.
Heres the Error.
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:558:11)
at ServerResponse.header (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:267:15)
at /Users/apple/Documents/Web Dev/collab/Backend/routes/index.js:90:23
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
code: 'ERR_HTTP_HEADERS_SENT'
}
Heres Index.js. Line 90 is at the very bottom,
# router.get("/", isAuth, (req, res)
const router = require("express").Router();
const passport = require("passport");
const bodyParser = require("body-parser");
const genPassword = require("../lib/passwordUtils").genPassword;
const connection = require("../config/database");
const mongoose = require("mongoose");
const User = mongoose.models.User;
const isAuth = require("./authMiddleware").isAuth;
// cors is needed with router.use else you have to put routes on the app.js
const cors = require("cors");
router.use(cors({ origin: "http://localhost:3001", credentials: true }));
// const isAdmin = require("./authMiddleware").isAdmin;
router.use(bodyParser.urlencoded({ extended: false }));
/**
* -------------- Post ROUTES ----------------
*
*/
router.post("/login", (req, res, next) => {
passport.authenticate("local", (err, user, info) => {
if (err) {
throw err;
} else if (!user) {
res.send("No User Exists");
} else {
req.logIn(user, (err) => {
if (err) throw err;
res.send(user);
return;
// console.log(req.user);
});
}
})(req, res, next);
});
router.post("/register", (req, res) => {
const saltHash = genPassword(req.body.repeatPassword);
const salt = saltHash.salt;
const hash = saltHash.hash;
const newUser = new User({
username: req.body.firstInput,
fName: "",
lName: "",
title: "",
hash: hash,
salt: salt,
});
newUser.save().then((user) => {});
res.sendStatus(200);
});
/**
* -------------- GET ROUTES ----------------
*
*/
router.post("/user", (req, res) => {
const fName = req.body.firstInput;
const lName = req.body.secondInput;
const title = req.body.repeatPassword;
const user = req.session.passport.user;
User.updateOne(
{ _id: user },
{ fName: fName, lName: lName, title: title },
function (err, result) {
if (err) {
res.sendStatus(401);
console.log(err);
} else {
res.sendStatus(200);
}
}
);
});
router.get("/", isAuth, (req, res) => {
const userMap = {};
User.find({}, function (err, users) {
users.forEach(function (user) {
userMap[user._id] = user;
});
return userMap;
})
.then((response) => {
res.status(200).json({ user: req.user, auth: true, response });
return;
})
.catch((err) => console.log(err));
});
module.exports = router;
Heres App.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const session = require("express-session");
const passport = require("passport");
const crypto = require("crypto");
const routes = require("./routes");
const isAuth = require("./routes/authMiddleware").isAuth;
const connection = require("./config/database");
const cors = require("cors");
app.use(cors({ origin: "http://localhost:3001", credentials: true }));
const User = mongoose.models.User;
const bodyParser = require("body-parser");
const MongoStore = require("connect-mongo")(session);
require("dotenv").config();
app.use(express.json());
// app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.urlencoded({ extended: true }));
const sessionStore = new MongoStore({
mongooseConnection: mongoose.connection,
collection: "sessions",
});
app.use(
session({
secret: "zdfbdaf",
resave: true,
saveUninitialized: true,
store: sessionStore,
cookie: {
cookie: { secure: false },
maxAge: 1000 * 60 * 60 * 24,
},
})
);
require("./config/passport");
app.use(passport.initialize());
app.use(passport.session());
app.use("/", routes);
app.listen(3000);
heres authMiddleware.js
module.exports.isAuth = (req, res, next) => {
if (req.isAuthenticated()) {
next();
// res.status(200).json({ user: req.user, auth: true });
} else {
res.status(401).json({ auth: false });
}
};
// module.exports.isAdmin = (req, res, next) => {
// if (req.isAuthenticated() && req.user.admin) {
// next();
// } else {
// res.status(401).json({ msg: 'You are not authorized to view this resource because you are not an admin.' });
// }
// }
Heres passport.js
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const connection = require("./database");
const mongoose = require("mongoose");
const User = mongoose.models.User;
const validPassword = require("../lib/passwordUtils").validPassword;
const cors = require("cors");
passport.use(cors({ origin: "http://localhost:3001" }));
const customFields = {
usernameField: "username",
passwordField: "password",
};
passport.use(
new LocalStrategy(customFields, (username, password, done) => {
User.findOne({ username: username })
.then((user) => {
if (!user) {
console.log("No user");
return done(null, false);
} else {
const isValid = validPassword(password, user.hash, user.salt);
if (isValid) {
console.log("Logged in");
return done(null, user);
} else {
console.log("Wrong Password");
return done(null, true);
}
}
})
.catch((err) => {
done(err);
});
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
})
.then((user) => {
done(null, user);
})
.catch((err) => done(err));
});
It only crashes half the time, kind of? It works at first, until you refresh the page. I am at a loss. Had someone in the discord also not know the issue. I'm begging for some help here. I'm losing my mind.
its because you are calling done twice once after finding the user
and second after .then block in passport.deserializeUser function
this will work:
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user)
});
});

passport does not save req.user after authentication

Currently a user can sign in with github, and i can see it gets the req.user in the callback function, and on passport github file
console.log(`frontid ${req.user.id}`) // logs user id
and passport
console.log(`backbro ${id}`); // logs an id
however, when i go on this route, the github user returns null and im not sure why. There were a few times, i see the signed in github user return in the current_user route, however its rare that i see it now. It sometimes shows, sometimes dont. Kinda wierd. Could it be a session issue ?
router.get("/current_user", (req, res) => {
if(req.user){
res.status(200).send({ user: req.user});
} else {
res.json({ user:null})
}
});
yes i looked at the following links, still no suitable answer.
Node + Express + Passport: req.user Undefined
req.user undefined after twitter authentication using express sever, passport.js
The way im accessing this link, is by explictily calling
localhost:8000/api/users/auth/github
in the address bar.
routes/users
router.get('/auth/github', passport.authenticate('github', {
scope:[ 'profile', 'id']
}));
router.get('/auth/github/callback',
passport.authenticate('github', { session:true, failureRedirect: 'http:localhost:8001/signIn' }),
function(req, res) {
// Successful authentication, redirect home.
// var token = jwt.sign({ id: req.user.id}, process.env.JWT_SECRET );
// // res.cookie("jwt", token, { expires: new Date(Date.now() + 10*1000*60*60*24)});
// jwt.verify(token, process.env.JWT_SECRET, function(err, data){
// console.log(err, data);
// })
const user = req.user
req.logIn(user, err => {
models.User.findOne({
where: {
id: req.user.id,
},
}).then(user => {
const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET);
// res.cookie("jwt", token, { expires: new Date(Date.now() + 10*1000*60*60*24)});
jwt.verify(token, process.env.JWT_SECRET, function(err, data){
console.log(err, data);
})
res.redirect('http://localhost:8001');
// console.log(req.user)
});
});
console.log(`frontid ${req.user.id}`)
// res.redirect('')
// console.log('this works', token);
});
passport-github.js
const GitHubStrategy = require('passport-github2').Strategy;
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
const models = require("../models/");
// passport.serializeUser((user, done) => {
// // push to session
// done(null, user.id);
// console.log(user.id)
// });
// passport.deserializeUser((id, done) => {
// models.User.findOne({
// where: {
// id,
// },
// }).then(user => done(null, user))
// .catch(done);
// });
module.exports = async (passport) => {
passport.use(
new GitHubStrategy(
{
clientID: process.env.clientID,
clientSecret: process.env.secret,
callbackURL: 'http://127.0.0.1:8000/api/users/auth/github/callback',
passReqToCallback: true,
profileFields: ['id', 'login']
},
(req, accessToken, refreshToken, profile, done) => {
const { id, login, email} = profile._json;
console.log(`backbro ${id}`);
// console.log(req)
models.User.findOne({
where:{
id: id
}
}).then( user => {
// if user is found
if(user){
return done(null, user)
}
// else create new user
else{
models.User.create({
id: id,
username:login,
email: email,
createdAt: Date.now()
}).then( user => {
console.log('github user created');
return done(null, user);
})
}
})
}
)
);
passport.serializeUser((user, done) => {
// push to session
return done(null, user.id);
});
passport.deserializeUser((userId, done) => {
// console.log('calling deserial' + userId);
// // TODO: findByPk syntax? findById deprecated? Try later after sucessfully record data in DB
models.User
.findOne({ where: { id: userId } })
.then(function(user){
// console.log(user);
return done(null, userId);
}).catch(function(err){
done(err, null);
});
// return done(null, id);
});
}
app.js
const express = require('express');
const app = express();
const userRoute = require('./routes/users');
const postRoute = require('./routes/posts');
const bodyParser = require('body-parser');
const logger = require('morgan');
const session = require('express-session');
const cookieParser = require('cookie-parser') ;
const dotenv = require('dotenv');
const env = dotenv.config();
const cors = require('cors');
const models = require('./models/');
const host = '0.0.0.0';
const PORT = process.env.PORT || 8000;
const passport = require('passport');
const path = require('path');
const Sequelize = require('sequelize');
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const proxy = require('express-http-proxy');
app.use(function(req, res, next) {
res.locals.user = req.user; // This is the important line
// req.session.user = user
console.log(res.locals.user);
next();
});
app.use(cors({
origin: process.env.ALLOW_ORIGIN,
credentials: false,
allowedHeaders: 'X-Requested-With, Content-Type, Authorization',
methods: 'GET, POST, PATCH, PUT, POST, DELETE, OPTIONS',
exposedHeaders: ['Content-Length', 'X-Foo', 'X-Bar'],
}))
var sequelize = new Sequelize(
process.env.POSTGRES_DB,
process.env.POSTGRES_USER,
process.env.POSTGRES_PASSWORD,{
"dialect": "sqlite",
"storage": "./session.sqlite"
});
myStore = new SequelizeStore({
db:sequelize,
})
if (!process.env.PORT) {
require('dotenv').config()
}
// console.log(process.env.DATABASE_URL);
if (!process.env.PORT) {
console.log('[api][port] 8000 set as default')
console.log('[api][header] Access-Control-Allow-Origin: * set as default')
} else {
console.log('[api][node] Loaded ENV vars from .env file')
console.log(`[api][port] ${process.env.PORT}`)
console.log(`[api][header] Access-Control-Allow-Origin: ${process.env.ALLOW_ORIGIN}`)
}
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'build')));
// We need a store in order to save sessions, instead of the sessions clearing out on us :)
require('./config/passport')(passport); // PASSPORT Init
require('./config/passport-github')(passport); // PASSPORT Init
app.use(cookieParser());
app.use(bodyParser.json());
app.use(session({
store: myStore,
saveUninitialized: false,
resave:false,
cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 }, // 30 days
secret : process.env.JWT_SECRET,
}));
myStore.sync();
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.urlencoded({ extended:false}));
// this code may be useless or useful, still trying to understand cors.
app.use('/api/users', userRoute );
app.use('/api/posts', postRoute );
// In order to use REACT + EXPRESS we need the following code, alone with a build
// in the client folder we run a npm run build in the client folder then it is referred
// in the following code.
app.use(express.static(path.join(__dirname, 'client/build')));
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'client/build')));
//
app.get('*', (req, res) => {
res.sendfile(path.join(__dirname = 'client/build/index.html'));
})
}
//build mode
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+'/client/public/index.html'));
})
models.sequelize.sync().then(function() {
app.listen(PORT, host, () => {
console.log('[api][listen] http://localhost:' + PORT)
})
})

Passport + Sequelize not saving req.user

I'm having an issue with saving the session. It appears that logging in and logging out works fine. However, if making code changes or if the nodemon server refreshes, it renders null on the current_user route.
And then this error when making post requests.
Cannot read property 'id' of undefined
router.get("/current_user", (req, res) => {
if(req.user){
res.status(200).send({ user: req.user});
} else {
res.json({ user:null})
}
});
routes
const jwt = require('jsonwebtoken');
const passport = require('passport');
router.post('/loginUser', passport.authenticate('login', {session: true}), (req, res, next) => {
passport.authenticate('login', (err, user, info) => {
if (err) {
console.log(err);
}
if (info != undefined) {
console.log(info.message);
res.status(401).send(info.message);
} else {
req.logIn(user, err => {
models.User.findOne({
where: {
username: req.body.username,
},
}).then(user => {
const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET);
// res.cookie("jwt", token, { expires: new Date(Date.now() + 10*1000*60*60*24)});
jwt.verify(token, process.env.JWT_SECRET, function(err, data){
console.log(err, data);
})
res.status(200).send({
auth: true,
token: token,
message: 'user found & logged in',
});
// console.log(req.user)
});
});
}
})(req, res, next);
});
passport.js
const bcrypt = require('bcrypt'),
BCRYPT_SALT_ROUNDS = 12,
JWTstrategy = require('passport-jwt').Strategy,
ExtractJWT = require('passport-jwt').ExtractJwt,
Sequelize = require('sequelize'),
Op = Sequelize.Op,
models = require( '../models/'),
localStrategy = require('passport-local').Strategy;
// passport = require("passport");
// serialize session, only store user id in the session information
module.exports = async (passport) => {
passport.use(
'register',
new localStrategy(
{
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true,
session: false,
},
(req, username, password, done) => {
try {
models.User.findOne({
where: {
[Op.or]: [
{
username: username,
},
{ email: req.body.email },
],
},
}).then(user => {
if (user != null) {
console.log('username or email already taken');
return done(null, false, {
message: 'username or email already taken',
});
} else {
bcrypt.hash(password, BCRYPT_SALT_ROUNDS).then(hashedPassword => {
models.User.create({
username: req.body.username,
password: hashedPassword,
email: req.body.email
}).then(user => {
console.log('user created');
return done(null, user);
});
});
}
});
} catch (err) {
done(err);
}
},
),
);
passport.use(
'login',
new localStrategy(
{
usernameField: 'username',
passwordField: 'password',
session: false,
},
(username, password, done, req) => {
try {
models.User.findOne({
where: {
[Op.or]: [
{
username: username,
}
],
},
}).then(user => {
if (user === null) {
return done(null, false, { message: 'Username doesn\'t exist' });
} else {
bcrypt.compare(password, user.password).then(response => {
if (response !== true) {
console.log('passwords do not match');
return done(null, false, { message: 'passwords do not match' });
}
console.log('user found & authenticated');
// note the return needed with passport local - remove this return for passport JWT
return done(null, user);
});
}
});
} catch (err) {
done(err);
}
},
),
);
const opts = {
jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT'),
secretOrKey: process.env.JWT_SECRET,
};
passport.use(
'jwt',
new JWTstrategy(opts, (jwt_payload, done) => {
try {
models.User.findOne({
where: {
username: jwt_payload._id,
},
}).then(user => {
if (user) {
console.log('user found in db in passport');
// note the return removed with passport JWT - add this return for passport local
done(null, user);
// console.log(user);
} else {
console.log('user not found in db');
done(null, false);
}
});
} catch (err) {
done(err);
}
}),
);
passport.serializeUser(function(user, done) {
done(null, user.id);
console.log(user.id); // gets user id
});
// from the user id, figure out who the user is...
passport.deserializeUser(function(id, done){
models.User.findOne({
where: {
id,
},
}).then(user => done(null, user))
.catch(done);
});
}
app.js
var express = require('express');
var app = express();
var userRoute = require('./routes/users');
var postRoute = require('./routes/posts');
var bodyParser = require('body-parser');
var logger = require('morgan');
var session = require('express-session');
var cookieParser = require('cookie-parser') ;
var dotenv = require('dotenv');
var env = dotenv.config();
var cors = require('cors');
var models = require('./models/');
const host = '0.0.0.0';
const PORT = process.env.PORT || 8000;
const passport = require('passport');
const path = require('path');
// const allowOrigin = process.env.ALLOW_ORIGIN || '*'
// CORS Middleware
if (!process.env.PORT) {
require('dotenv').config()
}
// console.log(process.env.DATABASE_URL);
if (!process.env.PORT) {
console.log('[api][port] 8000 set as default')
console.log('[api][header] Access-Control-Allow-Origin: * set as default')
} else {
console.log('[api][node] Loaded ENV vars from .env file')
console.log(`[api][port] ${process.env.PORT}`)
console.log(`[api][header] Access-Control-Allow-Origin: ${process.env.ALLOW_ORIGIN}`)
}
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'build')));
app.use(cookieParser());
app.use(session({
secret : process.env.JWT_SECRET,
}));
require('./config/passport.js')(passport); // PASSPORT Init
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.urlencoded({ extended:false}));
app.use(bodyParser.json());
// this code may be useless or useful, still trying to understand cors.
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', true);
res.header("preflightContinue", false)
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
app.use(cors({
origin: process.env.ALLOW_ORIGIN,
credentials: true,
allowedHeaders: 'X-Requested-With, Content-Type, Authorization',
methods: 'GET, POST, PATCH, PUT, POST, DELETE, OPTIONS'
}))
app.use('/api/users', userRoute );
app.use('/api/posts', postRoute );
// In order to use REACT + EXPRESS we need the following code, alone with a build
// in the client folder we run a npm run build in the client folder then it is referred
// in the following code.
app.use(express.static(path.join(__dirname, 'client/build')));
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'client/build')));
//
app.get('*', (req, res) => {
res.sendfile(path.join(__dirname = 'client/build/index.html'));
})
}
//build mode
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+'/client/public/index.html'));
})
app.use(function(req, res, next) {
res.locals.user = req.user; // This is the important line
// req.session.user = user
console.log(res.locals.user);
next();
});
models.sequelize.sync().then(function() {
app.listen(PORT, host, () => {
console.log('[api][listen] http://localhost:' + PORT)
})
})
The question is not so much about saving the req.user, this is an issue with not having a store set in place.
app.use(session({
store: '', // enter a store
secret : process.env.JWT_SECRET,
}));
You're using Sequelize, so i would recommend you to look into this
https://github.com/mweibel/connect-session-sequelize
If all runs well, you will not have to worry about req.id becoming undefined everytime you make a code change. Hope this helps.
You can do something like
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const sequelize = new Sequelize(
process.env.POSTGRES_DB,
process.env.POSTGRES_USER,
process.env.POSTGRES_PASSWORD,{
"dialect": "sqlite",
"storage": "./session.sqlite"
});
myStore = new SequelizeStore({
db:sequelize,
})
app.use(session({
store: myStore,
secret : process.env.JWT_SECRET,
}));

Resources