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
[js]
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());
[/js]
Do all the above before your routes middleware.
[js]
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);
});
[/js]
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
[js]
//login form submit
router.post(‘/login’,
passport.authenticate(‘local’, {
successRedirect: ‘/users/login’,
failureRedirect: ‘/users/login’,
failureFlash: true})
);
[/js]
In Your Login Form, i am using express handlebar as view engine
[js]
<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>
[/js]
[js]
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’);
})
[/js]
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
[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);
});
[/js]
Integrate with MongoDB
To integrate with mongodb we just need to make changes to our strategry
[js]
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);
});
}
));
[/js]
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.