I'm using the express-session package and I want to change the variable "_id" in the session.
Here my session init
app.use(session({
secret: "secretshhhhhh",
resave: true,
saveUninitialized: false,
}))
After the login page I try to store the id with these few lines:
req.session._id = user._id.toString()
req.session.save(function (err) {
req.session.save(function (err) {
console.log(req.session)
})
})
The console.log print the session with the id, but when I try to get the _id in an other page express send me back a null object. Here an exemple of printing session without the _id
return res.status(200).send(req.session);
I tried many methods but none of these worked for me.
EDIT:
Here my whole function to put it in session
module.exports.login_post = async function (req, res) {
User.findOne({ email: req.body.email }, function (err, user) {
if (user == null) {
return res.status(400).send({
message: "User not found"
})
}
else {
if (user.validPassword(req.body.password)) {
req.session._id = user._id.toString()
req.session.save(function (saveErr) {
req.session.reload(function (reloadSave) {
console.log(req.session, saveErr, reloadSave)
})
})
}
}
})
}
Here my whole function to get it from session
module.exports.session_get = function(req, res) {
return res.status(200).send(req.session);
}
module.exports.session_destroy = function(req, res) {
req.session.destroy();
return res.status(200).send({
message: "Session detroyed"
});
}
Related
the problem is when i log req.session.user i get the user results not problem, but when i try to log socket.request.session i get an empty session without the user data, even if i use socket.request.session.user i get user is undefined. whats the problem with it? i really need some help its for my college project which is in the next week
i've followed the docs on socket.io page : https://socket.io/how-to/use-with-express-session
but it doesn't seem like its sharing my session to the socket, im trying to access user data on socket connection
This is my session/socket.io setup
const session = require("express-session");
const sessionMiddleware = session({
secret: "testing",
resave: false,
saveUninitialized: false
});
const wrap = middleware => (socket, next) => middleware(socket.request, {}, next);
module.exports = {sessionMiddleware, wrap};
io.use(wrap(sessionMiddleware));
io.on("connection", (socket) => {
console.log(socket.request.session)
// On new post
socket.on("newPost", (post) => {
console.log(post)
})
console.log(socket.id)
});
and this is my login setup
router.post("/login", async (req, res) => {
const data = {
username: req.body.username.toString(),
password: req.body.password.toString()
}
console.log(data)
if(data.username === "") {
res.json({
status: "error",
message: "Username is required"
})
return;
}
if(data.password === "") {
res.json({
status: "error",
message: "Password is required"
})
return;
}
let user = await new userClass();
if(await user.login(data.username, data.password)) {
req.session.user = await user.getUser();
console.log(req.session.user)
res.redirect("/");
return
} else {
res.redirect("/entry?error=username or password is incorrect");
return;
}
})
When ever I submit a from to login in or get registered I get 400 bad request. But in register route the user get registered but it also gives bad request. When we go to login route same as register route I get BAD REQUEST. 0
I am using the following dependencies:
express session
passport
passport-local
passport-local-mongoose
Is there something wrong with the implementation of the passport-local-mongoose or its passport side or serialize or deserialize the user. Can anybody help me with this problem I am stuck on this for three days. Here is some code.
//-----------------------//Require---------------------
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const ejs = require("ejs");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy= require("passport-local").Strategy;
const passportLocalMongoose = require("passport-local-mongoose");
const mongoose = require("mongoose");
//-----------------------//App.use---------------------
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
//-----------------------//Passport---------------------
app.use(passport.initialize());
app.use(passport.session());
//-----------------------//Mongoose---------------------
mongoose.connect('mongodb://localhost/Twitter', {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set('useCreateIndex', true);
const tweetschema = new mongoose.Schema({
username: String,
password: String,
tweets: String
});
//-----------------------//Schema Plgin---------------------
tweetschema.plugin(passportLocalMongoose);
//-----------------------//New Model---------------------
const Tweet = new mongoose.model("Tweet", tweetschema);
//-----------------------//Local Strategy-------------------
passport.use(new LocalStrategy(Tweet.authenticate()));
//-----------------------//Seralize Passport---------------------
passport.serializeUser(Tweet.serializeUser());
passport.deserializeUser(Tweet.deserializeUser());
//-----------------------//Get Routes---------------------
app.get("/" ,(req, res)=>{
Tweet.find({}, function(err, founItems){
res.render("home", {founItems:founItems});
});
});
app.get("/tweets", (req, res)=>{
if(req.isAuthenticated()){
res.render("Tweets");
}else{
res.redirect("/login");
}
});
//-----------------------//Post Routes---------------------
app.post("/login", (req, res)=>{
const user = new Tweet({
username: req.body.email,
password: req.body.password
});
req.logIn(user, (err)=>{
if(err){
res.send(err);
}
passport.authenticate("local")(req, res, ()=>{
console.log("Successfull.");
})
})
});
app.post("/reg", (req, res)=>{
Tweet.register({username: req.body.email}, req.body.password, (err, user)=>{
if(err){
console.log(err);
res.redirect("/reg");
}else{
if(user){
passport.authenticate("local")(req, res, ()=>{
res.redirect("/tweets");
console.log("Successfully Regsitered The User!");
})
}
}
})
})
You redirect user to /login route, but you don't have get request for this.
If you have it but not uploaded try this in Seralize Passport
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
What about this:
app.post("/login", (req, res) => {
const email = req.body.email;
User.findOne({ username: email }, function (err, u) {
if (err) {
console.log(err);
} else {
if (u) {
u.authenticate(req.body.password, (err, model, info) => {
if (info) {
res.send("Wrong email or password!");
}
if (err) {
console.log(err);
} else if (model) {
req.login(u, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local");
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
}
});
}
});
} else {
res.send("Wrong email or password!");
}
}
});
});
So you first search user in the database with email: User.findOne({ username: email }, function (err, u){} I suggest to make username unique username: { type: String, unique: true} in tweetSchema.
After that you check for err. If u exists, you authenticate it with password. According to passport-local-mongoose- u.authenticate(password, (err, model, info)=>{}) has two arguments: password and callback function. In callback we check for info which is "an instance of AuthenticationError describing the reason the password failed, else undefined." After that we check for err and it is "null unless the hashing algorithm throws an error." And finally, we check for model that is "the model getting authenticated if authentication was successful otherwise false."
So, model is authenticated. After that we must use the user with req.login(u,(err)). Check for errors and if everything is alright, we authenticate user locally passport.authenticate("local");. If you want to save session, write:
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
That's all.
For registration :
app.post("/register", (req, res) => {
const email = req.body.email;
const password = req.body.password
User.find({ email: email }, function (err, docs) {
if (docs.length === 0) {
User.register(
{
username: email,
},
password,
function (err, user) {
if (err) {
console.log(err);
} else {
req.login(user, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local");
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
}
});
}
}
);
} else {
res.send("The accout already exists!");
}
});
});
I am reading an article about nodejs express module and sessions here
https://www.codementor.io/emjay/how-to-build-a-simple-session-based-authentication-system-with-nodejs-from-scratch-6vn67mcy3
I am confused on this portion of the code
app.use((req, res, next) => {
if (req.cookies.user_sid && !req.session.user) {
res.clearCookie('user_sid');
}
next();
});
from where did the req object get the user property ?
If we look at the article the session object is created like
app.use(session({
key: 'user_sid',
secret: 'somerandonstuffs',
resave: false,
saveUninitialized: false,
cookie: {
expires: 600000
}
So how does this even work
if (req.cookies.user_sid && !req.session.user)
how does the req.cookies.user_id shouldnt it be req.cookies.key ?
How does req.session.user work ?
user is not even a property of the session object no ?
Look further down in the article. There are several instances where req.user is an lvalue. In fact it's entirely up to you to assign to it:
The article posits this code block:
Signup:
// route for user signup
app.route('/signup')
.get(sessionChecker, (req, res) => {
res.sendFile(__dirname + '/public/signup.html');
})
.post((req, res) => {
User.create({
username: req.body.username,
email: req.body.email,
password: req.body.password
})
.then(user => {
/*
* The user just signed up, so let's sign him in
*/
req.session.user = user.dataValues;
res.redirect('/dashboard');
})
.catch(error => {
res.redirect('/signup');
});
});
Logging In:
// route for user Login
app.route('/login')
.get(sessionChecker, (req, res) => {
res.sendFile(__dirname + '/public/login.html');
})
.post((req, res) => {
var username = req.body.username,
password = req.body.password;
User.findOne({ where: { username: username } }).then(function (user) {
if (!user) {
res.redirect('/login');
} else if (!user.validPassword(password)) {
res.redirect('/login');
} else {
/*
* The user just logged in so lets sessionize them
*/
req.session.user = user.dataValues;
res.redirect('/dashboard');
}
});
});
I have read a lot about this issue but any answer doesn't work for me. I am working with React, Express and Passport to manage my authenticate routine. The authentication routine is fine, and it makes the redirect that I want. But, when I refresh any route, it says me that I am not authenticate. It seems that Passport doesn't save the session. Here my code:
Server.js
const lisaApp = express();
lisaApp.use(bodyParser.json())
lisaApp.use(bodyParser.urlencoded({ extended: false }))
lisaApp.use(cookieParser())
lisaApp.use(session({
secret: config.secret,
resave: false,
saveUnitialized: false
}))
lisaApp.use(passport.initialize())
lisaApp.use(passport.session())
passport.use(auth.localStrategy);
passport.serializeUser(auth.serializeUser);
passport.deserializeUser(auth.deserializeUser);
lisaApp.post('/login', (req, res, next) => {
const validationResult = validateLoginForm(req.body);
if (!validationResult.success) {
return res.status(400).json({
success: false,
message: validationResult.message,
errors: validationResult.errors
});
}
return passport.authenticate('local', (err, userData) => {
if (err) {
if (err.response.statusText === 'Unauthorized') {
return res.status(400).json({
success: false,
message: 'The password is not right'
});
}
return res.status(500).json({
success: false,
message: 'Wrong data'
});
}
console.log('is authenticated?: ' + req.isAuthenticated()) // Here always is false
return res.json({
success: true,
token,
message: 'Successful Login',
user: userData.data
});
})(req, res, next);
});
// I am using this function as a middleware to check if the user is authenticated, always is false. No matter if I put right data in the login form
function ensureAuth (req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.status(401).send({ error: 'not authenticated' })
}
auth/index.js(passport routine)
var LocalStrategy = require('passport-local').Strategy;
var LisaClient = require('pos_lisa-client');
var config = require('../config');
var ClientApi = LisaClient.createClient(config.lisaClient);
exports.localStrategy = new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
session: false,
passReqToCallback: true
}, (req, username, password, done) => {
var authData = {
username,
password
}
// Here is a custom API, I pass the data that I need. This works fine
ClientApi.authenticate(authData, (err, token) => {
if (err) {
return done(err)
}
var token = token.data
ClientApi.getClient(username, (err, user) => {
if (err) {
return done(err)
}
user.token = token
return done(null, user)
})
})
})
exports.serializeUser = function (user, done) {
// The app never enters here
done(null, {
username: user.username,
token: user.token
})
}
exports.deserializeUser = function (user, done) {
// The app never enters here
ClientApi.getClient(user.username, (err, usr) => {
if (err) {
return done(null, err)
} else {
usr.token = user.token
done(null, usr)
}
})
}
Where I am wrong?
If you're using a custom authentication callback, you have to call req.logIn() to establish a session (or you can create one manually):
// Add this where you are console.log'ing `req.isAuthenticated()`
req.logIn(userData, function(err) {
if (err) return next(err);
console.log('is authenticated?: ' + req.isAuthenticated());
return res.json({
success: true,
token,
message: 'Successful Login',
user: userData.data
});
});
This is documented here (scroll down to "Custom Callback"):
Note that when using a custom callback, it becomes the application's responsibility to establish a session (by calling req.login()) and send a response.
I want to remove previous session from MongoStore/sessionStore if a user login from new device. MEANJS is using
express-session
connect-mongo
to store sessions in mongodb. I did search on it but could not find a solution to fetch the list of sessions from db. Please help me here
MongoStore = require('connect-mongo')(session),
favicon = require('serve-favicon'),
module.exports.initSession = function (app, db) {
// Express MongoDB session storage
app.use(session({
saveUninitialized: true,
resave: true,
secret: config.sessionSecret,
cookie: {
maxAge: config.sessionCookie.maxAge,
httpOnly: config.sessionCookie.httpOnly,
secure: config.sessionCookie.secure && config.secure.ssl
},
key: config.sessionKey,
store: new MongoStore({
mongooseConnection: db.connection,
collection: config.sessionCollection
})
}));
};
This should work, at least it's a good starting point for you
var async = require('async'); //npm install async --save
exports.removeSessionsForUser = function(req, res, next) {
var userId = req.user ? req.user.id : undefined;
if (!userId)
return next(new Error('No user found in req. Exiting'));
var store = req.sessionStore;
var sessionsColl = store.db.collection('sessions');
sessionsColl.find({
'session.user': userId,
// we are tryin to remove all sessions, you can leave current
// '_id': { '$ne': req.sessionID }
}, { _id : 1 }, function (err, userSessions) {
async.each(userSessions, function (userSession, cb) {
store.destroy(userSession._id, cb);
}, function(notDone) {
if(notDone)
return next(new Error(notDone));
res.send('ok');
});
});
}
This uses async.each, which is
async.each(Array, function(item, callback) {/* iterate */}, function(error) {/* end */});
Finally with the help I would be able solve the issue
Here is my code
exports.logoutFromPreviousDevices = function (req, res) {
var userId = req.query.userid;
if (!userId)
return res.status(400).send({
message: errorHandler.getErrorMessage('No user found in input request')
});
var store = req.sessionStore;
var sessionsColl = store.db.collection('sessions');
sessionsColl.find({
// 'session.passport.user': userId,
// we are tryin to remove all sessions, you can leave current
// '_id': { '$ne': req.sessionID }
}, function (err, userSessions) {
if (userSessions !== null) {
userSessions.toArray(function (a, sessionsData) {
sessionsData.forEach(function (element, index) {
var data = JSON.parse(element.session);
if (element._id !== req.sessionID && req.query.userid === data.passport.user) {
store.destroy(element._id, function (destroyerr, dat) {
if (destroyerr)
return res.status(400).send({
message: errorHandler.getErrorMessage(destroyerr)
});
res.jsonp({ status: 'Previous session deleted' });
});
}
});
});
} else {
res.jsonp({ status: 'No session found' });
}
});
};