node-authentication-header
Javascript

Easy Node Authentication: Setup and Local

This tutorial has been updating for ExpressJS 4.0. Read more here.

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.

What we’ll be building:

We will build an application that will have:

  • Local account logins and signups (using passport-local)
  • Facebook logins and registration (using passport-facebook)
  • Twitter logins and registration (using passport-twitter)
  • Google+ logins and registration (using oauth with passport-google-oauth)
  • Require login for certain routes/sections of your application
  • Creating a password hash for local accounts (using bcrypt-nodejs)
  • Displaying error messages (using flash with connect-flash. required since express 3.x)
  • Linking all social accounts under one user account
  • Allowing a user to unlink a specific social account

The Tutorial Series

We’ll release this entire gigantic series over 5 different tutorials. They are:

  1. Getting Set up and Local Authentication
  2. Facebook Authentication
  3. Twitter Authentication
  4. Google Authentication
  5. Linking all accounts together

Enough chit chat. Let’s dive right into a completely blank Node application and build our entire application from scratch.

Here’s what we’ll be building:

node-authentication

And after a user has logged in with all their credentials:

node-authentication-profile

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.

Application Structure


	- app
	------ models
	---------- user.js 	<!-- our user model -->
	------ routes.js 	<!-- all the routes for our application -->
	- config
	------ auth.js 		<!-- will hold all our client secret keys (facebook, twitter, google) -->
	------ database.js 	<!-- will hold our database connection settings -->
	------ passport.js 	<!-- configuring the strategies for passport -->
	- views
	------ index.ejs 	<!-- show our home page with login links -->
	------ login.ejs 	<!-- show our login form -->
	------ signup.ejs 	<!-- show our signup form -->
	------ profile.ejs 	<!-- after a user logs in, they will see their profile -->
	- package.json 		<!-- handle our npm packages -->
	- server.js 		<!-- setup our application -->

Go ahead and create all those files and folders and we’ll fill them in as we go along.

Packages package.json

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.

// package.json

{
  "name": "node-authentication",
  "main": "server.js",
  "dependencies" : {
    "express" : "~4.0.0", 			
    "ejs" : "~0.8.5", 				
    "mongoose" : "~3.8.1", 			
    "passport" : "~0.1.17", 		
    "passport-local" : "~0.1.6", 	
    "passport-facebook" : "~1.0.2", 
    "passport-twitter" : "~1.0.2", 	
    "passport-google-oauth" : "~0.1.5",
    "connect-flash" : "~0.1.1", 	
    "bcrypt-nodejs" : "latest",

    "morgan": "~1.0.0",
    "body-parser": "~1.0.0",
    "cookie-parser": "~1.0.0",
    "method-override": "~1.0.0",
    "express-session": "~1.0.0"		
  }
}

Most of these are pretty self-explanatory.

  • Express is the framework.
  • Ejs is the templating engine.
  • Mongoose is object modeling for our MongoDB database.
  • Passport stuff will help us authenticating with different methods.
  • Connect-flash allows for passing session flashdata messages.
  • Bcrypt-nodejs gives us the ability to hash the password. 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:

npm install

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

Application Setup 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.

// server.js

// set up ======================================================================
// get all the tools we need
var express  = require('express');
var app      = express();
var port     = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash 	 = require('connect-flash');

var morgan       = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser   = require('body-parser');
var session      = require('express-session');

var configDB = require('./config/database.js');

// configuration ===============================================================
mongoose.connect(configDB.url); // connect to our database

// require('./config/passport')(passport); // pass passport for configuration

// set up our express application
app.use(morgan('dev')); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser()); // get information from html forms

app.set('view engine', 'ejs'); // set up ejs for templating

// required for passport
app.use(session({ secret: 'ilovescotchscotchyscotchscotch' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session

// routes ======================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport

// launch ======================================================================
app.listen(port);
console.log('The magic happens on port ' + port);

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.

Database Config config/database.js

We already are calling this file in server.js. Now we just have to set it up.

// config/database.js
module.exports = {

	'url' : 'your-settings-here' // looks like mongodb://<user>:<pass>@mongo.onmodulus.net:27017/Mikha4ot

};

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.

Routes app/routes.js

We will keep our routes simple for now. We will have the following routes:

  • Home Page (/)
  • Login Page (/login)
  • Signup Page (/signup)
  • Handle the POST for both login
  • Handle the POST for both signup
  • Profile Page (after logged in)
// app/routes.js
module.exports = function(app, passport) {

	// =====================================
	// HOME PAGE (with login links) ========
	// =====================================
	app.get('/', function(req, res) {
		res.render('index.ejs'); // load the index.ejs file
	});

	// =====================================
	// LOGIN ===============================
	// =====================================
	// show the login form
	app.get('/login', function(req, res) {

		// render the page and pass in any flash data if it exists
		res.render('login.ejs', { message: req.flash('loginMessage') }); 
	});

	// process the login form
	// app.post('/login', do all our passport stuff here);

	// =====================================
	// SIGNUP ==============================
	// =====================================
	// show the signup form
	app.get('/signup', function(req, res) {

		// render the page and pass in any flash data if it exists
		res.render('signup.ejs', { message: req.flash('signupMessage') });
	});

	// process the signup form
	// app.post('/signup', do all our passport stuff here);

	// =====================================
	// PROFILE SECTION =====================
	// =====================================
	// we will want this protected so you have to be logged in to visit
	// we will use route middleware to verify this (the isLoggedIn function)
	app.get('/profile', isLoggedIn, function(req, res) {
		res.render('profile.ejs', {
			user : req.user // get the user out of session and pass to template
		});
	});

	// =====================================
	// LOGOUT ==============================
	// =====================================
	app.get('/logout', function(req, res) {
		req.logout();
		res.redirect('/');
	});
};

// route middleware to make sure a user is logged in
function isLoggedIn(req, res, next) {

	// if user is authenticated in the session, carry on 
	if (req.isAuthenticated())
		return next();

	// if they aren't redirect them to the home page
	res.redirect('/');
}

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).

Views views/index.ejs, views/login.ejs, views/signup.ejs

Here we’ll define our views for our home page, login page, and signup/registration page.

Home Page views/index.ejs

Our home page will just show links to all our forms of authentication.

<!-- views/index.ejs -->
<!doctype html>
<html>
<head>
	<title>Node Authentication</title>
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
	<style>
		body 		{ padding-top:80px; }
	</style>
</head>
<body>
<div class="container">

	<div class="jumbotron text-center">
		<h1><span class="fa fa-lock"></span> Node Authentication</h1>

		<p>Login or Register with:</p>

		<a href="/login" class="btn btn-default"><span class="fa fa-user"></span> Local Login</a>
		<a href="/signup" class="btn btn-default"><span class="fa fa-user"></span> Local Signup</a>
	</div>

</div>
</body>
</html>

Now if we visit our app in our browser, we’ll have a site that looks like this:

node-authentication-local

Here are the views for our login and signup pages also.

Login Form views/login.ejs

<!-- views/login.ejs -->
<!doctype html>
<html>
<head>
	<title>Node Authentication</title>
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
	<style>
		body 		{ padding-top:80px; }
	</style>
</head>
<body>
<div class="container">

<div class="col-sm-6 col-sm-offset-3">

	<h1><span class="fa fa-sign-in"></span> Login</h1>

	<!-- show any messages that come back with authentication -->
	<% if (message.length > 0) { %>
		<div class="alert alert-danger"><%= message %></div>
	<% } %>

	<!-- LOGIN FORM -->
	<form action="/login" method="post">
		<div class="form-group">
			<label>Email</label>
			<input type="text" class="form-control" name="email">
		</div>
		<div class="form-group">
			<label>Password</label>
			<input type="password" class="form-control" name="password">
		</div>

		<button type="submit" class="btn btn-warning btn-lg">Login</button>
	</form>

	<hr>

	<p>Need an account? <a href="/signup">Signup</a></p>
	<p>Or go <a href="/">home</a>.</p>

</div>

</div>
</body>
</html>

node-auth-local-login

Signup Form views/signup.ejs

<!-- views/signup.ejs -->
<!doctype html>
<html>
<head>
	<title>Node Authentication</title>
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
	<style>
		body 		{ padding-top:80px; }
	</style>
</head>
<body>
<div class="container">

<div class="col-sm-6 col-sm-offset-3">

	<h1><span class="fa fa-sign-in"></span> Signup</h1>

	<!-- show any messages that come back with authentication -->
	<% if (message.length > 0) { %>
		<div class="alert alert-danger"><%= message %></div>
	<% } %>

	<!-- LOGIN FORM -->
	<form action="/signup" method="post">
		<div class="form-group">
			<label>Email</label>
			<input type="text" class="form-control" name="email">
		</div>
		<div class="form-group">
			<label>Password</label>
			<input type="password" class="form-control" name="password">
		</div>

		<button type="submit" class="btn btn-warning btn-lg">Signup</button>
	</form>

	<hr>

	<p>Already have an account? <a href="/login">Login</a></p>
	<p>Or go <a href="/">home</a>.</p>

</div>

</div>
</body>
</html>

node-auth-local-signup

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.

User Model

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).

// app/models/user.js
// load the things we need
var mongoose = require('mongoose');
var bcrypt   = require('bcrypt-nodejs');

// define the schema for our user model
var userSchema = mongoose.Schema({

    local            : {
        email        : String,
        password     : String,
    },
    facebook         : {
        id           : String,
        token        : String,
        email        : String,
        name         : String
    },
    twitter          : {
        id           : String,
        token        : String,
        displayName  : String,
        username     : String
    },
    google           : {
        id           : String,
        token        : String,
        email        : String,
        name         : String
    }

});

// methods ======================
// generating a hash
userSchema.methods.generateHash = function(password) {
    return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};

// checking if password is valid
userSchema.methods.validPassword = function(password) {
    return bcrypt.compareSync(password, this.local.password);
};

// create the model for users and expose it to our app
module.exports = mongoose.model('User', userSchema);

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.

Handling Signup/Registration

We will be handling login and signup in config/passport.js. Let’s look at signup first.

// config/passport.js

// load all the things we need
var LocalStrategy   = require('passport-local').Strategy;

// load up the user model
var User       		= require('../app/models/user');

// expose this function to our app using module.exports
module.exports = function(passport) {

    // =========================================================================
    // passport session setup ==================================================
    // =========================================================================
    // required for persistent login sessions
    // passport needs ability to serialize and unserialize users out of session

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id);
    });

    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

 	// =========================================================================
    // LOCAL SIGNUP ============================================================
    // =========================================================================
    // 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-signup', 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) {

        // asynchronous
        // User.findOne wont fire unless data is sent back
        process.nextTick(function() {

		// 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
            if (err)
                return done(err);

            // check to see if theres already a user with that email
            if (user) {
                return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
            } else {

				// if there is no user with that email
                // create the user
                var newUser            = new User();

                // set the user's local credentials
                newUser.local.email    = email;
                newUser.local.password = newUser.generateHash(password);

				// save the user
                newUser.save(function(err) {
                    if (err)
                        throw err;
                    return done(null, newUser);
                });
            }

        });    

        });

    }));

};

