This is definitely the right way. I would say that it is perfect for your needs. I personally like how using the field of your database directly reflects the business logic.
Alternatives, although I'm a fan of your solution, might be:
one
Adding the lastLogin date field to the default database is NULL . This will keep a date and time stamp whenever a user logs in. You can use it as an implicit check if the user has ever registered before. I personally prefer to have explicit columns for my purposes (for example, you make your firstLogin column), because the purpose of the column and the business logic of the application is very clear.
2
Another alternative could be saving when the user last updated his password, i.e. lastPasswordChange by default for NULL for new users. The same reasoning as above. It may be useful if you want your users to change their passwords every n days.
Security saying, I would say that would be hard. As long as your default firstLogin field is 1 , there would be no way a new user could skip changing the password when they first logged in.
However, when the user updates his password, be sure to update the firstLogin field in the same request or execute both requests inside the transaction. This way you will always be sure that the password and firstLogin fields have firstLogin . If for any reason the request fails, you will have a user who has already changed his password, and he will be asked / forced to change it again, or a user who has a randomly generated password without requesting to change it. Running this request in one request will ensure that both of them will be updated at the same time. Executing inside a transaction leaves you with the ability to refuse / roll back the transaction if the request fails.
On the other hand, your code can be written like this (and your path, and rightly so, is just a matter of preference and visual):
/* POST login page. */ router.post('/login', function(req, res, next) { passport.authenticate('local', { successRedirect: '/dashboard/users', failureRedirect: 'pages/login' }, function(err, user, info) { if(err) { console.log('') return res.render('pages/login', {title: 'Login', error: err.message}); } if(!user) { return res.render('pages/login', {title: 'Login', error: info.message}); } return req.logIn(user, function(err) { if(err) { return res.render('pages/login', {title: 'Login', error: err.message}); } // Using if/else if/else makes no difference since if the first if is executed // in both cases nothing else will execute due to if/else or the return. // In case the above statement resolves to `false` the effect wills till be the same if (user.firstLogin) { return res.redirect('/change-password'); // <- First login } // The else is not necessary due to the return in the line above. return res.redirect('/dashboard/users'); }); })(req, res, next); });
If you want a more specific answer to any question, I need a more specific question.