Authentication and logins in Node can be a complicated thing. Actually logging in for any application can be a pain. This article series will deal with authenticating in your Node application using the package Passport.

For this article, we'll be focusing on setup and only local logins and registrations/signups. Since this is the first article and also deals with setting up our application, it will probably be one of the longer ones if not the longest. Sit tight for the duration of your flight.

Setting Up Our Application

To set up our base Node application, we'll need a few things. We'll set up our npm packages, node application, configuration files, models, and routes.

We are going to install all the packages needed for the entire tutorial series. This means we'll install all the packages needed for passport local, facebook, twitter, google, and the other things we need. It's all commented out so you know what each does.

I use bcrypt-nodejs instead of bcrypt since it is easier to set up in windows. For more information on the newer ExpressJS 4.0 dependencies (morgan, body-parser, cookie-parser, method-override, express-session), see this article on

ExpressJS 4.0. Now that we have all of our dependencies ready to go, let's go ahead and install them:

Free Node eBook

Build your first Node apps and learn server-side JavaScript.

📧

Thank you!

You have successfully joined the Scotchy super duper web dev awesome mailing list.

npm install With all of our packages ready to go, let's set up our application in server.js.

Let's make all our packages work together nicely. Our goal is to set up this file and try to have it bootstrap our entire application. We'd like to not go back into this file if it can be helped. This file will be the glue for our entire application.

We are going to comment out our passport configuration for now. We'll uncomment it after we create that config/passport.js file.

The path of our passport object is important to note here. We will create it at the very beginning of the file with var passport = require('passport');. Then we pass it into our config/passport.js file for it to be configured. Then we pass it to the app/routes.js file for it to be used in our routes.

Now with this file, we have our application listening on port 8080. All we have to do to start up our server is:

node server.js Then when we visit http://localhost:8080 we will see our application. (Not really right this moment since we have some more set up to do)

Auto Refreshing: By default, node doesn't automatically refresh our server every time we change files. To do that we'll use nodemon. Just install with: npm install -g nodemon and use with: nodemon server.js.

Now this won't do much for our application since we don't have our database configuration, routes, user model, or passport configuration set up. Let's do the database and routes now.

Fill this in with your own database. If you don't have a MongoDB database lying around, I would suggest going to Modulus.io and grabbing one. Once you sign up (and you get a $15 credit for signing up), you can create your database, grab its connection url, and place it in this file.

app.post: For now, we will comment out the routes for handling the form POST. We do this since passport isn't set up yet.

req.flash: This is the connect-flash way of getting flashdata in the session. We will create the loginMessage inside our passport configuration.

isLoggedIn: Using route middleware, we can protect the profile section route. A user has to be logged in to access that route. Using the isLoggedIn function, we will kick a user back to the home page if they try to access http://localhost:8080/profile and they are not logged in.

Logout: We will handle logout by using req.logout() provided by passport. After logging out, redirect the user to the home page.

With our server running, we can visit our application in our browser at http://localhost:8080. Once again, we won't see much since we haven't made our views. Let's go do that now. (We're almost to the authentication stuff, I promise).

Authenticating With Passport Locally

Finally! We have finally set up our application and have gotten to the authentication part. Don't worry. The rest of the authentication articles in this tutorial series will use the same base so we won't have to set up our application again.

So far we have installed our packages, set up our application, connected to our database, created our routes, and created our views.

Now we will create our user model, configure passport for local authentication, and use our configured passport to process our login/signup forms.

We will create our user model for the entire tutorial series. Our user will have the ability to be linked to multiple social accounts and to a local account. For local accounts, we will be keeping email and password. For the social accounts, we will be keeping their id, token, and some user information.

You can change these fields out to be whatever you want. You can authenticate locally using username and password (passport-local actually uses username by default but we'll change that to email).

Our model is done. We will be hashing our password within our user model before it saves to the database. This means we don't have to deal with generating the hash ourselves. It is all handled nicely and neatly inside our user model.

Let's move onto the important stuff of this article: authenticating locally!

Configuring Passport for Local Accounts

All the configuration for passport will be handled in config/passport.js. We want to keep this code in its own file away from our other main files like routes or the server file. I have seen some implementations where passport will be configured in random places. I believe having it in this config file will keep your overall application clean and concise.

So far, we created our passport object in server.js, and then we pass it to our config/passport.js file. This is where we configure our Strategy for local, facebook, twitter, and google. This is also the file where we will create the serializeUser and deserializeUser functions to store our user in session.

I would highly recommend going to read the passport docs to understand more about how the package works.

That's all the code we need for the route. All of the heavy duty stuff lives inside of config/passport.js. All we have to set here is where our failures and successes get redirected. Super clean.

There is also much more you can do with this. Instead of specifying a successRedirect, you could use a callback and take more control over how your application works. Here is a great stackoverflow answer on error handling. It explains how to use done() and how to be more specific with your handling of a route.

Testing Signup

With our passport config finally laid out, we can uncomment that line in our server.js. This will load our config and then we can use our signup form.

Now that we have passport, our routes, and our redirects in place, let's go ahead and test our signup form. In your browser, go to http://localhost:8080/signup and fill out your form.

If all goes according to plan, you should be logged in, your user saved in the session, and you are redirected to the /profile page (the profile page will show nothing right now since we haven't defined that view).

If we look in our database, we'll also see our user sitting there cozily with all the credentials we created for him.

Exploring Your Database: I use Robomongo to see what's in my database. Just download it and connect to your database to see your new users after they signup!

This will be very similar to the signup strategy. We'll add the strategy to our config/passport.js and the route in app/routes.js.

// config/passport.js
...
// =========================================================================
// LOCAL LOGIN =============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) { // callback with email and password from our form
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
User.findOne({ 'local.email' : email }, function(err, user) {
// if there are any errors, return the error before anything else
if (err)
return done(err);
// if no user is found, return the message
if (!user)
return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash
// if the user is found but the password is wrong
if (!user.validPassword(password))
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata
// all is well, return successful user
return done(null, user);
});
}));
};

We have now provided a strategy to passport called local-login. We will use this strategy to process our login form. We can check if a user exists, if the password is wrong, and set flash data to show error messages. Let's open up our app/routes.js and handle the POST for our login form.

Now we have functional signup and login forms. If a user is successful in authenticating they will be redirected to the profile page. If they are not successful, they will go home. The last thing we need to do is make our profile page so that those that are lucky enough to signup (all of us?) will have an exclusive place of our site all to themselves.

There you have it! We've built a brand new application from scratch and have the ability to let users signup/register and login. We even have support for flash messages, hashing passwords, and requiring login for some sections of our site using route middleware.

Coming up next we'll be looking at how to take this same structure, and use passport to authenticate with Facebook, Twitter, and Google. After that we'll look at how we can get all these thing working together in the same application. Users will be able to login with one type of account, and then link their other accounts.

As always, if you see any ways to improve this or need any clarification, sound off in the comments and we'll respond pretty close to immediately... pretty close.