We have now provided a strategy to passport called local-signup. We will use this strategy to process our signup form. Let’s open up our app/routes.js and handle the POST for our signup form.

// app/routes.js
...

	// process the signup form
	app.post('/signup', passport.authenticate('local-signup', {
		successRedirect : '/profile', // redirect to the secure profile section
		failureRedirect : '/signup', // redirect back to the signup page if there is an error
		failureFlash : true // allow flash messages
	}));

...

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.

// server.js
...

	// uncomment this line
	require('./config/passport')(passport); // pass passport for configuration

...

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.

node-user-in-database

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!

With users able to sign up, let’s give them a way to login.

Login

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.

// app/routes.js
...

	// process the login form
	app.post('/login', passport.authenticate('local-login', {
		successRedirect : '/profile', // redirect to the secure profile section
		failureRedirect : '/login', // redirect back to the signup page if there is an error
		failureFlash : true // allow flash messages
	}));

...

If you try to login with a user email that doesn’t exist in our database, you will see the error. Same goes for if your password is wrong.

node-auth-login-error

Displaying User and Secure Profile Page views/profile.ejs

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.

<!-- views/profile.ejs -->
<!doctype html>
<html>
<head>
	<title>Node Authentication</title>
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
	<style>
		body 		{ padding-top:80px; word-wrap:break-word; }
	</style>
</head>
<body>
<div class="container">

	<div class="page-header text-center">
		<h1><span class="fa fa-anchor"></span> Profile Page</h1>
		<a href="/logout" class="btn btn-default btn-sm">Logout</a>
	</div>

	<div class="row">

		<!-- LOCAL INFORMATION -->
		<div class="col-sm-6">
			<div class="well">
				<h3><span class="fa fa-user"></span> Local</h3>

					<p>
						<strong>id</strong>: <%= user._id %><br>
						<strong>email</strong>: <%= user.local.email %><br>
						<strong>password</strong>: <%= user.local.password %>
					</p>

			</div>
		</div>

	</div>

</div>
</body>
</html>

After a user logs in, they can see all their information. It is grabbed from the session and passed to our view in the app/routes.js file. We will also provide a link to logout.

node-auth-local-profile-page

Conclusion

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.

Edit #1: Changed password hashing to be handled inside user model and asynchronously.
Edit #2: Changed password hashing to be explicitly called. Helps with future tutorials.
This article is part of our Easy Node Authentication series.

Chris Sevilleja

Design, development, and anything in between that I find interesting.

View My Articles

Stay Connected With Us
hover these for magic

