Express – Authentication with PassportJS

In this blog post we will see how to integrate passportjs with express

Passport is authentication middleware for express. Its very simple, unobtrusive and supports many authentication mechanisms.

To Install Passport

[code]

$ npm install passport -save

[/code]

Basics

Most websites employ a basic username/password login strategy. Lets see how to implement it using Passport.

Passport divides authentication broadly into 3 parts

  1. Authenticator

  2. Authentication Strategy

  3. Session

The Authenticator mainly decides the flow of code, i.e how will authentication error, success be handled. What information goes to session, how to handle db operations on success ,error etc.

The Strategy handles the actual authentication process, i.e facebook authentication, google authentication, user/password based etc.

The Session, handles what data is stored in session and how. This is optional, since many cases might not require session store. e.g API’s require each request to be authenticated.

Username/Password Authentication

Password provide a ‘Strategy’ called local, which can be used for this. To use this install the express session and flash modules as well.

[code]

$ npm install passport-local -save

$ npm install express-session -save

$ npm install connect-flash -save

[/code]

In your app.js file add these

  
var session = require('express-session');
  
var flash = require('connect-flash');

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

app.use(session({secret: 'keyboard cat'}));
  
app.use(flash());
  
app.use(passport.initialize());
  
app.use(passport.session());
  

Do all the above before your routes middleware.

  
passport.use(new LocalStrategy({
      
usernameField: 'email', //your login form input type names
      
passwordField: 'passwd'
  
},
  
function (username, password, done) {
      
console.log(username + 'username');
      
//authenticate only if username is test
      
if (username != 'test') {
          
return done(null, false, {message: 'Incorrect username.'});
      
} else {
         
//dummy user object below
          
return done(null, {
              
id: 1,
              
email: '[email protected]',
              
username: 'test'
          
});
      
}
  
}
  
));
  
passport.serializeUser(function (user, done) {
      
console.log('seralize');
      
console.log(user);
      
//push entire object to session
      
done(null, user);
  
});

passport.deserializeUser(function (user, done) {
      
console.log('de seralize');
      
console.log(user);
      
done(null, user);
  
});
  

In the above code if username is test if allows user to login and stores the entire user object in session.

In your routes file

  
//login form submit
  
router.post('/login',
          
passport.authenticate('local', {
              
successRedirect: '/users/login',
              
failureRedirect: '/users/login',
              
failureFlash: true})
          
);
  

In Your Login Form, i am using express handlebar as view engine

  
<br>
  
{{message}}
  
<br>
  
{{#with user}}
  
Login ID: {{id}}
  
<a href="#/users/logout">Logout</a>
  
{{/with}}
  
<br>
  
<form method="post" action="/users/login">
      
<div>
          
<label>Username:</label>
          
<input type="text" name="email">
      
</div>
      
<div>
          
<label>Password:</label>
          
<input type="password" name="passwd">
      
</div>
      
<div>
          
<input type="submit" value="Log In">
      
</div>
  
</form>
  
  
var express = require('express');
  
var router = express.Router();
  
var passport = require('passport');
  
var flash = require('connect-flash');

//login form route
  
router.get('/login', function (req, res) {
      
console.log(req.user); //if authentication will show object else null
      
res.render('index', {
          
message: req.flash('error'),
          
user: req.user
      
}
      
);
  
});
  
//logout route
  
router.get('/logout', function (req, res) {
      
req.logout();
      
res.redirect('/users/login');
  
})
  

Above we see a session based authentication using password. To modularize your code further you can move all passport code from app.js to a custom middleware as shown here.

Authentication for API

Suppose your are building an api and want every request to be authentication. This is how to do it. Also since no sessions are required, those can be removed. So this would be the entire code in app.js


passport.use(new LocalStrategy({
      
usernameField: 'api_key',
      
passwordField: 'api_secret'
  
},
  
function (username, password, done) {
      
console.log(username + 'username');
      
if (username != 'test') {
          
return done(null, false, {message: 'Incorrect username.'});
      
} else {
          
return done(null, {
              
id: 1,
              
email: '[email protected]',
              
username: 'test'
          
});
      
}
  
}
  
));

app.use('/api', function (req, res,next) {
  
// req.body.api_key
  
// req.body.api_secret
  
// api key and secret should be set in your req body either as a json request payload //or post data
      
passport.authenticate('local', {session: true}, function (err, user) {
          
if (!user) {
              
return res.sendStatus(403);
          
}
          
//authenticated
          
req.user = user;
          
next();
      
})(req, res);
  
});
  

Integrate with MongoDB

To integrate with mongodb we just need to make changes to our strategry


var mongoose = require('mongoose');
  
mongoose.connect('mongodb://127.0.0.1/db');
  
var conn = mongoose.connection;

var user_schema = mongoose.Schema({}, {
      
strict: false,
      
collection: 'user'
  
});
  
var User = conn.model('user', user_schema);
  
user_schema.methods.validPassword = function (password, cb) {
      
return this.model('User').findOne(
              
{
                  
username: this.username,
                  
password: password
              
},
      
function (err, row) {
          
if (row) {
              
cb(true);
          
} else {
              
cb(false);
          
}
      
});
  
};

passport.use(new LocalStrategy({
      
usernameField: 'email', //your login form input type names
      
passwordField: 'passwd'
  
},
  
function (username, password, done) {
      
console.log(username + 'username');
       
User.findOne({ username: username }, function(err, user) {
        
if (err) { return done(err); }
        
if (!user) {
          
return done(null, false, { message: 'Incorrect username.' });
        
}
        
user.validPassword(password,function(valid){
            
if(!valid){
                 
return done(null, false, { message: 'Incorrect password.' });
            
}
        
});

return done(null, user);
      
});
  
}
  
));
  

So above is entire implementation of passport with expressjs. For further details and features visit documentation. Reference Documentation Links : http://passportjs.org/guide/

There are many more authentication strategy like facebook, google, twitter, tumbler, etc which can be seen in their documentation.

excellence-social-linkdin
excellence-social-facebook
excellence-social-instagram
excellence-social-skype