connect-mongo not storing sessions in DB - node.js

I have an issue with persisting sessions in the DB.
I tried to store the session in MemoryStore to track the session's content, and the outupt is as expected, everything else works as expected.
But with MongoStore , the sessions collection gets createad in the DB and
everything else works as expected, but the session is not stored in the DB !!
Here is the code: ( i'm using Postman to send requests)
index.js -->
const express = require('express');
require('./db');
const passport = require('passport');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const MongoStore = require('connect-mongo');
const authRouter = require('./routes/auth');
const productsRouter = require('./routes/routing');
require('./routes/passport-local');
// const memoryStore = new session.MemoryStore();
const app = express();
const PORT = 3000;
app.listen(PORT, () => console.log(`Server running on Port ${PORT}`));
app.use(express.json());
app.use(cookieParser());
app.use(
session({
secret: 'ALKSDFLKSDLFMK',
resave: false,
saveUninitialized: false,
sotre: MongoStore.create({
mongoUrl: 'mongodb://localhost/express_tuto',
}),
// store: memoryStore,
})
);
app.use(passport.initialize());
app.use(passport.session());
// app.use((req, res, next) => {
// console.log(memoryStore);
// console.log(req.user);
// next();
// });
app.use('/auth', authRouter);
app.use('/products', productsRouter);
./routes/auth.js -->
const { Router } = require('express');
const passport = require('passport');
const router = Router();
router.post(
'/login',
passport.authenticate('local'),
(req, res) => {
console.log(req.session);
console.log(req.user);
console.log(`sessionID: ${req.sessionID}`);
res.send('Logged in');
}
);
module.exports = router;
./routes/passport-local.js -->
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
const User = require('../db/schemas/User');
const passport = require('passport');
passport.serializeUser((user, done) => {
console.log('serializing');
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
console.log('deserializing');
try {
const user = await User.findById(id);
if (user) {
done(null, user);
}
} catch (err) {
console.log(err);
done(err, null);
}
});
passport.use(
new LocalStrategy(
{ usernameField: 'email' },
async (email, password, done) => {
const user = await User.findOne({ email });
if (!user) {
console.log('no matching email!');
done(null, false);
}
try {
if (await bcrypt.compare(password, user.password)) {
console.log('user found');
done(null, user);
} else {
console.log('password incorrect');
done(null, false);
}
} catch (err) {
return done(err);
}
}
)
);
I am expecting to see the session stored in the DB given that everything ELSE works as expected!

My bad, there is a typo in the session store option.
sotre: MongoStore.create...//--> store:

Related

Passport.js authentication goes in infinite loop

I have been trying to build the authentication using PassportJs and MongoDB. I am using PassportJS only to log in. But, while submitting the post request it does not redirect me to the failureRedirect route, nor to the SuccessRedirect one, instead, the web page enters into an endless loop.
The code I have written is -
It has 2 files- app.js and user.js
App.js file -
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const passport = require('passport');
const mongoose = require('mongoose');
require('./db/db')
var fileupload = require('express-fileupload');
const path = require('path');
const app = express();
app.use(fileupload({
useTempFiles: true
}));
const session = require('express-session');
const mongostore = require('connect-mongo');
app.use(express.static(path.join(__dirname,'public')));
// session middle ware
app.use(session({
secret : 'mysupersecret',
resave : false,
saveUninitialized : false,
store: mongostore.create({
mongoUrl: process.env.DB,
}),
cookie : { maxAge : 180 * 60 * 1000 }
}));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static("public"));
app.use(bodyParser.json());
app.use(passport.initialize());
app.use(passport.session());
app.get("/", (req, res) => {
res.render("index");
});
app.use("/admin", require("./routes/admin"));
app.use("/user", require("./routes/user"));
app.use("/task", require("./routes/task"));
// PORT
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
User.js file -
const express = require("express");
const bodyParser = require("body-parser");
const router = express.Router();
const bcrypt = require("bcryptjs");
const passport = require("passport");
const User = require("../models/User");
const Task = require("../models/Task");
var LocalStrategy = require('passport-local');
// var bcrypt = require('bcryptjs');
var strategy = new LocalStrategy(function verify(email, password, done) {
try{
console.log(email);
User.findOne({email: email}, function (err, user) {
console.log(email);
if (err)
console.log(err);
if (!user) {
console.log("doen exist")
return done(null, false);
}
bcrypt.compare(password, user.password, function (err, isMatch) {
if (err)
console.log(err);
if (isMatch) {
return done(null, user);
} else {
console.log("galat password");
return done(null, false);
}
});
});
}catch(err){
console.log(err);
}
});
passport.use('epass',strategy);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
// User login
router.get("/login", (req, res) => {
res.render("user-login");
});
router.post("/login", (req,res) => {
try{
passport.authenticate('epass', { failureRedirect: '/user/login' }),
function(req, res,next) {
res.redirect('/user');
}
}catch(err){
console.log(err);
}
});
router.get("/", (req, res) => {
res.render("user")
})
module.exports = router;
I have searched everywhere and tried all the available possible solutions but nothing is solving this.
passport.authenticate() should be used as a middleware, not as a regular function:
router.post("/login",
passport.authenticate('epass', { failureRedirect: '/user/login' }),
function(req, res,next) {
res.redirect('/user');
}
);
The way you were using it causes the request to POST /user/login to never finish, because it's not sending back any response.
EDIT: also, make sure that you either use the default field names of username and password for logging in, or add the relevant options to the constructor of LocalStrategy to tell it which fields it should be expecting.

