David
David

Reputation: 560

Safe authentication with node.js and session.socket.io?

I'm using the latest versions of node.js and session.socket.io and this is how I set the session (please note that I'm not using a HTTPS connection so no secure: true):

app.configure(function() {
    app.use(cookieParser);
    app.use(express.session({
        signed: true,
        store: sessionStore,
        secret: 'SECRET',
        cookie: {
            maxAge: 24 * 60 * 60 * 1000,
            httpOnly: true
        }
    }));
});
var sessionSockets = new SessionSockets(io, sessionStore, cookieParser);

// Later
sessionSockets.on('connection', function(error, socket, session) {
    // session could be used here to detect if user is logged in

    // e.g. login: session.name = 'x'; session.save();
    // e.g. checkIfLoggedIn: if (session.name) return true;
});

Is my code safe/correct or how I could authenticate that a user is really logged in? Is it possible/recommended to change the sid of the cookie on the clients (due it's mentioned here)?

Upvotes: 9

Views: 23199

Answers (3)

José F. Romaniello
José F. Romaniello

Reputation: 14156

I know this is bit old, but for future readers in addition to the approach described by @kentcdodds of parsing cookie and retrieving the session from the storage (eg. my own passport.socketio module) you might also consider a token based approach.

In this example I use JSON Web Tokens which are pretty standard. You have to give to the client page the token, in this example imagine an authentication endpoint that returns JWT:

var jwt = require('jsonwebtoken');
// other requires

app.post('/login', function (req, res) {

  // TODO: validate the actual user user
  var profile = {
    first_name: 'John',
    last_name: 'Doe',
    email: '[email protected]',
    id: 123
  };

  // we are sending the profile in the token
  var token = jwt.sign(profile, jwtSecret, { expiresInMinutes: 60*5 });

  res.json({token: token});
});

Now, your socket.io server can be configured as follows:

var socketioJwt = require('socketio-jwt');

var sio = socketIo.listen(server);

sio.set('authorization', socketioJwt.authorize({
  secret: jwtSecret,
  handshake: true
}));

sio.sockets
  .on('connection', function (socket) {
     console.log(socket.handshake.decoded_token.email, 'has joined');
     //socket.on('event');
  });

The socket.io-jwt middleware expects the token in a query string, so from the client you only have to attach it when connecting:

var socket = io.connect('', {
  query: 'token=' + token
});

I wrote a more detailed explanation about this method and cookies here.

Upvotes: 27

Prabin Tp
Prabin Tp

Reputation: 766

User Authentication and session Storage Using Passport

var express = require('express'),
routes = require('./routes'),
api = require('./routes/api'),
http = require('http'),
path = require('path'),
mysql = require('mysql'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;

//MySQL

var sqlInfo = {
    host: 'localhost', 
    user: 'root',
    password: '', 
    database: 'dbname'
}


global.client = mysql.createConnection(sqlInfo);

client.connect();




var app = module.exports = express();




/**
 * Configuration
 */

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(path.join(__dirname, 'public')));

app.use(express.cookieParser("secret"));
app.use(express.session({
    secret: 'keyboard cat'
}));
app.use(passport.initialize());
app.use(passport.session());

app.use(app.router);




passport.use(new LocalStrategy(

    function(username, password, done) {

        return check_auth_user(username,password,done);

    }

    ));


// development only
if (app.get('env') === 'development') {
    app.use(express.errorHandler());
}

// production only
if (app.get('env') === 'production') {
// TODO
}



/**
 * routes start---------------------------------------------------------------
 */
// home page contain login form 
app.get('/home', function(reg, res){
    //check user session value, is logged in 
    if(req.user)
        res.render('dash',{
            username: req.user['member_id']//req.user array contains serializeUser data
        });
    else
        res.render('index');

});

app.get('/logout', function(req, res){

    req.logout();
    res.redirect('/home');
});

//login form submit as post

app.post('/login',
    passport.authenticate('local', {
        successRedirect: '/dashboard',
        failureRedirect: '/home'
    })
    );
//to project dashboard
app.get('/dash',routes.dash);
//to project dashboard
app.get('/signup',routes.signup);
//to project dashboard

app.get('*', routes.index);

/**
 * routes end---------------------------------------------------------------------
 */


/**
 * Start Server
 */

http.createServer(app).listen(app.get('port'), function () {
    console.log('Express server listening on port ' + app.get('port'));
});

Click for more details with example!.

Upvotes: -3

kentcdodds
kentcdodds

Reputation: 29021

I would recommend avoiding re-inventing the wheel and using a library such as PassportJS. There is a module specifically for using PassportJS with Socket.io here (I've never used this though I'm currently working on a project where I'll need it soon). I have used PassportJS and it's quite simple. I would recommend this.

Upvotes: 15

Related Questions