User Accounts Using Sequelize and Passport in Node.js

by Hamilton Chapman


Setting up user accounts and authentication in Rails is incredibly easy. For most of what I've needed in the past I have been able to use a Ruby gem called Devise. If you've ever used Rails then this will almost certainly be familiar to you. It is ridiculously easy to setup. Even then, if you find yourself craving some customisation, the chances are that somebody will have already wanted to do exactly the same thing and you'll therefore be able to scoop some ideas or some code from StackOverflow.

The latest app I've been working on at Pusher has involved using Node.js, which before about 2 or 3 weeks ago, I'd never really looked into. It's been a great opportunity to learn something new, but as you'd expect, it's not all been plain sailing.

The app required that I use sqlite3 as the database (due to it being pre-installed on all Macs). As you'll know if you've ever used databases in a Node app, pretty much all of the examples you find involve using MongoDB and Mongoose. This is of course completely reasonable, but of not much use to me.

I discovered Sequelize and thought that it looked like it would prove helpful in interacting with my sqlite database through Node. Getting it setup in the first place took a little fiddling but eventually (with some help from some people in the office) I had it setup and I was able to save to and retrieve data from my sqlite database.

var Sequelize = require('sequelize');

var sequelize = new Sequelize("_databaseName_", "_username_", "_password_", {
  dialect: 'sqlite',
  storage: "/path/to/database.sqlite"
});

var User = sequelize.define('User', 
{
  username: DataTypes.STRING,
  password: DataTypes.STRING
})

User.sync();

var user = User.create({ username: "admin", password: "bolognese" });

That's all that's needed to setup the basic connection with the database, create a User model, then save an instance of a User, and then log out the user's password (probably not the best idea to save your passwords like this - take a look at crypto).

So the first part of user accounts and authentication is in place. We can now create a model and persist data. Node's answer to Devise is called Passport.js. It essentially allows you to do the same basic things as Devise that most people will want to be doing with user accounts. The only significant difference I've found is that the documentation isn't as easy to follow and the amount of questions you can find about it online is fewer than the number for Devise. To be expected though.

Integrating Sequelize with Passport is fairly simple when you've figured out how Passport works on a basic level.

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;

// Serialize sessions
passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  db.User.find({where: {id: id}}).success(function(user){
    done(null, user);
  }).error(function(err){
    done(err, null);
  });
});

// Use local strategy to create user account
passport.use(new LocalStrategy(
  function(username, password, done) {
    User.find({ where: { username: username }}).success(function(user) {
      if (!user) {
        done(null, false, { message: 'Unknown user' });
      } else if (password != user.password) {
        done(null, false, { message: 'Invalid password'});
      } else {
        done(null, user);
      }
    }).error(function(err){
      done(err);
    });
  }
));

The serializeUser and deserializeUser functions need to be there for Passport to be able to use sessions so that authentication works nicely in your app.

The passport.use(new LocalStrategy... block is there to define how you want your authentication to work. For example it's in this block of code where you can decide what you want the messages to be if an invalid username or password is provided.

Having got all of that setup and working together it's then easy to start hashing your passwords when you store them. Passport also allows you to easily implement other "strategies" in much the same way that you can use omniauth in conjunction with Devise.

All in all, Passport is a great module for use in Express apps and if you need to use sqlite then rest easy in the knowledge that you can use Sequelize together with Passport.