Passport Local Strategy returns not found

I'm trying to make a register/login with node, express and mongoose. I want to register and login users and if they aren't logged in they can't retrieve data from the api.
To make the login and register i have been watching this tutorial: Link it isn't as addecuate for my needs because half of the efforts and code goes into the ejs but i have been okay until the passport login.
I have created my local strategy in config/passport.js:
const LocalStrategy = require("passport-local").Strategy;
const bcrypt = require("bcryptjs");
const User = require("../models/user");
module.exports = function (passport) {
passport.use(
new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
User.findOne({ email: email })
.then((user) => {
if (!user) {
return done(null, false, {
message: "That email is not registered",
});
}
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) console.log(err);
if (isMatch) {
return done(null, user);
} else {
done(null, false, { message: "Incorrect Password" });
}
});
})
.catch((err) => console.log(err));
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
};
My app.js looks like this:
const express = require("express");
const cors = require("cors");
const usersRouter = require("./routes/users");
const passport = require("passport");
const session = require("express-session");
require("dotenv").config();
const app = express();
require("./config/passport")(passport);
const connectDB = require("./db/connect");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
session({
secret: "*****",
resave: true,
saveUninitialized: true,
})
);
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 users router looks like this:
const express = require("express");
const router = express.Router();
const { postRegister } = require("../controllers/register");
router.route("/register").post(postRegister);
const { postLogin } = require("../controllers/login");
router.route("/login").post(postLogin);
module.exports = router;
The register works perfectly, but the login controller doesn't. Each time i post to that endpoint instead of getting a succesMessage or failureMessage i get the page not found router that is called at the end of app.js, i checked if the router calls the login function via a console log and it does. Here is the code for the login controller:
const passport = require("passport");
const postLogin = (req, res, next) => {
console.log("The function has been triggered");
passport.authenticate("local", {
successMessage: "Login authenticated",
failureMessage: "Login failed",
})(req, res, next);
};
module.exports = {
postLogin,
};
Why don't I get the responses from the login controller or my local strategy and instead i get page not found when the Login controller actually works?

successRedirect is not working in passport login passport-local

I am using node.js express with sequelize and database postgreSql.the problem is in passport login failureRedirect works properly sucessRedirect does not redirect to the page that I want. It still loading and not responding anything and does not come any error.
when I submit login it will check for errors if errors it will work perfectly in failureRedirect but in Success it does not work like page has loading only not goes to the destination page and if I stop the project and restart the project it will be in destination page!! i dont know what is the problem help me.
mainController.js
const express = require("express");
const sessions = require("express-session");
require("../model/MasterUser.model");
const passport = require("passport");
var session = sessions;
const router = express.Router();
router.get("/dashboard", (req, res) => {
res.render('dashboard');
});
router.get("/login", (req, res) => {
res.render("login", { layout: "login.hbs" });
});
router.post(
"/login",
passport.authenticate("local", {
successRedirect: "/main/dashboard",
failureRedirect: "/main/login",
failureFlash: true,
})
);
module.exports = router;
passport.js
const LocalStrategy = require("passport-local").Strategy;
const bcrypt = require("bcryptjs");
const sequelize = require("sequelize");
const masterUser = require("../model/MasterUser.model");
module.exports = function (passport) {
passport.use(
new LocalStrategy(
{ usernameField: "user_name" },
(user_name, password, done) => {
// Match user
masterUser.findOne({ where: { user_name: user_name } }).then((user) => {
if (!user) {
return done(null, false, {
message: "This username is not registered",
});
}
// Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: "Password incorrect" });
}
});
});
}
)
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
masterUser.findByPk(id, (err, user) => {
done(err, user);
});
});
};
index.js
const express = require("express");
const Handlebars = require("handlebars");
var flash = require("connect-flash");
const app = express();
const path = require("path");
const bodyparser = require("body-parser");
const expressHandlebars = require("express-handlebars");
const passport = require("passport");
const sessions = require("express-session");
var session = sessions;
const MainController = require("./controllers/MainController");
const db = require("./config/database");
//test db
db.authenticate()
.then(() => console.log("Database Connected..."))
.catch((err) => console.log("error" + err));
//for security purpose
const cors = require("cors");
app.use(
cors()
);
//Passport Config
require("./config/passport")(passport);
app.use(cookieParser());
//use body parser
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: true }));
const {
allowInsecurePrototypeAccess,
} = require("#handlebars/allow-prototype-access");
app.use(
bodyparser.urlencoded({
urlencoded: true,
})
);
app.use(
sessions({
secret: "secret_key",
resave: false,
saveUninitialized: true,
cookie: { maxAge: 60000 },
})
);
// use flash for show messages
app.use(flash());
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
//flash messages
app.use((req, res, next) => {
res.locals.success_msg = req.flash("success_msg");
res.locals.error_msg = req.flash("error_msg");
res.locals.error = req.flash("error");
next();
});
//setting up view Engine
app.set("views", path.join(__dirname, "/views"));
//using the hbs
app.engine(
"hbs",
expressHandlebars({
extname: "hbs",
defaultLayout: "default",
layoutsDir: __dirname + "/views/layouts",
handlebars: allowInsecurePrototypeAccess(Handlebars),
})
);
app.set("view engine", "hbs");
//route for Main
app.use("/main", MainController);
//default
app.get("/", (req, res) => {
res.render("login");
});
app.listen(3000, () => {
console.log("App listening on port 3000!");
});
the problem has been solved guys I made done wrong code in deserializeUser.
passport.js before
passport.deserializeUser((id, done) => {
masterUser.findByPk(id, (err, user) => {
done(err, user);
});
});
};
passport.js after
passport.deserializeUser(function (id, done) {
masterUser.findOne({ where: { id: id } }).then((user) => {
done(null, user);
});
});
the problem is for sequelize get the user data is different so now its worked for me.this is useful for who using express with sequelize and passport with postgresql

