NodeJs: Local Authentication Using PassportJs

Posted By Nisheet Sharma | 28-Feb-2018

PassportJs is a middleware that can be used to perform authentication, using different methods.

Some commonly used methods:

  1. Local Authentication : Which we can configure ourselves.
  2. Google: OAuth Authentication using Google Accounts
  3. Facebook: OAuth Authentication using Facebook Accounts
  4. Twitter: OAuth Authentication using Twitter Accounts

Each method is separately packaged, so PassportJs lets us choose which method/methods to use.

And install only those method/methods that we want/require for our application.

Its easy to add/remove the different methods, without any unwanted complex dependencies.

Steps to Install:

1. Install Passport module: npm install passport

2. Install the method/strategy you want to use in the application, I am using local authentication here: npm install passport-local

 

First lets configure, the local authentication as we want.

 

        //Require the passport module
        const passportjs = require('passport');
        //Require the passport-local module
        const LocalAuth = require('passport-local').Strategy;

        /*
            Now we set-up our custom validation logic for authentication.
            PassportJs automatically searches the request payload for credentials and passes them as arguments for the callback function.
            By default, PassportJs will use username, password as credentials, and search for them in the request's payload.
            Lets assume our custom request payload to be as follows: 
            {
                "email" : "email@mail.com",
                "password" : "somepassword"
            }
            One more argument that PassportJs passes to the callback is done.
            done is PassportJs's internal callback function, which takes the following arguments:
                done (error, userObj, info)
                error :  Use this to signal PassportJs that there was an error while validating user's authority
                userObj: Use this to pass the user's object/document as per your application logic if authentication was successful.
                         Otherwise, pass false to signal to PassportJs that authentication has failed.
                         PassportJs will automatically append this userObj to the incoming request afterwards, when the authentication process is completed.
                info :   This is an optional parameter you can use to forward any custom message for information, like why did the authentication fail.
        */
        var authenticationCheck = function(email, password, done) {
            //Assume we have a User model in our application that stores all the user's data.
            //Lets find if the email supplied in the request payload exists in our database or not
            User.findOne({ email: email },
                function (err, userObj) {
                    
                    if (err) { 
                        //If we encounter an error, signal that to passport using done(err)
                        return done(err); 
                    }
                    if (!userObj) {
                        /* 
                            Check whether the userObj is undefined
                            If undefined, it means the userObj does not exist in our database.
                            So, we'll signal to PassportJs that user authentication has failed, and send a custom message for information
                        */
                        return done(null, false, { message: 'Email address does not exist!' });
                    }
                    if (userObj.password != password) {
                        /* 
                            For simplicity, I have shown a direct check for passwords, you can use some encryption logic of your own for better security.
                            Check whether the password matches or not.
                            If it does not, signal a failure response to PassportJs as follows.
                        */
                        return done(null, false, { message: 'Wrong password!' });
                    }
                    //Finally, if all is good return the user details with userObj
                    return done(null, userObj);
                }
            );
        };

        //Create a new Local Strategy method, and pass our custom authentication function as argument
        //Also, because we are setting custom credentials as email and password, we will have to signal that as well as shown below.
        var localAuthenticationStrategy = new LocalAuth({ usernameField: 'email', passwordField: 'password'}, authenticationCheck);

        //Signal passport module to use our local strategy for authentication
        passportjs.use(localAuthenticationStrategy);
    

For applications that are using Express, you will need to add the following line of code in your app as well:

app.use(passportjs.initialize());

So, that PassportJs's module is initialized.

Now, to use authentication for any route, just do the following:

        app.get('/home',    //Your custom route
            passportjs.authenticate('local'), //Pass local as argument to the passportjs's authenticate function, for local authentication checks
            function(req, res, next) {  //Your custom request handler
                //The User's obj will be automatically appended to req after authorization as req.user, so you can use it here.
                doSomething(req.user, res);
            }
        );
    

By default, if the authentication fails, passportjs automatically sends a 401 Unauthorized response, if authentication is successful, it calls the next function in line.


Request for Proposal

Recaptcha is required.

Sending message..