Wednesday, October 29, 2014

Passport Authentication For Local Strategy - Node.js With Express Framework & Mongoose Database

Registration/Login is famous part in Web Based Application to enable User Privacy and track their records and Changes made.This is Easy in PHP -where i have written already Three post regarding login system for web Application.However in node.js it is quite easy for us to implement in faster manner.Passport.js comes here to help us in different strategy for implementing authentication system and integrate with Database and Session.

Passport.js module is well matured module which is used to Authenticate existing user and create new user for corresponding Strategy.here Strategy is nothing but simply just a way of authentication using username/password.



Reference : Download |  Demo 

Installation :

Before starting this module, i would like to go through some of My Last post on basic articles in node.js
C:\> npm install passport -g

This will install passport module globally in your local machine.however there are lot of strategy.we are going to use local-strategy.

App structure :

App structure is general where we would have a ,

1) models [directory]  - contains models => models.js(structure of Database) 
2) config[directory] - contains database connection url and passport.js Logic and functions.
3) view[directory] - our Front end to parse messages and display written with Templating Language (we have used EJS template)

here we are going to use express.js for our convenience to manage routes.

passport.js

Lets start with Passport.js logic and Working.Generally this is a strategy authenticating a user with Username and Passwords.where they are stored in a database.after successful authentication we are setting sessions and redirecting the user to the Dashboard/profile.And we maintain sessions wherever we need to protect the access.

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

 var User = require('../models/model');
  module.exports = function(passport) {
    passport.serializeUser(function(user, done) {
        done(null, user.id);
    });
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
     });



In the Above Code we have just initialize user from model schema of Database and passport as Local strategy.
I have used the module.exports to make seperate files in order to easily maintain the code and understanding.however it is connected to the server.js where we export the module.
serialize and deserialize is commonly used to deal with sessions handling.Stackoverflow answer is easy to understand,what does the abvove two function does.check it here

Creating and Naming a LocalStrategy:

 passport.use('signup', new LocalStrategy({
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true 
    },
    function(req, email, password, done) {

        User.findOne({ 'users.email' :  email }, function(err, user) {
            if (err)
                return done(err);
            if (user) {
                return done(null, false, req.flash('signupError', 'Email is already taken.'));
            } 
            else {
       var newUser            = new User();
                newUser.users.email    = email;
                newUser.users.password = password; 
                newUser.save(function(err) {
                    if (err)
                        throw err;
                    return done(null, newUser);
                });
               }
        });
    }));


By the above functionality we are creating a localstrategy named signup for user registration.Generally for basic Signup we need username/Email with password is allowed in passport.js but we could inspect additional parameters by passing to callback the req object,so when you submit the form the additional params can be obtained from req object.check for additional form fields passing for passport.js.Since we explicitly make the passReqToCallback : true option we could pass the req object and inspect it inside the passport.js function.

And the next step is to query the Database for the existing user and return either done with error or success message to set the session.

we are querying the user document and getting out the object as user and if it exist we pass it as an error to flash a Error message.Else create a new Object with the Database schema and populate the Database accordingly and invoke done with user object to set the session.

Login Strategy :

here we are just naming and creating a simple login functionality to authenticate the user to use the service and set the session.


  passport.use('login', new LocalStrategy({
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true 
         },
    function(req, email, password, done) { 
        User.findOne({ 'users.email' :  email }, function(err, user) {
            if (err)
                return done(err);
            if (!user)
                return done(null, false, req.flash('loginError', 'No user found.try Again'));               if(user.users.password != password)
               return done(null, false, req.flash('loginError', 'Password Error.try Again')); 
            
            return done(null, user); 

        });

    }));


In the above Strategy we defined as login and passing our Username/Email and Password,btw we could overrride and passreqcall back to use additional form fields via req object as said before.However here query on mongoose matters here.
we are finding only one record containing email/username and getting out the object as user as return from database.However we need to check the object because in mongoose,if no record is returned by database then the object would be null, so that we verify with if clause statements and Authenticate the user and set the session or flash the error message.

user.js(models) : 



 var mongoose = require('mongoose');
 var user = mongoose.Schema({
    users            : {
        email        : String,
        password     : String
  }
  });
  module.exports = mongoose.model('User', user);


A simple Mongoose scheme for Database.have a look below.Local for email and password.verify to check the user via Email.We would cover this Email Verfication for User later.

Define Routes Using Express : 

now let us create some Express route to handle the request from user and serve the view part.I am writing the Routes directly in Server.js file , you can to export the module and write and load as separate file.here passport.authenticate function is called to take care of the verification strategy.



  app.get("/",isLoggedIns,function(req,res){
res.render("index.ejs",{ message: req.flash('loginError') });
  });

  app.post("/login",passport.authenticate('login', {
successRedirect : '/profile', 
failureRedirect : '/',
failureFlash : true 
}));

  app.get("/signup",isLoggedIns,function(req,res){
res.render("signup.ejs",{ message: req.flash('signupError') });
  });

  app.post("/signup",passport.authenticate('signup', {
successRedirect : '/profile', 
failureRedirect : '/signup',
failureFlash : true 
}));
  app.get("/profile",isLoggedIn,function(req,res)
  {
res.render("profile.ejs",{user : req.user });

  });

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

  app.get("/*",function(req,res){
res.render("404.ejs");
  });

  function isLoggedIn(req, res, next) {

if (req.isAuthenticated())
return next();
res.redirect('/');
   }

   function isLoggedIns(req, res, next) {

if (req.isAuthenticated())
res.redirect('/profile');
else
return next();
   }



Few Words About EJS and Connect-Flash : 

Connect flash is used to flash the Error/Success message between the Authentication Passport and User.just the Error message (user defined) to the User Display.
Ejs Template is generally used for displaying our views as HTML and parsing the values as JSON and displaying it in front end dynamically.Learn more about EJS here.
Sample view index.ejs to parse the Error in Login :



      <div class="col-sm-12">
    <% if (message.length > 0) { %>
        <div class="alert alert-danger"><%= message %></div>
    <% } %>
       </div>

Database Connection and Establishment:

Learn Here to create Modulus.io Database and set up Remote Connection in my past post.

module.exports = {
  
   'url' : 'mongodb://username:[email protected]:27017/abs' 
   
    };

About Security and Validation : 

I haven't verified any SQL injection for this Above Post,however you can use some packages to verify SQL injections and Execution commands that lets the server to open to Attack.Generally when you use eval() command,it gives hackers a well opportunity to Down the server and Application.i have escaped all the inputs provided by the user here.

Note:
Download the Code provided and Work it out.The given Code doesn't suits for production mode,here you can do lot of development works and make ready for production mode.Security is more concern for node.js because of exec() command.try to validate the user inputs and escape it and use it in your operations and perform Database operation.

Note For Downloading code :
If your downloading the code,

  • update the Credentials of Database in database.js file.
  • npm install the packages in your folder using package.json file given.
  • I have used Express session ,you can change the Session secret to implement in your projects.
  • to run execute node server.js command once you get into directory.

For Errors/Suggestions/Clarification/improvements/bugs drop mail to [email protected] .or connect/chat with me Facebook/twitter/G+ hangouts for errors/help/Bugs.Share is care.Do comments.

0 comments:

Post a Comment

feel free to post your comments! Don't Spam here!