Transitioning from Mongoose-Auth to Passport for Authentication in Node.js
Up until about a week ago, I was using Mongoose-Auth, when I decided my app needed some cleaning up. For most simple Node.js apps, it makes sense to route everything through your app.js (or server.js, depending on your preference/framework) file. But once your app starts to get a bit more developed, it makes more sense to break some of the code out into separate files, not only to make it easier to read, but also to make it easier to debug.
In the process of trying to separate my code out, I started having issues with Mongoose-Auth. In particular, I had a really difficult time maintaining authorization (cookies) for a specific user from one page to another, and it wasn’t exactly clear how to pass authentication between files. So I decided to follow my friend’s advice and looked into Passport.
The beauty of Passport is that it’s a LOT easier to implement. It’s simple, and the documentation isn’t terrible. A bit of fair warning, however: if you’re relatively new to Node.js/JavaScript, then the documentation (which makes sense to those who are Node/JS ninjas) can be a bit confusing. So I recommend using the Passport Guide in conjunction with some solid examples, like this Locomotive-Passport Boilerplate and this login example.
But transitioning from Mongoose-Auth to Passport was a bit of a challenge. (Especially since I wanted to keep all the user data, passwords and all, intact in my MongoDB.)
Getting rid of all the Mongoose-Auth stuff was easy; just delete it all. And putting all the Passport stuff was also pretty easy; just follow the Passport Guide’s Configuration steps.
I did have to make a few modifications, though (thank goodness for MongooseJS!):
- Include the bcrypt module to salvage the hash/salt parameters in the user database, and create a virtual for the UserSchema to take the hash/salt information and transform it to/from a password.
- Create a verifyPassword method, to accommodate the bcrypt functionality.
- Define an authenticate static to handle the user authentication process for checking the user’s input information with what I’ve got in the database.
Perhaps the biggest issue I had, however, was in getting the app to recognize the session cookie generated by the user authentication. I was able to get to the login page, submit my login credentials, and verify that I existed in the database – but then I’d get rerouted to the login page, with the claim that I wasn’t authenticated.
It turns out that the express configuration has to be in a rather specific order. (No one informed me of this – so hopefully it’ll help someone else!) Specifically, the express.session variable needs to be configured before any of the passport variables are configured:
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(require('stylus').middleware({ src: __dirname + '/public' }));
app.use(express.session({ secret: 'applecake' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
Once that was done, however, I was free and clear! You can see all my code for CrowdNotes on GitHub. (Specifically, check out modules/user.js, accessDB.js, and app.js.)
Next stop: a more beautiful MVC layout for the app
Nice series of posts. The thought process is well presented. Will follow as you progress. Have added this post to a compilation of very useful Node.js articles and code at Node.js on Scoop.it
[...] rockbot develops the web Skip to content HomeAbout RaquelSmart Latinas at escuchame.org ← Transitioning from Mongoose-Auth to Passport for Authentication in Node.js [...]
thanks for the post, very helpful! … i looked at crowdnotes and noticed you were having an issue calling bcrypt asynchronously. i’m guessing the hash and salt are coming back null?
the code in User.js is ok, the problem is implementation … your setting the password property syncly when it should be set asyncly for the hash and salt to be valid before your app runtime continues.
for this reason, i decided it was cleaner to abstract away password in my project. here’s my password class if your interested:
https://gist.github.com/2943281
HTH!
Just came across this after searching for “bcrypt passport.js” – Thanks a bunch. Really helpful stuff. Using your user schema as a starting point.