Search code examples
javascriptphpnode.jsexpressexpress-session

How to implement login system in node.js and expressJs


I am developing an app in node.js and using expressJs, but I am a PHP developer, I know that in PHP we can use session to implement login and I thought in node.js case is the same, so as I searched I found the express-session module, and I tried to implement this way. This app.js file

var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
app.set('port', process.env.PORT || 3000);
app.set('view engine', 'ejs');
app.set('views', 'app/views');
app.use(require('./routes/login_api'));
app.use(require('./routes/login'));
app.use(require('./routes/Index_api'));
app.use(require('./routes/index'));

var server = app.listen(app.get('port'), () => {
  console.log('Server is listening on ' + app.get('port'));
});

So as you can see I have four different routes, /routes/login renders the login.ejs template, /routes/login_api handles the requests and response of the login page, /routes/Index_api, /routes/Index_api (which is my dashboard), is the same way. This is `login_api

var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var session = require('express-session');
var mysql = require('mysql');
var conn = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: '',
    database: 'fmis'
});
conn.connect();

router.use(bodyParser.urlencoded({
    extended: false
}));
router.use(bodyParser.json());
router.use(session({
    secret: 'secret',
    saveUninitialized: true,
    resave: true
}));
router.post('/login_api', function(req, res) {
    var Username = req.body.Username;
    var Password = req.body.Password;
    var query = "SELECT `User_Id`, `User_Username`, `User_Password`, `User_Name`, `User_Last_Name`, `User_Type`,  `User_Photo`  FROM `users` WHERE `User_Deleted` = 0 AND `User_Username`='" + Username + "' AND  `User_Password` = '" + Password + "'";

    conn.query(query, function(err, result) {
        if (err) {
            console.error(err);
            res.end();
        } else {
            if (result.length == 1) {
                req.session.Username = result[0].User_Username;
                req.session.Password = result[0].User_Password;
                req.session.UserType = result[0].User_Type;

            }
        }
        console.log(req.session.Username); // gives the right result
    });
    console.log(req.session.Username); // gives the undefined 

});

As far as I know the session.Username is a global variable (as it is in PHP) so it should be accessible in everywhere but when I access it in routes/index route it gives the undefined result, not even that if write the console.log(req.session.Username); inside query callback function it gives the right result which is returned from the database but when I place it out side query callback function it gives undefined result. So any suggesstion please help me


Solution

  • You need to understand the async and non-blocking nature of Node.js. When you call conn.query the process does not block and moves on to the next statement which is console.log (outside the callback). Most probably the callback hasn't been called yet. Callback will be called at an arbitrary time when either the result or error is available. That's why you see that "weird" behaviour. The order of execution is not necessarily the order of statements.

    A Quick Solution:

    I recommend Passport. It is popular and easy to use for handling authentication.

    You can use it as a middleware which is cleaner and get access to the current user simply by req.user which is available in the request context. It has different authentication strategies, including OAuth, and easy to work with.

    NOTE: It requires the session and cookie-parser.

    In your particular application see:

    • LocalStrategy to load user details from database;
    • de/serializeUser for reading and writing user data from session;

    Also you need to use passport.initialize() and passport.session() middlewares. See the project's page for details on how to use it.