Connect-pg-simple not saving session to database

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.

Passport Not Authenticating Correctly

This is my first time doing user authentication and I think I'm nearly complete. I'm using Express with Passport.js and MongoDB/Mongoose. When I run my gulp file everything loads correctly but when I attempt to login with my credentials I'm constantly redirected to the failure page (home screen). Here's my code:
// Initialize
const bodyParser = require('body-parser')
const path = require('path')
const bcrypt = require('bcryptjs')
const express = require('express')
const session = require('express-session')
const cookieParser = require('cookie-parser')
const passport = require('passport'),
LocalStrategy = require('passport-local').Strategy
let userData = require('./models/user.js')
const app = express()
// Configuration
app.use(cookieParser())
app.use(session({ secret: 'ThisIsTheSessionSecret', resave: true, saveUninitialized: true }))
app.use(passport.initialize())
app.use(passport.session())
app.use(express.static(path.join(__dirname, '../../docs')))
app.use(express.static(path.join(__dirname, '../../src')))
app.set('port', process.env.PORT || 8080);
app.set('view engine', 'pug')
app.set('views', 'src/pages')
let urlencodedParser = bodyParser.urlencoded({ extended: false })
// Configure authentication and sessions
passport.use(new LocalStrategy(
function(username, password, done) {
user.findOne({ username: username }, function(err, user) {
if (err) { console.log(err) }
if (!user) {
return done(null, false, { message: 'Incorrect username.' })
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' })
}
return done(null, user)
})
}
));
// Session
passport.serializeUser(function(user, done) {
done(null, user.id)
});
passport.deserializeUser(function(id, done) {
user.findById(id, function(err, user) {
done(err, user)
})
})
app.listen(app.get('port'))
console.log('Listening on port: ' + app.get('port'))
// Initialize database (local or remote?)
const MongoClient = require('mongodb').MongoClient,
mongoose = require('mongoose'),
assert = require('assert')
const database = 'mongodb://localhost:27017/database'
mongoose.connect(database)
let db = mongoose.connection
db.on('error', console.error.bind(console, 'connection error'))
db.once('open', function() {
// let testUser = new userData.UserModel({ username: 'PodcatchUser', password: 'RIPHarambe' })
// console.log(testUser.username)
})
// Routing
app.get('/', function(req, res) {
console.log('Welcome!')
res.render('index')
})
// Registration
app.post('/signup', urlencodedParser, function(req, res) {
let username = req.body.username,
password = req.body.password,
salt = bcrypt.genSaltSync(10),
hash = bcrypt.hashSync(password, salt)
let user = new userData.UserModel({
username: username,
password: hash
})
console.log(user.username)
console.log(user.password)
user.save(function(err) {
if (err) {
return console.log(err, user)
} else {
console.log('User has been saved to the database successfully')
}
})
res.end()
})
// Login
app.post('/login', passport.authenticate('local', { successRedirect: '/success',
failureRedirect: '/' }), function(req, res) {
res.end()
})
and the code in the userData module:
const mongoose = require('mongoose')
let UserSchema = mongoose.Schema({
username: String,
password: String
})
let UserModel = mongoose.model('UserModel', UserSchema)
module.exports.UserSchema = UserSchema
module.exports.UserModel = UserModel
I'm really confused as to what's happening. Mongo saves the credentials and hashed password to the database, I create a session and have a cookie parser but it doesn't authenticate. Help would be greatly appreciated :)

Resources