Get valuable tips, articles, and resources straight to your inbox. Every Tuesday.

  • pinku1

    you are amazing!

    • http://scotch.io/ Chris Sevilleja

      Thanks!

  • sammychl

    should’ve posted this last week! i finally got the fb part working like few hours ago

    • http://scotch.io/ Chris Sevilleja

      Sorry! We’re going to post the Facebook part of this in a few days. Hopefully we both landed in the same ballpark for implementing Facebook auth.

      • sammychl

        i used Redis instead of mongo :) would be good aside to add that in tutorial!

        • http://scotch.io/ Chris Sevilleja

          Good point. I’ll look into adding that in the next ones. Thanks.

  • Behcet

    // check to see if theres already a user with that email
    if (user) {
    return done(null, false, req.flash(‘signupMessage’, ‘That email is already taken.’));
    }

    fails because req is undefined. I also tried the demo page, nothing visible happens I just end up at /signup again

    • http://scotch.io/ Chris Sevilleja

      Thanks for the notice. I’m looking into it now.

      • http://scotch.io/ Chris Sevilleja

        In the routes file, for app.get(‘/signup’, … it looks for req.flash(‘loginMessage’). This is a typo on my part. That should be req.flash(‘signupMessage’) because it was named that in passport.js. I’ll update the tutorial. Thanks.

        • Behcet

          Thanks for the quick response. I have just discovered
          passReqToCallback : true
          parameter is missing in tutorial webpage, that’s why I was getting errors

          • http://scotch.io/ Chris Sevilleja

            Well that’s embarrassing. Sorry. I added it in the code repo but not in the tutorial. I’ll update that. Thanks.

          • rylycomics

            I am still getting this error. I have “passReqToCallback: true” set in the “passport.use(‘local-signup’, new LocalStrategy({…” portion of passport.js. I also have “res.render(‘signup.ejs’, { message: req.flash(‘signupMessage’) });” set under “app.get(‘/signup’, function(req, res) {…” in routes.js. Ideas?

          • http://scotch.io/ Chris Sevilleja

            Oops. That’s my fault. We have set passReqToCallback to true, so the callback can receive the req. However, we have not passed it into that function.

            change function(email, password, done

            to function(req, email, password, done

            Now the callback will have req.

          • http://scotch.io/ Chris Sevilleja

            I have updated the code to reflect this. Sorry about that and thanks for pointing it out.

  • Muhammad Nur Hidayat

    Hi there, i use your local strategy script

    when i use to signup, it’s working perfectly,

    but when i try to login, it always return “Oops! Wrong password.”

    is there any mistake that i’ve done?

    • http://scotch.io/ Chris Sevilleja

      Sorry. It’s probably on my end. I’ve moved the code for hashing the password around so much that I know I’ve made a mistake. I’m checking on it right now.

      • Muhammad Nur Hidayat

        i already clone exactly from your github and it seem your code for login doesn’t work too..

        and now i already switch back using my old crypto,with my own custom salt and hash
        and it’s working fine.

        but overall i understand how to use passport-local,many thanks chris

        • http://scotch.io/ Chris Sevilleja

          You are very welcome. I found the problem. My code was wrong in the hashPassword method in the user model.

          I was stupidly passing the undefined password for hashing instead of passing the password from the signup form. I’ve updated the code and article. Thanks for pointing it out.

      • Muhammad Nur Hidayat

        and maybe it’s better keep your mongoose logic(find,update,etc) on model,and controller only passing parameter to models. so it can be used in another controllers.

        because i see your model only for schema.

  • rylycomics

    Still getting strange errors in this. When I initially signup I get this error:

    TypeError: Object function model(doc, fields, skipId) {
    if (!(this instanceof model))
    return new model(doc, fields, skipId);
    Model.call(this, doc, fields, skipId);
    } has no method ‘findByID’

    …at 25:8 of ‘passport.js’…

    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
    User.findByID(id, function(err, user) {
    done(err, user);
    });
    });

    This error will continually popup with a ’500′ error as I attempt to access other pages. Despite this it does seem to add my initial user to the Mongo database. It also tells me every password I enter is incorrect. It also disallows me from entering any other users and throws :

    MongoError: E11000 duplicate key error index: dev_db.users.$username_1 dup key: { : null }

    …when I attempt to.

    I think I may need to start over. =(

    • http://scotch.io/ Chris Sevilleja

      It looks like it has problems finding the user in the session or putting the user in the session. Does login work ok?

      Are you sure you set up Passport to utilize the session? In server.js, make sure that these two lines are there:

      app.use(passport.initialize());
      app.use(passport.session());

      • rylycomics

        Yeah, I have the lines in ‘server.js’ as they appear above…

        app.use(express.session({ secret: ‘ilovescotchscotchyscotchscotch’ })); // session secret
        app.use(passport.initialize());

        And ‘/login’ seems to recognize that the email appears in my database but it constantly throws the “Oops! Wrong password!” message.

        I think I may take the next few days to go through this again. I know that a lot of the code has been rearranged since it was originally posted, there may be an error somewhere in my files because of this.

        • http://scotch.io/ Chris Sevilleja

          I found an error in my code. In the user model, change bcrypt.hash(user.local.password to bcrypt.hash(password…

          This should solve your Oops Wrong Password problem since on signup, it wasn’t actually hashing the password you passed into the signup form.

  • Pingback: Easy Node Authentication: Facebook ♥ Scotch

  • Pingback: Easy Node Authentication: Twitter ♥ Scotch

  • David Murdoch

    You could easily switch from using bcrypt-nodejs to using easy-pbkdf2 in order to get built-in(and mandatory) salting. https://npmjs.org/package/easy-pbkdf2.

    First, do this: var easyPbkdf2 = require('easy-pbkdf2')({'DEFAULT_HASH_ITERATIONS': 64000});

    Then, add a `salt` field to the local user mongoose schema.

    Now you can create your password hashes like this (it is asynchronous, so make sure you update your code accordingly):

    easyPbkdf2.secureHash( password, function( err, passwordHash, newSalt ) {
    if ( err )
    return next ( err );

    user.local.password = passwordHash;
    user.local.salt = newSalt;
    });

    And authenticate like this:

    easyPbkdf2.verify( user.salt, user.password, function( err, isValid ) {
    if( err || !isValid ) {
    return done( null, false, req.flash(‘loginMessage;’, Oops! Wrong password.’) );
    }

    // all is well, return successful user
    return done(null, user);
    });

    While bcrypt is *theoretically* “better” than PBKDF2, it hasn’t been vetted nearly as much as PBKDF2. In fact, if you need your library, platform, app to comply with NIST or FIPS standards, you can’t even use bcrypt.

  • David Murdoch

    Well, I had a long, thought out comment but it is gone now. Disqus is the worst comment system ever invented.

  • pelumini

    Yee! Got it working on my dev-machine. You’ve done a good job, bravo!

  • hong6

    Amazing example, thanks so much! One thing I can’t figure out…
    I Created https://modulus.io/database/Go3gihiw
    But Error: failed to connect to [mongo.onmodulus.net:27017]
    Do you know why?

    // config/database.js
    module.exports = {
    ‘url’: ‘mongodb://myusername:[email protected]:27017/Go3gihiw’
    };

    • http://scotch.io/ Chris Sevilleja

      That is weird. Could you show the entire error here? That looks right. I’d have to see more of the error to know for sure.

      • hong6

        Actually I got it working from my home computer, but still got error from my office computer/network. and also I can’t connect my DB via Robomongo in office, network security issue? attached error images here.

        • KukicAdnan

          There are a couple of things that will throw the EACCESS error.
          1) Ensure that you are running the server at a greater than 1024 port.. so like :3000 or :8080 should work
          2) Ensure that you have admin rights / run node as administrator.
          3) Do you have another program running that could be blocking the port? Skype perhaps?

          • hong6

            Yeah I tried other port like 8089, UI works few seconds, then abort, error says failed to connect to mongo.onmodulus.net… It works totally from home though, I guess it is office network security issue.
            Thank you!

      • hong6

        If I changed port, error indicate failed to connect database

  • Pingback: Easy Node Authentication: Google ♥ Scotch

  • Jonrod

    Wow!! Thank you for sharing!
    I read most of your posts on Node as it’s gold information : good structure, good design, good practices… Very sleek! Congrats!

    I am quite struggling to merge your “easy-node-authentication-setup-and-local” along with your “todo-MEAN”.

    Indeed, they have complete different structure :
    On one hand “todo-MEAN” relies on a single front-end route like “app.get(‘*’, index)” while “node-authentication” relies on several routes to handle login, signup and profile.

    I could basically create a special route to serve the required “todo-MEAN” app, but I have a SPA structure in mind and my different routes are handled by Angular to be served asynchronously with a $routeProvider Controller. I thus have “PARTIALS” instead of “PAGES”.

    How do you handle PARTIALS authentication with passport? Is it possible?

    Thanks in advance for your reply.

    • http://scotch.io/ Chris Sevilleja

      Hello. Thanks for reading first of all.

      So I gather that you are trying to do authentication completely using an $http service from Angular to hit your Node authentication route. I’ve been working this out myself so I can write an article on it, but I believe that for authentication like that, you are going to have to redirect at some point for social connections (since you have to send a user to Facebook, Twitter, or Google to authenticate).

      If you are authenticating locally, you could use $http to call a Node route. Then instead of doing a successRedirect, you could pass back json.

      app.get(‘/auth/local/callback’,
      passport.authenticate(‘local’, { failureRedirect: ‘/login’ }),

      // function to specifically handle the callback and pass json back
      function(req, res) {
      res.json(‘success!’);
      });

      Hopefully that helps. I can help clarify if that doesn’t make complete sense.

      • Jonrod

        Ok I get the idea.
        I should then play with angular’s $http calls instead of trying to make node handle the whole redirection.

        But I still have some misunderstandings about partials : since I use only one route to serve front-end app, what is the best way to manage local variables?

        For instance, when login with passport, your tutorial handles a pretty usefull “flash.message()” in case of login errors and “listens” to this underlying “message” to be displayed inside the template. This is working because it is not a Single Page App and thus every routes are explicitly handled one by one from the server-side.

        But in my Single Page tryout I have a “no-refresh magic” happening with Angular at the front-end (exactly the same structure taken from your own tutorial here : http://scotch.io/tutorials/javascript/single-page-apps-with-angularjs-routing-and-templating).
        So when I go through all the process of calling the root “homepage” that initializes every local-variables like for instance “flash.message()” or “req.user” and decide to go to

        http://localhost:3000/TODO

        that WORKS LIKE A CHARM! ;-)

        Unfortunately, when I try to directly reach the same

        http://localhost:3000/TODO

        from the address bar I get a very ugly error message telling me that “message” is undefined…

        I clearly understand why it’s undefined : flash.message() depends on my base/layout/index (I mean the non refreshed part of the page) while “/TODO” is only a partial totally unaware of local-variables initially sent by Node.js…
        But… I am not good enough to resolve this problem by my own! :-)

        I will then wait for your next Tutorial!!! ahah!!

        • http://scotch.io/ Chris Sevilleja

          You are completely correct that Node has not sent the variables to your partial/view. The way to resolve this is to think of your application differently. Since you are creating a single page app with Angular, you want to treat Node as an API/Data layer and Angular as the frontend.

          This means that all your data will be passed from Node to Angular using $http calls. So those variables like messages and passing user data should be passed to Angular in your Angular controller.

          For a little more information on that, check out our other article: http://scotch.io/tutorials/javascript/creating-a-single-page-todo-app-with-node-and-angular It will help to understand how to pass data to and from Node to Angular.

          Hopefully that helps a bit more and I’ll start thinking up new articles to be closer to your current scenario.

          • Jonrod

            Thumbs up!
            Thank you Chris.

            I wish you pass a happy new year!
            ;-)

          • rahanee

            Hi, did you ever get it working with Angular? If yes, do you have a repository on Github that I could take a look at? I’m struggling :/

      • Steve

        Hi Chris,

        I see how you can return json data when it is successful but how would you do the same thing for failure and optionally pass a message that Angular can show to the user?

        • http://scotch.io/ Chris Sevilleja

          You could pass back a success/error and then handle that in Angular.

          .success(function(data) {
          if (data.success) {
          console.log(‘successful!’);
          } else {
          $scope.message = data.message; // pass back a message if theres an error
          }

          Then you could display this message in your view using {{ message }}.

          • Steve

            Hi Chris,

            Thanks for that, what I’m having trouble with is actually sending messages to Angular from the server. There is only a callback function for the passport.authenticate on success (it seems), if you try to sign up with the same email address for example, it just returns the failureRedirect html if I log it out to the console:

            This is the route: http://cl.ly/ToOU
            This is the strategy: http://cl.ly/Tnzn
            Angular service: http://cl.ly/Toj1

            I know I am missing something and your guidance would be hugely appreciated, I have looked everywhere and can’t find the answer. I’m fairly new to all this.

            Cheers!

          • http://scotch.io/ Chris Sevilleja

            You could try not using failureRedirect at all and handling everything in a custom callback. In your custom callback, you could check for a success variable and handle both failure and success within that. Hopefully that helps.

            http://stackoverflow.com/questions/15388206/sending-back-a-json-response-when-failing-passport-js-authentication
            http://passportjs.org/guide/authenticate/ (the custom callback section)

  • Pingback: Easy Node Authentication: Linking All Accounts Together ♥ Scotch

  • Connor James Leech

    Why do you structure your app totally different from the default express setup (that has three folders: public, routes and views)?

    • http://scotch.io/ Chris Sevilleja

      It’s really all up to preference. You can definitely use their base structure. I personally like moving my routes into one file since it’s easier to read, you get an overview of your application, and you don’t have to bounce around looking through different route files. (It’s good for tutorials too).

      We’re not that far from the express setup either. I looked at theirs and mean.io when creating this. You’re gonna need a place to put models and controllers when your application requires them so I like putting them into an app folder.

      Again, it’s all preference. Express has a good starting point but to move to a larger application, I think it’s good to have a structure like mean.io or how we’re set up here.

      • Connor James Leech

        Ok cool thank you. I’m coming from a rails background. The javascript stack is way more flexible

  • Light Is Everything

    Great tutorial, one thing I am trying to wrap my head around is what is actually served to the browser, a html doc?

    Could you modify the above to also work with phonegap, again as I’m not sure what is actually serving to the browser I’m not sure how this could work?

    • http://scotch.io/ Chris Sevilleja

      The browser is served the .ejs file with is just HTML with templating features from Jade. This is send to the browser using res.render().

      I’m not entirely sure how Phonegap works so I can’t really say. Phonegap apps can only use HTML, CSS, and Javascript so I think that you would have to create the frontend of your app totally separate and do authentication via an API call to any Node backend that you create.

      • Light Is Everything

        Is it the .ejs or something else? Looking in the Network tab of dev tools there isn’t a .ejs served, just the login (example) GET request? I get that the content of the page is from say login.ejs but what is the file that is sent back from node? Not too concerned as it all works, just curious.

        I actually got Phonegap working by have an index.html in the root just create the initial GET with window.location.replace(server_name); It then just works as expected serving up the app. Nice!

        • http://scotch.io/ Chris Sevilleja

          I think it is the HTML that gets sent. Node processes the ejs template and sends the HTML. https://github.com/visionmedia/ejs

          Awesome that Phonegap works for you!

  • Pingback: Google

  • Alexander di Chiara

    Hi Chris, that’s a pretty good job, many congs. Me, i’m still sticking in the old way so, i really appreciate the approach, cool and clean ;)

    Just a point, in your revised schema you’re salting your password, so maybe the blue tip about salting has to be edited? or am I wrong?

    Cheers!

    • Alexander di Chiara

      Another little thing: the google tut link on the bottom points to -twitter not -google, a small thing, just to let you know ;)

      Many thanks again! Awesome Job!
      Alex

      • http://scotch.io/ Chris Sevilleja

        Thanks for those. Both have been fixed!

        • Alexander di Chiara

          You’re very welcome, that’s the minimum. I’ve to say what’s very interesting about passport is the opportunity to bring in your full req.body, i’ve splitted the userlevel without additional support, since i’ve 2 different views:

          // set the user’s local credentials

          newUser.local.email = email;
          newUser.local.password = newUser.generateHash(req.body.password);
          newUser.local.approved = 0;
          newUser.local.level = req.body.level;

          that’s truly pretty straightforward, and working.

          Many thanks, fast prototyping but as good as production. :)

  • Michael Fok

    Hi Chris,

    I seem to be having problems with posting to ‘/signup’, particularly in passport.js when we use User.findOne to look for duplicate emails. I’ve placed console messages both before, after, and inside it, but only the first and last get triggered. the log message inside the findOne message never seems to be called. Any idea why this might be?

    • http://scotch.io/ Chris Sevilleja

      Yes sorry. I updated the other articles in this tutorial, but not this one. You’re going to want to make the User.findOne call asynchronous. To do this, you’d surround the User.findOne code with process.nextTick()

      This ensures that User.findOne won’t fire unless data actually is sent back. https://github.com/scotch-io/easy-node-authentication/blob/linking/config/passport.js#L78

      That should work but if not, we can check for other solutions.

      • Michael Fok

        Ah Chris, thank you for the quick response!

        Updated it with the code in the github file, but still no luck. The messages in User.findOne still aren’t being triggered. In fact, when I tried to sign up via the demo just now, I got a ‘The page cannot be displayed because an internal server error has occurred.’ error. Any thoughts?

        edit: nevermind, I tried the demo again and it was working. Hmm…

        • http://scotch.io/ Chris Sevilleja

          That is interesting. What are you console.logging to test?

          • Michael Fok

            http://jsfiddle.net/BLuf8/

            I added a number of ‘bp’s (breakpoints) to see where the app was and wasn’t working. My logs have looked a little something like this:

            GET /signup 304 18ms
            bp1
            bp3
            bp2
            POST /signup 200 2273ms
            bp1
            bp3
            bp2
            POST /signup 200 856ms

          • http://scotch.io/ Chris Sevilleja

            Glad it all got worked out. In the future, try logging something that will show if code executed. Like the profile, or the user information. This helps to show if a certain call is or isn’t working, not just a check if it actually executed.

          • Michael Fok

            Looking at my modulus logs, it seems like I actually AM querying the database? https://www.dropbox.com/s/l5c426qshdzzg9j/Screenshot%202014-02-01%2020.47.09.png

          • Michael Fok

            Hey, upon testing it later – it seems that I had used a `mongoose.createConnection(configDB.url); instead of a `mongoose.connect`. Odd that it wasn’t throwing an error or giving me any signs though it seems to be working now.

            Thanks for trying to work it out with me earlier. Much appreciated!

      • Ruan Botha

        Hi Chris, I have been working with node.js and mongo on a fulltime basis for the past 4 months, but being quite new to development and JS, I have not been able to understand properly what process.nextTick() is used for – would you mind explaining it a bit more in depth, especially in this case where you used it? Thank you!
        Ruan

  • Ruan Botha

    You are a boss Chris! This was an excellent tutorial! Thank you for the great work you put into the first part, will peruse the other parts as necessary! :D

    • Ruan Botha

      Hi Chris, hope you are well! Also wanted to find out under what license this code falls? Can we use it (or parts of it) in our own web apps? :D

      • http://scotch.io/ Chris Sevilleja

        Hello. This is under the MIT license and feel free to use any or all parts of it for your apps! Hopefully it helps speed up your development.

        • Ruan Botha

          Thank you Chris! Yeah it definitely does! :-)

  • Pingback: Web Weekly Episode 6 Video Highlights - Dan Wahlin

  • black boulez

    Really usefull, and easy to follow ,thanks!

  • gkrinker

    Hi,

    Thank you very much for sharing a detailed and well explained tutorial. I’m a little new to node and its modules.

    I was wondering whether you could comment on the security of your design.

    1) When you do your post for sending credentials, shouldn’t you be doing it over HTTPS? When is it necessary for you to use HTTPS so that others aren’t sniffing your information? How could you change your design to use that?

    2) I can’t follow how you’re keeping track of session. Does passport abstract all of that? If so, are they using cookies? Are the cookies plaintext? Are you sending the user a id string back?

    3) Are you getting any protection from content injection for free? I don’t see any code to try and escape dangerous characters or anything.

    Anyway, how hacker safe is this design?

    • James Lukaro

      Definitely a good question. Hacker safety is important.

    • http://scotch.io/ Chris Sevilleja

      Hey Georges. Let me start by saying that I am by no means an expert in security so I will try to answer them to the best of my ability. You’ve asked some great questions.

      1. When sending credentials from a client to server, you should always use HTTPS. When changing this, I believe you would implement the passport-http module made by Passport’s creator. In the other articles in this series, we use Passport Strategies like GoogleStrategy and FacebookStrategy. This passport-http module will provide access to the BasicStrategy and DigestStrategy. Look through those docs to see how those are used. It will send the password in plaintext so HTTPS will handle all that for you.

      References:
      http://passportjs.org/guide/basic-digest/
      https://github.com/jaredhanson/passport-http

      2. Passport will use Express to handle the session in our example. I’m not entirely sure the method for this, but the docs do say that Passport will serialize and unserialize an instance of the user to and from the session. This does not mean that it uses the express.session() middle ware. I believe that is more for storing your own data into session.

      References:
      http://passportjs.org/guide/configure/ (Middleware and Sessions sections)
      http://stackoverflow.com/questions/14245519/how-does-passport-js-handle-sessions

      3. Databases aren’t my specialty really. I’ve heard that NoSQL databases are better against injection than relational database. MongoDB doesn’t parse the data so that is how injection attacks are avoided. This is the best reference I have to this answer. It looks like injection is possible when using PHP, but for this tutorial since we are using Node, that’s not an issue.

      References:
      http://stackoverflow.com/questions/5021456/how-does-mongodb-avoid-the-sql-injection-mess

      RESTful Node Authentication

      This is what I want to get into in the future. I believe this is a very common way to do authentication nowadays and I’m working on a tutorial series for this. The main differences are that you wouldn’t be using sessions for your interaction with the API. You would do your first authentication from your client to server using a RESTful login and then the server would respond with a token. Each request after that would include the access_token.

      With this way, you can remove the need for a session by adding the session:false parameter.

      passport.authenticate(‘basic’, { session: false }),

      I’ll expand more on this in future articles but this request should also be HTTPS and you wouldn’t have to worry about storing sessions so there’s that.

      As always, these are the best answers that I have but I’m sure others out there have more knowledge than me on the subject. If you find information that you find helpful, please post it so I can learn also. If anyone else wants to chime in on these answers also, I’d definitely encourage it.

  • Dan Limburg

    Hello, I tried everything, and even downloaded the demo files. When I run node:

    $ node server.js

    I get this weird error output:

    connect.multipart() will be removed in connect 3.0
    visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
    connect.limit() will be removed in connect 3.0
    The magic happens on port 8080
    events.js:72
    throw er; // Unhandled ‘error’ event
    ^
    Error: failed to connect to [your-database-here:27017]
    at null. (node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:553:74)
    at EventEmitter.emit (events.js:106:17)
    at null. (node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:140:15)
    at EventEmitter.emit (events.js:98:17)
    at Socket. (node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js:512:10)
    at Socket.EventEmitter.emit (events.js:95:17)
    at net.js:830:16
    at process._tickCallback (node.js:415:13)

    What should I do?

  • James Lukaro

    Chris, you rock! But I have one small problem: “The magic happens on port 8080″. Can I ‘move the magic’ to a different port? I need to use the auth in another port, not :8080.

  • Jack Saat

    Want to do something like this authentications with Facebook/Twitter and Google BUT with Laravel and Mysql database and some use of Angular in the frontend! :S

  • grebett

    As we say in France, “chapeau Monsieur”, which means i take off my hat as a token of admiration !

    • Marcoos

      Token :D

  • Ivor Scott

    Danke! Ich liebe dich!

  • Matt Martin

    Hi Chris, thanks so much for these tutorials. I actually started with your MEAN series, then wanted to add authentication so I thought I might be able to sort of combine this content with the MEAN series to get authentication on top of the MEAN stack. One question I have about this is what is the best way to setup routes for signin, and signup? Do they go in the server side, completely bypassing angular, or do they route through the public folder – through angular?

    Thanks so much for these great tutorials!

    Regards,
    Matt

    • http://scotch.io/ Chris Sevilleja

      I believe you should route them through Angular. You should have the authentication be handled through an API. So in this scenario, Angular will do a POST for signin or signup and the Node API would return a user object and successful login message using JSON.

      We’ll be doing a tutorial on exactly this very soon so keep an eye out for that.

      • Matt Martin

        Thanks so much, Chris. I’ll definitely be watching for that tutorial!

  • Arnaud

    Hi, thanks for the tutorial.

    I followed the steps carefully but everytime I try to launch the application with node server.js I get the following error message:

    connect.multipart() will be removed in connect 3.0
    visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
    connect.limit() will be removed in connect 3.0
    The magic happens on port 27017

    /Users/Folder/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js:242

    throw message;
    ^
    MongoError: auth fails
    at Object.toError (/Users/Folder/node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js:110:11)
    at /Users/Folder/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js:39:33
    at /Users/Folder/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js:1806:9
    at Server.Base._callHandler (/Users/Folder/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js:442:41)
    at /Users/Folder/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:485:18
    at MongoReply.parseBody (/Users/Folder/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:68:5)
    at null. (/Users/Folder/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:443:20)
    at EventEmitter.emit (events.js:95:17)
    at null. (/Users/Folder/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:191:13)
    at EventEmitter.emit (events.js:98:17)

    What’s going wrong?

    • tybenmark

      Salut Arnaud,
      The reason for this error is most likely because when you define your modulus mongo database url, you are literally putting ” and ” in the url. Instead you need to type in your actual username and password.

  • Stefan474

    I cannot run server using code from github :/
    There is an error: ” Error: Cannot find module ‘../build/Release/kerberos’ ”
    What is kerberos and how can I fix this problem? I haven’t made any changes in code, this is exactly what I got from github.

    • http://scotch.io/ Chris Sevilleja

      That is very weird. I have no idea what kerberos is. I’ve tested pulling the repo and from console everything works fine.nnnIf you figure it out, post it here. I think people that use Visual Studio would be interested.

  • Pingback: Node.JS | Pearltrees

  • Richard Jedliu010dka

    Hi, please can you explain me why do you place the req.flash(….) into the done method call?nnE.g. here:nn// if no user is found, return the messagenif (!user)nreturn done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flashnnnAs I know the req.flash method returns the number of messages set with the specified type. Is it somehow useful to pass it as third parameter of the done function?

    • http://scotch.io/ Chris Sevilleja

      This is how we are able to display the error message to the user in our form. I figured this was the best way to pass data to our frontend from Node.

      • Richard Jedlička

        Yes, you use req.flash for it. But why don’t you call it this way?


        if (!user)
        req.flash('loginMessage', 'No user found.');
        return done(null, false);

        Why do you pass the result of req.flash to the done method?

        • http://scotch.io/ Chris Sevilleja

          That’s a good question. I’m not entirely sure to be honest. Just one of the ways I saw it done. I guess the other way would work also.

          You can pass parameters like that when using done but I guess in this case since it is saved to the session, it isn’t necessary.

          If you try out the req.flash outside of done, could you let us know your findings here?

          • Richard Jedlička

            Ok, I will let you know when I try it. Now I can say than there is another way:


            if (!user) {
            return done(null, false, { message: 'No user found.' });
            } else {
            return done(null, user, { message: 'Login successful' });
            }
            ....
            ....
            app.get('/login', passport.authenticate('local', {
            failureRedirect: '/login',
            successRedirect: '/',
            failureFlash: true, // for error flash messages to work - available through req.flash('error')
            successFlash: true // for success flash messages to work - available through req.flash('success')
            });

  • pamasway

    Congratulations! This was an excellent tutorial! Keep writing new ones! :D I’ve got a new follower

  • johnzan

    Hi Chris, just a quick note to say a very big thanks for this post – Its given me a fantastic start :-)
    Thanks again.
    J.

  • Jose Rafael

    Chris,
    This is EXACTLY what I’ve been looking for! Outstanding work putting this in such an accessible format! I just finished doing the tutorial and I’m walking away with a bunch of new tools! Thanks!!!

    • http://scotch.io/ Chris Sevilleja

      Glad to hear it! Thanks for reading. Let me know if there are any other tutorials you’d like to see.

      • Jose Rafael

        Well since you’re asking, It’d be nice to see something on MongoDB. Maybe extending the authentication tutorial by letting users do CRUD operations. btw, love the new site refresh! Seems to run much smoother to me.

        • http://scotch.io/ Chris Sevilleja

          We’ll definitely be doing a Node CRUD one and some basics into getting into the MEAN stack. Maybe a full blown app in the future with auth, crud and more.

          • Jose Rafael

            That sounds great! Looking forward to getting into the next tutorial! Many thanks!

  • Mack

    Hello Chris,

    Thanks for this amazing tutorial, this will help me a lot in my internship project !
    But, I’m really a newbie to the MEAN stack : I don’t understand the database config part. I want to use a local mongo database and I really don’t have an idea how to put that in the config/database.js file, the current structure is for Modulus if I’m not wrong.
    So my question is : how can a local db be linked and what is the structure to use ?
    the equivalent of this one “mongodb://:@mongo.onmodulus.net:27017/Mikha4ot”

    Thanks !

  • twopartysystemsucks

    I keep getting the following error

    /Users/ruscalder/Projects/taction/routes/admin.js:23

    app.post(‘/signup’, passport.authenticate(‘local-signup’, {

    ^

    TypeError: Cannot call method ‘authenticate’ of undefined

  • Reno Natallino

    Thank you very much for posting this tutorial,
    your information about create nodejs project from scratch really really help me to learn.

    for beginner like me, your tutorial really helpful..

    Once again, Thank you very much..

    • http://scotch.io/ Chris Sevilleja

      Hey Reno. Glad to hear it helped. Thanks for reading.

  • aholsteinson

    Fantastic tutorial, very well documented and easy to follow through. I am learning node.js and this was very helpful. Thanks!

  • Ahmed

    Great Tutorial! Thank you!

    I wanted to allow the user to login with a username or an email address so I added another field to the “user” model called “username”. I edited signup.ejs, login.ejs, & passport.js

    passport.use(‘local-signup’, new LocalStrategy({
    // by default, local strategy uses username and password, we will override with email
    emailField : ‘email’,
    usernameField : ‘username’,
    passwordField : ‘password’,
    passReqToCallback : true // allows us to pass back the entire request to the callback
    },

    function(req, email, username, password, done) {

    // asynchronous
    // User.findOne wont fire unless data is sent back
    process.nextTick(function() {

    // 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
    if (err)
    return done(err);

    // check to see if theres already a user with that email
    if (user) {
    return done(null, false, req.flash(‘signupMessage’, ‘That email is already taken.’));
    } else {

    return done(null, false, req.flash(‘signupMessage’, ‘That email is already taken.’));
    } else {

    // if there is no user with that email
    // create the user
    var newUser = new User();

    // set the user’s local credentials
    newUser.local.email = email;
    newUser.local.username = username;
    newUser.local.password = newUser.generateHash(password);

    // save the user
    newUser.save(function(err) {
    if (err)
    throw err;
    return done(null, newUser);
    });
    }
    });

    Now when I create a new user two things happen:
    1. The User is saved in the database; however, the value for password is hashed, the value of username is the password that I typed in the form, and email is the username.
    2. The program crashes with “TypeError: undefined is not a function” in passport.js line: return done(null, false, req.flash(‘loginMessage’, ‘No use

    Last, I would also like to hash the email, if possible. I’m hoping you can point to the right direction. Thank you so very much!!

    • http://scotch.io/ Chris Sevilleja

      Make sure you are binding your variables from your form correctly using ng-model. That could be the reason why user is showing up as password.

      Not too sure about the second one. It looks like you are passing email and password into the passport callback function. I’m not sure if this could call an error. You’d have to check the passport docs on how to authenticate using either email or username.

    • Tarun Sukhu

      Hey Ahmed,

      I too did run into this issue and on investigating passport docs with respect to the LocalStrategy , I could not find a way of providing both the ‘emailField’ and ‘usernameField’ together. In-fact it only excepts ‘usernameField’ and one needs to provide only one option of what this field maps to username or email. However I did workaround this using a hidden form field to tell me whether it is a username or email field and based on that perform the login. Similarly you would need to make a change in the sign-up function where you need to check both the email and the username options based on which one is provided ( though in my case I made email mandatory and username optional) , plus have a validation of previously existing usernames and emails for the sign-up.

      here is the snippet from my project https://github.com/tsukhu/rwd-spa-alljs-app

      ————————-
      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
      // login form hidden field for login option (username or email)
      // if username set then set the key for username and password
      if (req.body.loginOption===’login-user’){
      // find a user whose email is the same the forms email
      // we are checking to see if the user trying to login already exists
      User.findOne({‘local.username’ : req.body.username } , function(err, user) {

      } else {

      User.findOne({‘local.email’ : email }, function(err, user) {

      ..
      }

  • Alexandre Ferreira

    How I can use session.regenerate in this tutorial to prevent session fixation?

  • Paradoxical

    Hey @sevilayha:disqus, you mentioned about a month ago that you were working on expanding this for RESTful authentication. Are you still planning to release that? I know many people who can only work using REST apis (particularly for mobile) and we’d all love to see it. Coming from the Rails world, this is very simple, as all of this is basically baked into Devise and a few satellite gems. Looking forward to seeing your solution!

    • http://scotch.io/ Chris Sevilleja

      Yes I am planning on releasing that. I started doing the experiments for that, but ran into kind of a snag. I got carried away doing RESTful authentication with the MEAN stack and then dove into doing Angular authentication with Facebook, Google, and Twitter.

      I’m still trying to figure out the best way to handle this. Are you more interested in RESTful authentication just for local accounts or more for the social accounts? I’m starting to think social account authentication should just be done through the provider (Facebook, Google, Twitter).

      • Paradoxical

        We’ve been diving into this too, and it’s tricky. The primary goal is to auth each request post-authentication. We’ve accomplished this through attaching an auth token to the header of each request and validating on the API. It’s overhead, but there’s seemingly no way around it. You can then whitelist certain routes where auth isn’t needed – e.g., /signup. The auth token is provider-agnostic. Does not matter if initial auth was local, social, or multiple.

        RESTfully initial-authing social is challenging, particularly in a non-native app, such as Phonegap/Cordova. You’ll need to open a browser window within the app to allow handoff to the provider, then handle any possible next cases. Of course this is super-fun when the provider auth wants to redirect to a URL – but you’re in a mobile app now and this paradigm isn’t nearly as helpful. So you’ll need to write some code and watch what’s happening in the in-app browser and handle accordingly. Finally, you’ll have to break this behavior out from the web/mobile web flow, which will be more traditional.

        Anyway, yes, would love to see how you handle RESTful+MEAN. We have it working, but always dreaming of a simpler solution. Hopefully I answered your question – I think whatever the solution, you need to try to control the flow, rather than kicking the user out and hoping they come back. I’ve seen big companies/apps still spawning a new Safari window, and it’s horrible UX.

        • http://scotch.io/ Chris Sevilleja

          You bring up some great points about mobile authentication. That was a perspective I wasn’t thinking about when building out the next round of auth tutorials. And awesome idea about having the auth token be provider-agnostic.

          I agree with you about usability being very important. I’ll keep working on it and trying to get a really elegant solution.

      • Chris Blazek

        I just finished up a solution for a project I’m working on. We have an oAuth service written in rails that creates a token using the Client Credentials flow along with a redis session store shared with our socket.io service. The socket service validates tokens & session ids with what’s in the redis session store. Our client is a mobile app written in angular. I’m using Omniauth as the authentication piece and can drop in middleware to support other providers. Currently I’m just checking against ldap.

  • Michael Joseph Aubry

    Such a clutch post! Thanks for this, I am going to try and implement socket.io with this, that way logged in users can chat and send messages in real time.

    • http://scotch.io/ Chris Sevilleja

      Nice. I’m actually working on a socket.io article that I hope to release end of this week or beginning of next.

  • dfearon

    Sorry for the stupid question, but I don’t understand the comment:

    // User.findOne wont fire unless data is sent back

    Is this talking about whether the “User.findOne…” line is executed at all, or about what happens after the find is performed?

    By the way, I posted a couple of issues on Github (though the most important one relates to code not in this first part of the tutorial).

    • http://scotch.io/ Chris Sevilleja

      Sorry instead of “won’t fire unless”, that should be “won’t fire until” so the callback will queue up the job and wait until information is sent back from the authentication to run User.findOne. It won’t be able to findOne if there is no data to check. This is how we make this call asynchronous and non-blocking.

      I saw the issues on Github. Won’t be able to get to them this week, but I’ll try for early next week. If you figure it out, send a pull request too!

      • Dfearon

        OK, thanks for the clarification.

        I’m kind of new to Github, Node and JS so I’ll take a look but not sure I can determine the best solution.

        The signup problem seems to be from line 108-115 of passport.js. I think it might be solved by replacing the whole block with the following line, but could be misunderstanding something:

        return done(null, req.user);

        For the email addresses I’d just convert to lower-case before saving or comparing to the database, and after loading from the database to support existing databases with mixed-case email addresses.

        • dfearon

          One problem with my proposed solution: Since the database is being searched by e-mails obviously it’s not possible to just convert the one DB e-mail address to lower-case before comparing. This means that in order to support existing databases with mixed-case e-mail addresses, it would be necessary to either:
          a. Run slower, mixed-case searches for e-mail addresses using regular expressions
          or
          b. Convert all database e-mail addresses to lower-case using a one-time script.

          For new projects without users in an existing database there would be no problem, though.

          • dfearon

            P.S. – The advantage to using a regexp search is that it could be used for intentionally-mixed-case usernames if somebody preferred to use those in place of e-mail addresses.

            I could try creating a pull request for my current code, which converts all e-mail addresses to lower-case (including Facebook and Google addresses), but I don’t know whether that’s your preferred solution.

          • dfearon

            I’ve created a pull request for the signup issue. I had previously misunderstood the purpose of the existing code (to connect a local account) — my proposed solution retains that functionality while preventing existing local account info from being overwritten. As mentioned, though, I’m new to this, so please verify the changes before applying.

          • http://scotch.io/ Chris Sevilleja

            Hey. Great additions and great thought process. I’ve merged the request to the repo. Thanks very much for helping this project get better. I agree that changing the database to be all lowercase after the fact is a hard thing to do. You should definitely start the database the lowercase way.

            I believe case shouldn’t make two different usernames or two different emails so making them lowercase is a good idea. Thanks again.

          • dfearon

            OK, great! No problem.

            If anyone does need to use an existing database with the updated code, they should be able to write a piece of code that loops through every email address, converts them to lower-case and saves them again. Run once and forget.

  • Noam Dgani

    Hey Chris

    First of all, i completed the Todo app series and got hooked on your wonderful articles.

    They are very clear and concise.

    Thank you for a great job.

    I have a question about this article –

    I completed building the app as presented above and for some reason, when i navigate to local host

    i get a read time out.

    I’ve been trying different things, and found that if i change server.js from:

    app.use(express.session({ secret : ‘ilovescotchscotchyscotchscotch’}));

    to:
    app.use(express.static(__dirname + ‘/views’));

    and use an index.html (just a dummy one) instead of index.ejs, I dont get the timeout.

    What am i missing here?

    Thanks

    • http://scotch.io/ Chris Sevilleja

      Hey Noam, thanks for reading and going through the articles! The two lines you refer to do entirely different things. If you are getting a timeout, then first make sure you have ejs installed in your package.json file.

      Also, are you using res.render (for ejs files) or res.sendfile (for html files)? By default, ejs should look into the /views folder so that line isn’t really necessary.

      • Noam Dgani

        Thanks for your reply.

        I checked and i have ejs included in my package.json and i am using res.render.
        do i have to do anything else besides include ejs in my package.json and running an npm install?

        • http://scotch.io/ Chris Sevilleja

          When you configure your application you have to set it to use ejs.

          app.set(‘view engine’, ‘ejs’); // set up ejs for templating

          • Noam Dgani

            yep. done that as well.
            Still not working.
            I’ll keep digging…

  • Akhyar Sadad

    Hey you really made my day..!!! That saves me a lot of time to learn from scratch.
    How can i add forgot password and email that password to the registered user. any pointer?

  • dmitry

    hello, nice tut…

    one question, does passport-local goes to DataBase every time it need to deserialize? this means it goes two times on every authenticated page request? Isn’t that bad?

    • http://scotch.io/ Chris Sevilleja

      It wouldn’t hit the database to get the information. The info is serialized and deserialized from the session so no database hit.

      http://passportjs.org/guide/configure/ Scroll to the bottom bit about sessions on the official docs.

  • Kien

    I deployed this app to heorku server. It crashed. Any thought? It work fine locally

  • azeem

    Hey Scothy , many thanks for ur time and tutorial … can u please upload a new tutorials including google drive and gmail authtication using passport node module… that could very usefull.. we dont a have good example for google drive upload example… even google doc is not very helpfull for google drive

  • MC

    This was SO helpful, thank you so much for the clear step by step in depth explanation! I’m new to node and web development generally and this may be one of the best posts I’ve come across. Keep up the good work.

  • Gonchar Denys

    Hello, i have one small question, how can i read that messages in routes.js?

    // 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

    • http://scotch.io/ Chris Sevilleja

      Don’t use req.flash. Just throw an object in there with the data you need: return done(null, false, {message: 'No user found.'})

      Then you can use that with a custom callback. Scroll down to custom callback at the docs.

      http://passportjs.org/guide/authenticate/

  • Kimmy Chan

    Advertisement spam. This guy is the co-founder of Userbin.

  • TheCraccer91 .

    Thanks a lot for your turtorial, I love it!

  • Julian Suttner

    Great Tutorial. Helped me so much!

  • M Yusuf

    First of all, awesome article Chris. Have read your other articles on Node and Express too ! Really informative.
    My question is: In the passport.js fle, you use process.nextTick() and you have given a reason for it too.
    I could not understand exactly why you used it.. I tried the code without it and it worked fine. Also, you have not used it in the login strategy.
    Could you explain further, in layman terms, exactly what is process.nextTick()’s advantage ?

  • brentchow

    Is this tutorial going to be updated for Express 4.0?

    • http://scotch.io/ Chris Sevilleja

      Yes I’m looking at what changes are necessary for Express. I think the main changes are how to configure passport (using the middleware in server.js) and what effect it has on the routes.

      Thinking I’ll just add another section to this tutorial on upgrading since changing out the current articles would be a little complicated.

      • fohtoh

        Awesome, that would be very helpful.

        • nishant

          Here is the version that works with 4.0. I use handlebars so if needed you need to change the view engine.
          // server.js

          // set up ======================================================================
          // get all the tools we need
          var express = require(‘express’);
          var app = express();
          var port = process.env.PORT || 3001;
          var mongoose = require(‘mongoose’);
          var passport = require(‘passport’);
          var flash = require(‘connect-flash’);
          var logger = require(‘morgan’);
          var cookieParser = require(‘cookie-parser’);
          var bodyParser = require(‘body-parser’);
          var exphbs = require(‘express3-handlebars’);
          var session = require(‘express-session’);

          var configDB = require(‘./config/database.js’);

          // configuration ===============================================================
          mongoose.connect(configDB.url); // connect to our database

          // require(‘./config/passport’)(passport); // pass passport for configuration

          // set up our express application
          app.use(logger(‘dev’)); // log every request to the console
          app.use(cookieParser()); // read cookies (needed for auth)
          app.use(bodyParser()); // get information from html forms

          app.engine(‘handlebars’, exphbs({defaultLayout: ‘main’}));
          app.set(‘view engine’, ‘handlebars’);

          // required for passport
          app.use(session({ secret: ‘ilovescotchscotchyscotchscotch’ })); // session secret
          app.use(passport.initialize());
          app.use(passport.session()); // persistent login sessions
          app.use(flash()); // use connect-flash for flash messages stored in session

          // routes ======================================================================
          require(‘./app/routes.js’)(app, passport); // load our routes and pass in our app and fully configured passport

          // launch ======================================================================
          app.listen(port);
          console.log(‘The magic happens on port ‘ + port);

      • fohtoh

        Just curious if you had an ETA on when you would do that?

        • http://scotch.io/ Chris Sevilleja

          Not entirely sure. I think there are some compatibility issues with Express 4 and Passport. Can’t really do much till that’s fixed I guess.

  • BalaSubrahmanyam

    Hey Thanks for such Beautiful code ..! Can U help Me out !! By sharing the ChangePassword ! thing ..! Please !

  • http://danielfs.github.io Daniel Fernandes Silva

    Hi! I was trying the first command “node server.js” at Application Setup section and I faced the error described in this image (https://www.dropbox.com/s/uyt0tzfz4nwzthi/snapshot1.png). It’s my first tutorial about node.js and I can’t understand it. Does anyone help me? Thanks.

  • John K

    Hey Chris, your article is golden, but I have 2 questions!

    1) Do you plan to write an article about socket.io and combine ALL those authentication methods with websockets?

    2) If not I need to know what your suggestion is to me about the following:
    is it better to keep using sessions like you did above – or should I use tokens with websockets, like this article suggests (https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/) ?

    p.s1: I plan to use websockets with a mobile app – !
    p.s2: I’m totally new to node.js
    Thank you

    • http://scotch.io/ Chris Sevilleja

      1. socket.io articles are in the pipeline. socket.io and this much authentication is probably a while away. still have to get through some basic socket.io articles and then authentication articles like node and tokens, mean stack authentication.

      2. That’s a good resource. I think tokens are definitely the way to go. All the great companies that go that route can’t be wrong!

      Keep going with Node and good luck with your mobile app. You’re on the right track.

      • John K

        Great, thanks for your reply :)

        Would it be much to ask you a generic idea of how to tweek your code to make it use tokens instead of sessions?

        • http://scotch.io/ Chris Sevilleja

          Not at all. That’s one of the next articles in the list. When work dies down soon, I’ll start writing that one up.

          • https://github.com/SudoPlz John K

            If you do that it would be great to use https://github.com/primus/primus (primus) with which a user can use either sockJS (the best), engine.io or socket.io.

  • Ubaldo

    Hi, Great tutorial! I followed everything but I figure out that the logout link doesn’t work… I also tryed adding req.session.destroy() just above the req.logout() but nothing work… I cannot delete the session… Do you know how to handle on it? Cheers!

    • Ranji

      Were you able to solve this issue ???

  • Pingback: Updates & Top Posts Related to Our Work @ Deconstructed | Deconstructed

  • Jindrich Vavruska

    Nice tutorial, although it did not quite work for me. I am a newbie and so all npm modules I have installed by default are the newest versions, hence express configuration has to be quite different. It would be nice to mention somewhere in the beginning that the differences between express 3 and express 4 are significant, just to avoid confusion and warn a beginner that they need to pay attention to these differences.

  • Jesús Mur

    I would like to add some information like first name or last name, how can I do it? thanks, great tutorial.

  • Pingback: nodeJS: websockets chat with authentication - Tech Forum Network

  • @d_varlamov

    Thank you for amazing work!

  • Oron Ben Zvi

    Hi Chris, just another feedback:

    I see that on your tutorials you’re not consistent when requiring your own modules,

    sometimes it’s:require(‘./config/database.js’);

    and sometimes it’s without ‘.js’ like this: require(‘./config/database’);

    personally i like the non-extension style because it feels more like a module than a file, but whatever approach you choose, I recommend stay with one to prevent audience confusion (:

    • http://scotch.io/ Chris Sevilleja

      Hey Oron. I too prefer the non-extension style. Using the .js was a remnant from when I first started getting into Node (not very long ago at all). Moving forward I’m definitely going with the non-extension way. Thanks.

  • Oron Ben Zvi

    Hi Chris,
    question: why do use the bcrypt.hashSync and bcrypt.compareSync methods instead of the async ones? why have you created blocking code when you could avoid that? any special reason for that?

    • Oron Ben Zvi

      I’ve refactored the code a bit to async

      // user.js —————————————————-

      // generating a hash

      userSchema.methods.generateHash = function(password, next){

      bcrypt.hash(password, bcrypt.genSaltSync(8), null, next);

      };

      // checking if password is valid

      userSchema.methods.validPassword = function(password, next) {

      bcrypt.compare(password, this.local.password, next);

      };:

      //passport.js ——————————————————————–

      1.

      // set the user’s local credentials

      newUser.local.email = email;

      newUser.generateHash(password, function(err, hash) {

      if (err)

      return done(err);

      newUser.local.password = hash;

      // save the user

      newUser.save(function(err) {

      if (err)

      return done(err);

      return done(null, newUser);

      });

      });

      2.

      if (!valid)

      return done(null, false, req.flash(‘loginMessage’, ‘Oops! Wrong password.’));

      // all is well, return successful user

      return done(null, user);

      • http://scotch.io/ Chris Sevilleja

        This is great. Thanks. You should definitely use the async method. That was an oversight on my part.

  • Giuseppe D’Amico

    Hi great tutorial, I have aproblem and a question for you, why from the login page to the server the password is send in clear? I have troble with req.flash I cannot make it working

  • Evaldas Buinauskas

    Hey there again. I was wondering if it’s possible to get Google profile picture using passportjs? Everything I found was Facebook-only related.

    • http://scotch.io/ Chris Sevilleja

      Sorry for the super late response. Try to console.log the profile and see the data that comes back. From the passportJS docs: http://passportjs.org/guide/profile/

      There is a section for photos. Maybe that will have the image you need in there?

  • Tarun Sukhu

    Excellent Tutorial Chris !

    The step by step details makes it very easy to follow and build on .. I was able to use this as a base in my project as well and extend it to my requirements. This can be viewed at https://github.com/tsukhu/rwd-spa-alljs-app . the additions being Express 4.x , Jade instead of EJS , Added rememberme functionality with session storage.

  • Tj Moore

    Maybe I am not understanding this correctly, but after a user creates their profile, can passport be used to edit their credentials? Any help with this is much appreciated. Thanks.

    • http://scotch.io/ Chris Sevilleja

      Hey sorry for the late response. From what I see, it looks like Passport only lets you authenticate and check information. To edit their information on the respective social sites is out of the scope of the functionality that Passport provides.

      You can always store the information any way you want in your databases and let the users edit all that information whenever they want however.

  • CCaldera500

    Great tutorial. Many Thanks for posting this.
    I added a form on the profile page to allow users to add an ‘age’ to the profile. So the my question is, how would I add data to the database that is not used by passport?
    Here is the code I tried:
    app.post(‘/addage’, function( req, res ) {
    User.findById( req.params.id, function ( err, user ) {
    user = req.user;
    user.update( {
    id : req.params.id,
    local.skill : req.body.age
    });
    res.redirect(‘/profile’);
    });
    });

    Thanks!

  • http://dworzanski.com/ Tom Dworzanski

    Thank you for using a key derivation function (bcrypt) for securing the passwords in the database. There are many tutorials online that miss this critical step and it’s good to see someone doing it right.

  • Piotr Rojek

    Hi! This tutorial is awesome, just needs an update for Express 4.2 :-)
    I have a question. Can I translate it to polish and publish it on my new blog about Node.js? The original links and credits would be posted, of course.

    Cheers!

    • http://scotch.io/ Chris Sevilleja

      Hello so sorry for the late response. Ill update the article soon but please feel free to translate and publish. Everything we post is for learning and the community so you wanting to post thisis awesome!

  • Dan

    this is an awesome tutorial! Unfortunately I need to use MySQL instead of mongoose, and I’m a bit of a beginner. I’ve been scouring the web and all the other tutorials are over my head. I’d love it if you could do a follow on tutorial using MySQL for this same project.

  • Pingback: Programmierblog von Johannes Dienst » Nodejs-Tutorial Teil 5: Echte Authentifizierung

  • Pazinio

    Great article, elegant and clear. thanks!

    I’d be glad to have your advice about some question:
    as a node beginner (and web principles in general) I’m trying to understand the right way to integrate this easy node authentication solution for google plus (sessions and cookie based) with my mobile client (android based). I’ve added the Google Plus SDK for android and I successfully passed the authentication step from my mobile app (directly to google plus), now I hold user google Token, my question is, what are the next steps? should I send GET request with the token as cookie to /auth/google? maybe /auth/google/callback?

    Thanks in advance for your reply.

  • aforty

    Really helpful tutorial, thank you! I had been struggling for a while to understand all the passport components and strategies before coming across this.

  • http://www.joshcanhelp.com joshcanhelp

    Hey there … thanks so much for the tutorial, everything works as it should after making a few changes to use Handlebars instead of EJS and upgrading the middleware code for Express 4.

    I did have a question … if I try to login with one or both fields empty, I’m kicked back to the login page (as expected) but no error message. If I try a console.log in the local-login strategy, it never reaches that block unless it has both fields present. That means I can’t do a “Please fill out both fields” error. In app.post for /login, I wrapped passport.authenticate with a function so I could do a little extra logic but I’m not sure how to replicate the failureRedirect along with a flash message.

    Any idea how I can accomplish this? Thank you!

  • Mohanavigneshwaran A

    Hi,
    After the Application setup, I am trying to run the server.js like you have mentioned but i am getting an error like “Failed to connect to [undefined:27017]” Please find the full error message below. For your information, mongodb is up and running. I have followed the steps from the official website to install it. Please help me with this!

    $ node server.js
    connect.multipart() will be removed in connect 3.0
    visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
    connect.limit() will be removed in connect 3.0
    Application listens to the port:3000
    events.js:72
    throw er; // Unhandled ‘error’ event^

    Error: failed to connect to [undefined:27017]
    at null.(/home/vigneshmoha/Documents/node/branding/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:546:74)

    at EventEmitter.emit (events.js:106:17)
    at null. (/home/vigneshmoha/Documents/node/branding/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:150:15)

    at EventEmitter.emit (events.js:98:17)
    at Socket. (/home/vigneshmoha/Documents/node/branding/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js:533:10)

    at Socket.EventEmitter.emit (events.js:95:17)
    at net.js:833:16
    at process._tickCallback (node.js:419:13)

    • Mohanavigneshwaran A

      Sorry. My bad! I resolved it. I haven’t provided the db server path in the database config file and also i haven’t really noticed that “Undefined” part in that error.

  • Erik

    Why is the salt not stored in the data base with the password? It seems that the salt is the same for everyone, generated by one number, 8. bcrypt.genSaltSync(8)? Am I missing something?

    • Scott Martin

      Bcrypt creates a password digest that is a combination of the password hash and the salt used to create the hash. Bcrypt separates the two when it tries to verify that the password matches a given digest. It will automatically create a new salt every time it creates a new hash. I suspect the only reason the author uses genSaltSync manually is to control the strength of the hash. Bcrypt-nodejs uses a default strength of 10 and in the example it is 8. You can check out the API for bcrypt-nodejs at https://github.com/shaneGirish/bcrypt-nodejs.

  • http://michaelcalkins.com/ Michael Calkins

    Loved this! Everything worked first try with some modifications for Express4! Ty :)

  • Gattermeier

    This is fantastic. I implemented this with Express 4 and Angular.js. I only have an issue communicating error responses and user information from the routes (or the .isLoggedin middleware) back to angular. Although I am getting the hang of it really quickly, I consider myself still very much a noob. Any advice, directions, good sample code?

  • Pingback: Upgrading Our “Easy Node Authentication” Series to ExpressJS 4.0 ♥ Scotch

  • KC

    I’m having a hard time at the Database Config part:

    module.exports = {

    ‘url’ : ‘your-settings-here’ // looks like mongodb://:@mongo.onmodulus.net:27017/Mikha4ot

    };

    The Mongo URI I got was mongodb://:@novus.modulusmongo.net:27017/guqu3niT

    and I tried doing it like:

    module.exports = {

    mongodb://kc:[email protected]:27017/guqu3niT

    };

    and a bunch of other ways but it still won’t work. The error I’m getting is:

    C:UsersKCServer3configdatabase.js:7

    };

    ^

    SyntaxError: Unexpected token }

    Thanks for any help.

    • Noam

      Looks like you’re missing the key (‘url’, or anything you like) to your value:

      module.exports = {

      url: ‘mongodb://kc:[email protected]…:27017/guqu3niT’

      };

  • George Portillo

    Hello Chris,

    First of all, thanks for this tutorial. It has helped me understand a lot regarding mongodb.

    To the point… Sometimes users might not want to specify the “email” field when they’re trying to log in using Facebook. You should first check if the email property is undefined. Like so (mainly for users who don’t know how to fix it):

    In the passport.js file, around line 158 – you can do something like this.

    if(typeof profile.emails === “undefined”) {
    newUser.facebook.email = “”;
    } else {
    newUser.facebook.email = (profile.emails[0].value || ”).toLowerCase();
    }

  • Muhammad Saleh

    WOOOOOOW !!!!!!!
    This is AMAZING it’s been ages since I’ve seen a professionally written tutorial like this one
    I can’t tell you how grateful I am
    I was looking for such tutorial which combines Express 4 and Passport and couldn’t find any

    Your tutorial didn’t teach me how to use these modules only NOOOOO your tutorial taught me how to even write neat Node.js apps

    Thank you so much

  • Meriem

    Hi, thanks for this amazing tuto, but when i try to install the list listed on package.json, i get some errors, one of them (error package.json must be actual JSON, not just JavaScript.). In other case, i have created the file with an extension . json,. Could you please tell me which is the cause of this error ? And how can i solve it ?

  • Andressa

    Hi Chris, I dont know if I didn’y find, but , how do you know that it is the same user if he uses different accounts and the accounts have different info? I mean, if I had it stored already, it would be easy. But the fact is the first log in in each account, how do you know is the same user? Can you point me the part you do that?

    Thank you. Your articles are very good.

  • Noam

    Love this tutorial! Thank you so much.
    I pretty much implemented the code exactly how you did here (with some updates for using express 4). I’m having a problem, when trying to signup a user it tries to redirect to a page called ‘/authenticate’ (and returns a 404 because that page doesn’t exist). I check my db and it never inserted the user info (and I know the connection to the db was established). I can’t figure out what I’ve been doing wrong. Any ideas? Thanks.

  • Shiroi Kamei

    Hi. Thanks for this beautiful post. I’m just wondering about the database. Seeing you created the database using mongoose (mongodb included) easily makes me feel a little curious about what happened. One stupid question, how did you make the collection “users” for this webapp? I’ve been looking at your code for hours but I can’t find a single clue about it.

  • MikeyP

    Hey man, I’m trying to work my way through this tutorial. I’m having trouble firing it up after setting up the modulus DB. I’m getting an error MongoError: auth fails. I’ve copied the URL from modulus to the MongoDB, I’ve tried subbing in a user name and password for and and getting the same error. Any thoughts?

  • Bondi French

    Hi Chris,
    great tutorial! I made it working using Postgres and the ORM Sequelize, one thing that I don’t understand is in your ‘app/route.js’ in the last part isLoggedin function, where does req.isAuthenticated() come from? is that from Passport.js or Express? or elsewhere? because I don’t see it defined anywhere. Thx

  • Zhen Zhang

    Hi, Thanks for your awesome post! But I have a problem when I try to add a “set password” feature on it.

    passport.use('local-setpwd', new LocalStrategy({
    usernameField : 'email',
    passwordField : 'password',
    passReqToCallback : true
    },
    function(req, email, password, done) {
    var user = req.user;
    user.local.email = email;
    user.local.password = user.generateHash(password);

    user.save(function(err) {
    if (err)
    throw err;
    return done(null, user);
    });
    }));


    This is the code I suppose to take effect. But it doesn’t. It will always get back to ‘failureRedirect” Status.

    Would you please make a little enhanced-version with this feature?

    Thanks!

  • Pingback: update bcrypted pass node js and mongoose | Unlimitedtricks

  • Pingback: update bcrypted pass node js and mongoose