Nodejs Express3 using sessions to check if user is logged in
Solution 1
Maybe I'm understanding your question wrong, but the only thing you are missing is a route, where you authenticate the user, e.g.:
app.post('/login', function(req, res){
if(req.body.user == 'Ryan' && req.body.password == 'Dahl'){
req.session.user = aUserIdOrUserObject;
res.send(200) // or redirect
}
};
This is hust pseudo code. You obviously want to check if user and password match against your database.
The second point you are missing is a permanent session store like https://github.com/masylum/connect-mongodb or https://github.com/CarnegieLearning/connect-mysql-session. The memory store is only usefull for development, in production this could kill your server.
Solution 2
What I do in the app I work, and in order to not have to do this validation in every controller action, is:
//userValidation.js
module.exports = function(req, res, next){
if(req.body.user == 'Ryan' && req.body.password == 'Dahl'){
next();
}else res.send("Not auth");
}
//controller.js
var validate = require("./userValidation");
app.post("/route", validate, function(req, res){
//if execution get to this point you are sure that user is authenticated.
});
This code is also from the App I work, this is how we set the session to work. For dev purposes you can replace MongoStore
with a MemoryStore
.
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(connect.compress());
app.use(express.static(__dirname + "/public", { maxAge: 6000000 }));
app.use(express.favicon(__dirname + "/public/img/favicon.ico", { maxAge: 6000000 }));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({
secret: config.sessionSecret,
maxAge: new Date(Date.now() + (1000 * 60 * 15)),
store: new MongoStore({ url: config.database.connectionString })
}));
app.use(function(req, res, next){
console.log("\n~~~~~~~~~~~~~~~~~~~~~~~{ REQUEST }~~~~~~~~~~~~~~~~~~~~~~~".cyan);
res.locals.config = config;
res.locals.session = req.session;
res.locals.utils = viewUtils;
next();
});
app.use(app.router);
app.use(function(req, res, next){
res.status(404).send("Resource not found");
});
});
In order to set the user in the session we have this:
var User = require("../utils/modelRegistrar").user; //any way to get the User model
var userRepository = require("../domain/repositories/usuarioRepository");
var hash = require("../utils/hash");
module.exports.init = function(app, io){
app.publicPost("/login", login);
app.put("/exit", exit);
};
function login(req, res){
var dadosDeLogin = req.body.dadosDeLogin;
userRepository.autenticar(dadosDeLogin.login, /*hash.md5(*/dadosDeLogin.senha/*)*/, function(err, user){
if(err) req.next(err);
if(user){
user.lastAcess = new Date();
user.access++;
userRepository.update(user, ["lastAcess", "acess"], function(err){
if(err) req.next(err);
else{
req.session.logedUser = user;
res.redirect("/home");
}
});
}
else res.redirect("/#user-not-found");
});
};
function exit(req, res){
if(req.session.logedUser) delete req.session.logedUser;
res.redirect("/");
}
May some part of the code is still in portuguese
germainelol
Updated on June 04, 2022Comments
-
germainelol almost 2 years
I have the following
app.js
codeapp.configure(function(){ app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.enable('jsonp callback'); app.set('view engine', 'jade'); app.set('view options', {layout : false}); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.cookieParser()); app.use(express.session({ secret : 'abcdefg' })); app.use(app.router); app.use(express.static(__dirname + '/public')); app.use(function(req, res, next){ res.locals.user = req.session.user; next(); }) });
I'm trying to make it so that the following code on my
.jade
view will work- if(session.user) div#logoutsection.pull-right a#logout-btn.btn.btn-info.pull-right.top-bar-form-button(href='logout/') Logout p#loginprompt.pull-right.login-prompt #{session.user.username} logged In - else ul.pull-right li a#signup-btn.btn.pull-right.top-bar-form-button(href='#signup-modal', data-toggle="modal") Sign Up
So if they are not signed in, provide the option to sign up, and if they are signed in, tell them they are 'logged in'. I added in the function at the end of the
app.configure
code as before it was usingdynamicHelpers()
I was told thatcookieParser()
was the way to go, but how would I code this in so that I could check whether my user was logged in and provide their username as I am trying to above?Any help appreciated.
Thanks!
EDIT: index.js
'use strict' var util = require('util'); var Logger = require('devnull'); var logger = new Logger({namespacing : 0}); var User = require('../schemas/User'); var Post = require('../schemas/Post'); /** * Get Meta information about all the Post's */ var getAllMeta = function(req, res, next){ Post.getAllMeta(function(err, postsList){ if(!err && postsList){ req.postsList = postsList; } next(err); }); }; /** * validate the signup credentials entered by the user * @param {String} username * @param {String} pass1 : first password * @param {String} pass2 : verification password */ var validateUserData = function(username, pass1, pass2){ if(pass1.trim() !== pass2.trim()){ util.log('Passwords not Matching ' + pass1 + ' ' + pass2); return 'Passwords not Matching'; } return ''; //put any other validations here }; /* * GET home page. */ module.exports = function(app){ /** * Map the URL '/' to the callback */ app.get('/', function(req, res){ logger.log('Serving request for url [GET]' + req.route.path) Post.getAll(function(err, allPosts){ if(!err && allPosts){ res.render('index', {'allPosts' : allPosts}); }else{ util.log('Error fetching posts from database : ' + err); res.render('error'); } }); }); /** * Map the URL '/login' to the callback */ app.post('/login', function(req, res){ logger.log('Serving request for url [POST] ' + req.route.path); var username = req.body.User; var password = req.body.Password; User.validateUser(username, password, function(err, user){ if(err && !user){ res.json({ retStatus : 'failure' }); }else{ console.log(user); req.session.user = user; res.json({ retStatus : 'success', user : user , }); } }); }); /** * Logout the current user and clear the session */ app.get('/logout', function(req, res){ logger.log('Serving request for url [GET] ' + req.route.path); req.session.user = undefined; res.redirect('/'); }); /** * Add a new User to database */ app.post('/signup', function(req, res){ util.log('Serving request for url [POST] ' + req.route.path); var signupForm = req.body.signupForm; var username = signupForm.username; var pass1 = signupForm.pass1; var pass2 = signupForm.pass2; var validateMsg = validateUserData(username, pass1, pass2); if(validateMsg !== ''){ res.json({ 'retStatus' : 'failure', 'message' : validateMsg }); }else{ var newUser = new User(); newUser.username = username; newUser.password = pass1; newUser.save(function(err, savedUser){ var message = ''; var retStatus = ''; if(!err){ util.log('Successfully created new user with Username : ' + username); message = 'Successfully created new user : ' + username; retStatus = 'success'; req.session.user = savedUser; }else{ util.log('Error while creating user : ' + username + ' error : ' + util.inspect(err)); if(err.code === 11000){ message = "User already exists"; } retStatus = 'failure'; } res.json({ 'retStatus' : retStatus, 'message' : message }); }); } }); app.get('/admin', getAllMeta, function(req, res){ util.log('Serving request for url [GET] ' + req.route.path); if(req.session.user){ res.render('post', {'postsList' : req.postsList}); }else{ res.redirect('/'); } }); /** * Save the post to database */ app.post('/admin/save/post', function(req, res){ var postContent = req.body.postContent; if(postContent.postKey === '' || postContent.postKey === undefined){ var post = new Post(); post.subject = postContent.postSubject; post.content = postContent.postContent; post.author = req.session.user.username; post.tags = postContent.postTags; post.save(function(err, response){ if(!err && response){ util.log('Successfully saved Post with id : ' + response.id); res.json({ 'retStatus' : 'success', 'data' : response }) }else{ util.log('Error saving the Post : ' + err); res.json({ 'retStatus' : 'failure', 'error' : err }); } }); }else{ var conditions = {'key' : postContent.postKey}; var update = { 'subject' : postContent.postSubject, 'content' : postContent.postContent, 'tags' : postContent.postTags }; Post.update(conditions, update, null, function(err, numAffected){ if(!err && numAffected){ util.log('Successfully updated the Post with id : ' + postContent.postKey); res.json({ 'retStatus' : 'success', 'numAffected' : numAffected }); }else{ util.log('Error updating the Post with id : ' + postContent.postKey + ' ' + err); res.json({ 'retStatus' : 'failure' }); } }); } }); app.get('/post/show/:key', function(req, res){ Post.findByKey(req.params.key, function(err, postData){ if(!err && postData){ postData = postData[0]; res.json({ 'retStatus' : 'success', 'postData' : postData }); }else{ util.log('Error in fetching Post by key : ' + req.params.key); res.json({ 'retStatuts' : 'failure', 'msg' : 'Error in fetching Post by key ' + req.params.key }); } }); }); app.post('/admin/save/', function(req, res){ //container for saving a post }); app.get('/admin/remove/:key', function(req, res){ //container for deleting a post }); app.get('/contact', function(req, res){ util.log('Serving request for url[GET] ' + req.route.path); res.render('contact'); }); };
User.js
'use strict' var util = require('util'); var bcrypt = require('bcrypt'); var mongoose = require('mongoose'); var Schema = mongoose.Schema; var validatePresenceOf = function(value){ return value && value.length; }; var toLower = function(string){ return string.toLowerCase(); }; var User = new Schema({ 'username' : { type : String, validate : [validatePresenceOf, 'a Username is required'], set : toLower, index : { unique : true } }, 'password' : String, }); User.statics.findUser = function(username, password, cb){ return this.find({'username' : username}, cb); }; User.statics.validateUser = function(username, password, cb){ this.find({'username' : username}, function(err, response){ var user = response[0]; if(!user || response.length === 0){ cb(new Error('AuthFailed : Username does not exist')); }else{ if(password == user.password){ util.log('Authenticated User ' + username); cb(null, user); }else{ cb(new Error('AuthFailed : Invalid Password')); } } }); }; module.exports = mongoose.model('User' , User);
-
loganfsmyth over 11 yearsYou are setting
user
as the template variable, but trying to access it assession.user
. Maybe try justif(user)
? -
germainelol over 11 years@loganfsmyth This gives me the same response as using
session.user
which isuser is not defined
-
-
germainelol over 11 yearsNot sure I follow sorry, I'm kind of new to learning nodejs and all of its features. I'm connecting to my mongodb database like so:
mongoose.connect('mongodb://localhost/testdb');
But I'm not sure how to check against the database, or what to put where you have putaUserIdOrUserObject
. Assuming all of this eventually works, how would you recommend checking this in the view? I read the links but they look like the matrix to me in some cases! -
topek over 11 yearsI think your view code is fine. It's the login logig you are missing. If you are just trying to start you could use passportjs.org or another authentication package nodetoolbox.com/categories/Authentication . This should get you started easily. Another link that might help: stackoverflow.com/questions/3498005/…
-
germainelol over 11 yearsI keep reading about passport indeed. But my problem is taking the passport logic and applying it to my program which I have taken from here by the way and started editing
https://github.com/ric03uec/nodeblox/tree/tutorial_5
I seem lost. -
topek over 11 yearsI think the only problem you are facing is that you are trying to achieve too much in one step. Maybe you should step back and just start with some basic login form (user, password), send it to a route like in my answer, check it against some predefined variables and set a session.user, if the credentials are correct. At this step you have a logged in user and can play around in the view. Later you can come back to your login logik and refine it. It's better to have something working now, than get stuck in other libraries code and give up.
-
germainelol over 11 yearsI thought the login logic was quite simple, if a user is logged in => print their username instead of login form. If not logged in => show login form. But my problem is simply what code to put in app.js in order for my view to know if I am logged in or not, I've searched everywhere and no help is really found, only examples where no one says where exactly to put the code :/
-
topek over 11 yearsYou do not need much more code than on this screen. With the post to the /login route you set a session variable. This session variable can be used on successive request to switch between logged in and logged out users in the view. The only part missing is a route where you display your view. `app.get('/, function(req, res){res.render('index', {user: req.local.user}) and in your view you can use the user variable.
-
germainelol over 11 yearsI have updated the original code with the /login post from
index.js
which is validating the user correctly? So the post is successfully set to the user withreq.session.user = user
. But theapp.get
part you posted. Where should I be putting this? -
germainelol over 11 years` app.get('/', function(req, res){ res.render('index', { user: req.local.user }) });` I have made sure this is on the index.js page, but this gives error
cannot read property user of undefined
Where or how should I be defining this? Sorry to pester you. -
topek over 11 yearsthis should be done in your middleware. Put a console log in your middleware and make sure it gets run.
-
germainelol over 11 years
http.createServer(app).listen(app.get('port'), function(){ console.log("Express server listening on port " + app.get('port')); app.get('/', function(req, res){ res.render('index', {user: req.local.user}) }); });
I should add it here? By middleware I understand this is where I'm making a connection of some sort to the server so I assume you mean here, where user is still not defined. I will try other places but I don't follow. -
topek over 11 yearsmiddleware is where you set
res.locals.user = req.session.user;
-
germainelol over 11 years
app.use(function(req, res, next){ res.locals.user = req.session.user; next(); }) app.get('/', function(req, res){ res.render('index', {user: req.local.user}) });
Yep I now have this, but I still get the same error that I have not defineduser
:/ All your help is appreciated also I would like to add... -
topek over 11 yearsput a
console.log("this should be called");
beforeres.locals.user
and watch your console, if the function is really called. -
germainelol over 11 yearsNo I just see
Express server listening on port 3000
and if I try to go to localhost:3000 I get the same errors again. -
germainelol over 11 yearsNot sure what to change after playing around with where to put different things
-
topek over 11 yearsCould you try to put that middleware before app.use(express.router). I'm not quite sure on this, but I think that I had once a similar problem.
-
germainelol over 11 yearsHi, I have tried putting
app.use(app.router);
both at the end ofapp.configure
and just after thethis should be called
function both giving the same error and not printing to the cmd window -
germainelol over 11 yearsThanks for reply, I have added the code I have for
User.js
under Schemas. This should work by itself? If you see the comments with the previous answer to the question, I am also trying to get the session working through his methods to no success yet -
germainelol over 11 yearsWhere/how are you defining
config.sessionSecret
,config
,memoryStore
andviewUtils
? -
Renato Gama over 11 yearsThat values are not relevant, you can ignore them. They are not useful in the session configuration (except for the MemoryStore and MongoStore). Config is an object with project specific configuration, memoryStore is the default way of saving session objects to memory (not useful for production)
-
germainelol over 11 yearsYep I don't follow with MemoryStore sorry. I'm only trying to get my code to work to pass the user's username to the view when they are logged in. At the moment I can't even get the app to run because of errors I don't understand how to fix sorry.
-
germainelol over 11 years
app.get('/', function(req, res){ res.render('index', {user: req.local.user}) });
It is thisuser:
that is not defined according to the errors -
germainelol over 11 yearsI am getting an error of
user
not being defined here which occurs when I run the program, however I also have a console.log function which does not print in the console as you see in the comments in the other question. ` app.get('/', function(req, res){ res.render('index', {user: req.local.user}) });` -
germainelol over 11 yearsI only have the problem of it not recognising session.user, I have an index.js, login.js and User.js in order to validate the user's login details, but where should I be setting the session once they are logged in so that the view can print their username? I have added index.js to the OP
-
Renato Gama over 11 yearsTake a look at my new edit. Not sure if is it what youre looking for. Hope it helps!