I am a beginner Node.js developer and am working on a web app for which I need session management. I'm defining Express session like the following:
app.use(cookieParser());
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: true,
cookie: {
expires: 600000
}
}));
And set the session variable in /signup (not shown) and /login. However, if I try to access req.session in any other route, it shows up as "undefined". Does anyone have any input on this?
router.post('/login', async function(req, res) {
console.log(req.body);
var email = req.body.email,
password = req.body.password;
let user = await User.findOne({ email: email });
if (!user) {
res.status(400).send("Failure");
} else if (!bcrypt.compareSync(req.body.password, user.password)) {
res.status(400).send("Failure");
} else {
req.session.user = user;
res.status(201).send("Success");
}
});
Related
I'm having problem with express-session, it seems like it's not saving my user session. Here is when I declare my session:
// Session
// app.use(express.urlencoded({ extended: true }));
app.use(session({
secret: "key per i cookie",
saveUninitialized: false,
resave: false,
store: MongoStore.create({
mongoUrl: process.env.URI,
autoRemove: 'disabled'
}),
cookie: { maxAge:30000, secure:false }
}));
app.use(cookieParser());
app.use(function(req, res, next) {
res.locals.session = req.session.user;
next();
});
And then saving it when user is logged in
app.post('/login', async (req,res) => {
const { username, password } = req.body
const user = await User.findOne({username}).lean()
if(!user) {
return res.json({status:'error', error:'Username o password non validi'})
}
if (await bcrypt.compare(password, user.password)) {
const token = jwt.sign({
id: user._id,
username: user.username
}, JWT_SECRET);
req.session.user = username;
req.session.save();
console.log('Utente loggato ' + req.session.user);
return res.json({ status: 'ok', data: token });
}
res.json({status:'error',error:'Username o password non validi'});
});
Apparently in the post I save the session but after login, when trying to access in an EJS page with
<% if(session.user) { %>
<h1>Session stored</h1>
<% } else { %>
<p>No session</p>
<% }%>
I got no session stored. What am I doing wrong?? Thanks in advance
I think you should use the secret phrase used in your session in your cookie parser
app.use(cookieParser("key per i cookie"))
i am using nodejs and mongodb, the problem is that my express session doesn't work
Frontend code:
$(document).on('click', "#signin", function(){
$.ajax({
type: "POST",
url: "/conectare",
data: {username: $(".username").val(), password: $(".password").val()},
success: function(res){
atentionare(res); // this is a function that displays a message on the screen
load_signin_options(); // this is a function that appends more buttons on my navbar
}
})
});
and my server code:
app.post('/conectare', function(req,res ){
var user = req.body.username;
var pass = req.body.password;
MongoClient.connect(uri, function(err,db){
var dbc=db.db("mydb");
dbc.collection('user').find({username: {$eq: user}}).toArray(function (err, result){
let len= result.length;
if( len == 0 ){
res.send("User does not exist");
}
else{
var a = result[0];
if(pass===a.password){
res.send("successfully connected");
req.session.username = user;
console.log("parola e buna");
}
else{
res.send("Incorrect password");
}
}
});
db.close();
});
});
this is my session, i also installed express-session
app.use(session({
secret: 'secret',
resave: true,
cookie: { maxAge: 0 },
saveUninitialized: true
}));
i tryed to follow this post How to create sessions in node.js
but and i found out that my session doesnt work, but i don;t understand how to make it work
You set your cookie to maxAge = 0, meaning you're never creating the cookie needed to hold the sessionId.
Change to:
app.use(session({
secret: 'secret',
resave: true,
cookie: { maxAge: 3600 },// one hour
saveUninitialized: true
}));
Recently I've found tricki bug in my express js project and I would be grateful for help with debugging it.
This is related question, but answer is not resolving problem, because I want to specify maxAge and deleting this parameter from session configuration is not solution for me.
I am using Passport js + express-session
This is my session configuration:
var passport = require('passport');
var session = require('express-session');
var cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(session({
secret: 'MySecret',
resave: false,
saveUninitialized: false,
cookie : {
secure: false, // If it's true, login is not working as well
maxAge: new Date(Date.now() + (60 * 1000 * 30))
}
}));
app.use(passport.initialize());
app.use(passport.session());
To check that user is authenticated I'm using simple middleware:
middlewareObj.isLoggedIn = function(req, res, next) {
if (req.isAuthenticated()){
return next();
} else {
return res.redirect('/signin');
}
};
Passport local-signin:
passport.use('local-signin', new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function (req, email, password, done) {
var User = user;
var isValidPassword = function (userpass, password) {
return bCrypt.compareSync(password, userpass);
}
User.findOne({
where: {
email: email
}
}).then(function (user) {
if (!user) {
return done(null, false, req.flash('error', 'User does not exists'));
}
if (!isValidPassword(user.dataValues.userPassword, password)) {
return done(null, false, req.flash('error', 'Incorrect password.'));
}
return done(null, {user});
}).catch(function (error) {
return done(null, false, req.flash('error',error.message));
});
}
));
This is my logout route:
router.get('/logout',(req,res) => {
req.session.destroy(function(err) {
return res.redirect('/');
});
});
Standard user login is working fine, after submitting sign in form user is serialized than deserialized and isAuthenticated() method returns true.
But cookie configuration(maxAge exactly) is making some problems. When cookie lifetime expired, next user's login is not working anymore. isAuthenticated() method is returning false (user object does't exist inside req).
After restarting server, user can login normally, but when cookie maxAge is reached, next login is not working again. Passport is not showing any errors.
It likely has something to do with your maxAge value. The expressjs/sessions package docs point out that maxAge is "the number (in milliseconds) to use when calculating the Expires Set-Cookie attribute".
You're passing a Date to maxAge; it's expecting the number of milliseconds until the cookie expires.
The session of my nodejs app is expiring every time I refresh the page, after login. It does work fine if I visit different pages but as soon as I refresh the page, the session ends. I've tried a couple of things but none of it seems to work. How can I keep it from expiring even after the page refresh? If I can store session in the database or someplace else to keep it from expiring.
Here are the files
Passport-init.js
var mongoose = require('mongoose');
var User = mongoose.model('user');
var localStrategy = require('passport-local').Strategy;
var bcrypt = require('bcrypt-nodejs');
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
console.log('serializing user:',user.username);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
if(err) {
done(500,err);
}
console.log('deserializing user:',user.username);
done(err, user);
});
});
passport.use('login', new localStrategy({
passReqToCallback : true
},
function(req, username, password, done) {
User.findOne({'username': username},
function(err, user) {
if(err) {
return done(err);
}
if(!user) {
console.log("UserName or Password Incorrect");
return done(null, false);
}
if(!isValidPassword(user, password)) {
console.log("UserName or Password is Incorrect");
return done(null, false);
}
return done(null, user);
});
}));
passport.use('signup', new localStrategy({
passReqToCallback : true
}, function(req, username, password, done) {
User.findOne({'username': username},
function(err, user) {
if(err) {
console.log("Error in signup");
return done(err);
}
if(user) {
console.log("Username already exist" + username);
return(null, false);
}
else {
var newUser = new User();
newUser.username = username;
newUser.password = createHash(password);
newUser.save(function(err) {
if(err) {
console.log("Error in saving user");
throw err;
}
console.log(newUser.username + ' Registration succesful');
return done(null, newUser);
});
}
});
}));
var isValidPassword = function(user, password) {
return bcrypt.compareSync(password, user.password);
}
var createHash = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(10), null);
}
};
Auth.js
var express = require('express');
var router = express.Router();
module.exports = function(passport) {
router.get('/success', function(req, res) {
res.send({state: 'success', user: req.user ? req.user : null});
});
router.get('/failure', function(req, res) {
res.send({state: 'failure', user: null, message: 'Invalid Username or Password'});
});
router.post('/login', passport.authenticate('login', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure'
}));
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure'
}));
router.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
return router;
};
Server.js
var express = require('express');
var path = require('path');
var app = express();
var server = require('http').Server(app);
var logger = require('morgan');
var passport = require('passport');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var mongoose = require('mongoose');
var MongoStore = require('connect-mongo')(session);
mongoose.connect("mongodb://localhost:27017/scriptknackData");
require('./models/model');
var api = require('./routes/api');
var auth = require('./routes/auth')(passport);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
app.use(session({
secret: 'super secret key',
resave: true,
cookie: { maxAge: 60000 },
saveUninitialized: true,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
var initpassport = require('./passport-init');
initpassport(passport);
app.use('/api', api);
app.use('/auth', auth);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
var port = process.env.PORT || 3000;
server.listen(port, function() {
console.log("connected");
});
As per express-session documentation
cookie.maxAge
Specifies the number (in milliseconds) to use when calculating the Expires Set-Cookie attribute. This is done by taking the current server time and adding maxAge milliseconds to the value to calculate an Expires datetime. By default, no maximum age is set.
And use express.session() before passport.session() to ensure login session is stored in correct order. passport docs
In your case you have specified maxAge as 60000ms (60sec) only. Try this:
...
app.use(session({
secret: 'super secret key',
resave: true,
cookie: { maxAge: 8*60*60*1000 }, // 8 hours
saveUninitialized: true,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
app.use(passport.initialize());
app.use(passport.session());
...
Increase your cookie maxAge value according to your need, it will solve your issue.
I was facing the same issue as you and I got the problem fixed by doing this:
If anyone is having issues, this could probably help to solve it.
app.use(session({
secret: "our-passport-local-strategy-app",
resave: true,
saveUninitialized: true,
cookie: {
maxAge: 24 * 60 * 60 * 1000
},
store: new MongoStore({
mongooseConnection: mongoose.connection,
ttl: 24 * 60 * 60 // Keeps session open for 1 day
})
}));
I had this problem and I found out how to fix it. In my case, this problem was just during using localhost during running react app on own port. I use the build production version, there was no problem. But it is not good to run build every time you need to see changes.
First I run Nodejs on 5000 port at localhost.
In React's package.json, I added "proxy": "http://localhost:5000/". After that, I ran react app on port 3000. Now when I use fetch, the URL to my API is not http://localhost:5000/api/login but just /api/login.
You can read more about that here:
https://create-react-app.dev/docs/proxying-api-requests-in-development/
Do not forget to remove the proxy from package.json when you will deploy to the server. This is good only for the development version.
As per the fine manual (emphasis mine):
Note that enabling session support is entirely optional, though it is recommended for most applications. If enabled, be sure to use express.session() before passport.session() to ensure that the login session is restored in the correct order.
In your case, the order is not correct. Try this:
...
app.use(session({
secret: 'super secret key',
resave: true,
cookie: { maxAge: 60000 },
saveUninitialized: true,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
app.use(passport.initialize());
app.use(passport.session());
...
I'm encountering a little problem when using passport.js with express 4.11.1
Below is my app.js
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
function(username, password, done) {
if(username == '1' && password == '1') {
var user = {username: 'test',id: 123,firstName: 'test'};
return done(null, user);
} else {
return done(null, false, {message: 'Incorrect username or password'});
}
}
));
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(username, done) {
var user = {
username: 'test',
id: 123,
firstName: 'test'
};
done(null, user);
});
module.exports = passport;
Then I modified my app.js, adding the middleware
var passport = require('./auth');
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: { secure: true }
}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
At last, I defined in the router:
var passport = require('../auth');
router.get('/login', function (req, res, next) {
res.render('login', {title: 'Login', message: ''});
});
router.post('/login',
passport.authenticate('local',
{
successRedirect: '/user2',
failureRedirect: '/login'
}));
router.get('/user2', function(req, res) {
console.log(req.session.passport);
if(req.session.passport.user === undefined) {
res.redirect('/login');
} else {
res.render('user2', {title: 'Welcome!', user: req.user});
}
});
Now the problem that I found is that I can successfully login, however when I try to print out req.session.passport, I found the passport object in session is {}. I guess maybe it's because the passport.serializeUser function doesn't really work, but when I try printing out the user object passed to the passport.serializeUser function, it has values. Can someone help me look into this issue? Thanks in advance.
Your code looks fine, except this part:
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: { secure: true } <<<<<<<<<<
}));
docs say that you should use secure cookies when you are using https, so excluding this field should fix your problem.
secure boolean marks the cookie to be used with HTTPS only.