Node.js: User Authentication with Passport Local Strategy (2024)

Node.js: User Authentication with Passport Local Strategy (2)

User authentication is indispensable to most of today’s web applications. Handling user registration and sign-in is an important feature, which can sometimes present a development overhead. Interestingly, Node and Express do not have any built-in module for authentication, that’s why Passport comes in to rescue.

To begin with, Passport is a authentication middleware for authenticating requests, it has a lot of neat features and authentication mechanisms (they called them strategies) out of the box, such as the local traditional username/password authentication, and other OAuth providers like Facebook and Twitter as a authentication method. Today we are only focusing on the traditional authentication by username/password with Passport in Node web application.

To install Passport, make sure you have Passport as a dependency in your application package.json (normally in your application root directory), then run the following command in your terminal:

$ npm install

If it doesn’t work, you probably need to run it as a administrator by putting “sudo” right before npm (which stands for node package manager for those are not familiar with). If all work out fine, you should see passport in your node_modues folder.

To initialize Passport, you put following code snippet into your web config file. If your application uses persistent login sessions (which normally do), the passport.session() middleware is also needed.

var passport = require('passport');
...
app.configure(function() {
...
app.use(express.session({ secret: 'your secret key' }));
// Make sure this comes after the express session
app.use(passport.initialize());
app.use(passport.session());
...});

In the above code snippet, you did two things. First, you required the Passport module. Second, you registered two middlewares: the passport.initialize() middleware, which is responsible for bootstrapping the Passport module and the passport.session() middleware, which is using the Express session to keep track of your user’s session.

Next up you need to install Passport’s local strategy module. To do that, include passport-local in your package.json and install it from the terminal, just like you install Passport in the first place. But first thing first, we need to define how Passport handle user serialization/deserialization during authentication. Assume you have a user model defined (with Mongoose) as User:

passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findOne({
_id: id
}, '-password -salt', function(err, user) {
done(err, user);
});
});

The basic idea about serialization and deserialization is, when a user is authenticated, Passport will save the user’s _id property to the session as req.session.passport.user. Later on when the user object is needed, Passport will use the _id property to grab the user object from the database. The reason why we don’t save the entire user object in session are: 1. Reduce the size of the session; 2. It’s much safer to not save all the user information in the session in case of misuse. Pretty neat right? Notice when we query the database to retrieve the user object by its _id, we used the field options argument (the dash) to tell Mongoose to skip the password and salt fields, which is also a good security practice.

Now it’s the time to configure our Passport local strategy:

var passport = require('passport');// This is how you initialize the local strategy module
var LocalStrategy = require('passport-local').Strategy;
...
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({
username: username
}, function(err, user) {
// This is how you handle error
if (err) return done(err);
// When user is not found
if (!user) return done(null, false);
// When password is not correct
if (!user.authenticate(password)) return done(null, false);
// When all things are good, we return the user
return done(null, user);
});
}));

Then you need to modify the User model in order to support Passport’s authentication, in your User model you need to include:

var mongoose = require('mongoose'),
crypto = require('crypto'),
Schema = mongoose.Schema;
var UserSchema = new Schema({
... // This is where you need to define all the fields
});
...UserSchema.pre('save', function(next) { if (this.password) {
this.salt = new Buffer(
crypto.randomBytes(16).toString('base64'),
'base64'
);
this.password = crypto.pbkdf2Sync(
password, this.salt, 10000, 64).toString('base64');
);
};
next();});...

This looks daunting at first glance, let’s break it down a little bit. Basically the idea is, whenever before we save the user back to the database, we generate a new salt using Node’s built-in module crypto. To know more about crypto, take a look at its documentation. Then we encrypt the password via crypto’s pbkdf2Sync function as a 64-bit string. This is a good practice because you don’t want to just save the exact password as a string, which is vulnerable.

Side note: PBKDF2 stands for Password-Based Key Derivation Function II, there’s a interesting article in Wikipedia that explains how it works.

So there you have it, with the Passport strategy done, the next step would be wiring your views (such as sign up/sign in form) with proper routing, as well as displaying flash error messages with Connect-Flash module. I will write another post about how this module works later, but for now you should have an basic idea of how to implement Passport with its local strategy. Just in case you are curious about how the Passport authentication process workflow works, there is a pretty neat article explaining how the data actually flows during the authentication process, worth to take a look.

This tutorial covers the basic idea of how Passport local strategy work, I will write another tutorial about OAuth strategies (Facebook, Twitter etc) in the near future. Stay tuned and happy coding. :)

Node.js: User Authentication with Passport Local Strategy (2024)
Top Articles
Latest Posts
Article information

Author: Stevie Stamm

Last Updated:

Views: 5559

Rating: 5 / 5 (80 voted)

Reviews: 87% of readers found this page helpful

Author information

Name: Stevie Stamm

Birthday: 1996-06-22

Address: Apt. 419 4200 Sipes Estate, East Delmerview, WY 05617

Phone: +342332224300

Job: Future Advertising Analyst

Hobby: Leather crafting, Puzzles, Leather crafting, scrapbook, Urban exploration, Cabaret, Skateboarding

Introduction: My name is Stevie Stamm, I am a colorful, sparkling, splendid, vast, open, hilarious, tender person who loves writing and wants to share my knowledge and understanding with you.