# Node.js Authentication using Passport.js


Check the source code here

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1621505254141/kNZfFlS-m.jpeg)

Authentication is an important portion for web application. From client side, like a mobile application must require a secure authentication to the server and [***passport](http://passportjs.org/)*** is a prominent helper.

Here I’m developing a simple oAuth(open authentication) application and show how to secure routing.

## Work-Flow

* Two routes will be available: guest, user

* The /guest routes can be accessed by anyone

* The /user routes can be accessed by the authenticate users

## REQUIREMENTS

1. [***Node.js(6.x)](https://nodejs.org/en/)***

1. [***NPM(3.x)](https://www.npmjs.com/)***

1. [***Express.js(4.x)](https://expressjs.com/)***

## APP SETUP
> Dependency

Make your directory and inside the directory, create a file named **package.json**

```
mkdir myPassportAuthentication
cd myPassportAuthentication/
touch package.json
```


Paste the following code in your **package.json** file:

```
{
  **"name"**: **"my-passport-authentication"**,
  **"main"**: **"server.js"**,
  **"dependencies" **: {
    **"express"**: **"~4.14.0"**,
    **"mongoose"**: **"~4.6.1"**,
    **"passport"**: **"~0.3.2"**,
    **"passport-local" **: **"~1.0.0"**,
    **"bcrypt-nodejs" **: **"latest"**,
    **"morgan"**: **"~1.7.0"**,
    **"body-parser"**: **"~1.15.2"**,
    **"cookie-parser"**: **"~1.4.3"**,
    **"method-override"**: **"~2.3.6"**,
    **"express-session"**: **"~1.14.1"
  **}
}
```


To download the dependencies, run

```
npm install
```


So our entry point is the **server.js**
> Server

Lets create the **server.js** in the same directory.

```
touch server.js
```


Now paste the following code in **server.js**

```
*// server.js

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

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

*// router files ===============================================================
***var **authRoutes   = require(**'./routes/auth'**);
**var **testRoutes   = require(**'./routes/test'**);

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

*// 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.**json**()); *// get information from html forms
*app.use(bodyParser.**urlencoded**({ **extended**: **true **}));

*// required for passport
*app.use(session({
    **secret**: **'eminem'**, *// session secret
    ***resave**: **true**,
    **saveUninitialized**: **true
**}));
app.use(passport.initialize());
app.use(passport.session()); *// persistent login sessions

// routes ======================================================================
*app.use(**'/auth'**, authRoutes);
app.use(**'/test'**, testRoutes);

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

> Routes

Create two routing files,

```
mkdir routes
cd routes
mkdir auth
mkdir test
cd auth
touch index.js
cd ..
cd test
touch index.js
```


From the both routing file

* ./routes/auth/index.js

* ./routes/test/index.js

Export the router module.

Paste the following code on the both file:

```
**var **express = require(**'express');
var **router = express.Router();

module.exports = router;
```

> Database

Now time to configure database. Follow the following commands:

```
mongo
use myPassportAuth
```


So our database is created, now create the config file and put database info:

Go to the project root directory and

```
mkdir config
cd config
mkdir database
touch index.js
```


Inside the **./config/database/index.js **paste the following code:

```
*// config/database.js
*module.exports = {
    **'url' **: **'mongodb://localhost/myPassportAuth'
**};
```

> Passport

Go to the root directory and follow the command:

```
cd config
mkdir passport
cd passport
touch index.js
```


Now paste the following code to the **./config/passport/index.js**

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

**var User       **= require(**'../../models/user'**);

**var ***myLocalConfig *= (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 LOGIN =============================================================
    // =========================================================================
    *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 in the req from our route (lets us check if a user is logged in or not)
        *},
        **function**(req, email, password, done) {
            **if **(email)
                email = email.toLowerCase(); *// Use lower-case e-mails to avoid case-sensitive e-mail matching

            // asynchronous
            *process.nextTick(**function**() {
                **User**.findOne({ **'local.email' **:  email }, **function**(err, user) {
                    *// if there are any errors, return the error
                    ***if **(err)
                        **return **done(err);

                    *// if no user is found, return the message
                    ***if **(!user)
                        **return **done(**null**, **false**);

                    **if **(!user.validPassword(password))
                        **return **done(**null**, **false**);

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

        }));

    *// =========================================================================
    // LOCAL SIGNUP ============================================================
    // =========================================================================
    *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 in the req from our route (lets us check if a user is logged in or not)
        *},
        **function**(req, email, password, done) {
            **if **(email)
                email = email.toLowerCase(); *// Use lower-case e-mails to avoid case-sensitive e-mail matching

            // asynchronous
            *process.nextTick(**function**() {
                *// if the user is not already logged in:
                ***if **(!req.**user**) {
                    **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**);
                        } **else **{

                            *// create the user
                            ***var **newUser            = **new User**();

                            newUser.local.**email    **= email;
                            newUser.local.**password **= newUser.generateHash(password);

                            newUser.save(**function**(err) {
                                **if **(err)
                                    **return **done(err);

                                **return **done(**null**, newUser);
                            });
                        }

                    });
                    *// if the user is logged in but has no local account...
                *} **else if **( !req.**user**.**local**.**email **) {
                    *// ...presumably they're trying to connect a local account
                    // BUT let's check if the email used to connect a local account is being used by another user
                    ***User**.findOne({ **'local.email' **:  email }, **function**(err, user) {
                        **if **(err)
                            **return **done(err);

                        **if **(user) {
                            **return **done(**null**, **false**);
                            *// Using 'loginMessage instead of signupMessage because it's used by /connect/local'
                        *} **else **{
                            **var **user = req.**user**;
                            user.**local**.**email **= email;
                            user.**local**.**password **= user.generateHash(password);
                            user.save(**function **(err) {
                                **if **(err)
                                    **return **done(err);

                                **return **done(**null**,user);
                            });
                        }
                    });
                } **else **{
                    *// user is logged in and already has a local account. Ignore signup. (You should log out before trying to create a new account, user!)
                    ***return **done(**null**, req.**user**);
                }

            });

        }));
};

module.exports = *myLocalConfig*;
```


## Model

Again go to the root directory and follow the commands

```
mkdir models
cd models
mkdir user
cd user
touch index.js
```


Paste the following code and make the user model:

```
*// load the things we need
***var **mongoose = require(**'mongoose'**);
**var **bcrypt   = require(**'bcrypt-nodejs'**);

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

    **local            **: {
        **email        **: String,
        **password     **: String
    }
});

*// 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 photographers and expose it to our app
*module.exports = mongoose.model(**'User'**, userSchema);
```


## Boilerplate Completion

Here’s our boilerplate code is ready. Go to the root directory and run

```
node server.js
```

> You must see: “The magic happens on port 8080”

Let’s complete the auth route. Paste the code in **./routes/auth/index.js**

```
**var **express = require(**'express'**);
**var **router = express.Router();
**var **passport = require(**'passport'**);

router.**post**(**'/signup'**, passport.authenticate(**'local-signup'**, {
    **successRedirect **: **'/auth/profile'**,
    **failureRedirect **: **'auth/signup'
**}));

router.**post**(**'/login'**, passport.authenticate(**'local-login'**, {
    **successRedirect **: **'/auth/profile'**,
    **failureRedirect **: **'auth/login'
**}));
router.get(**'/profile'**, *isLoggedIn*, (req, res) => {
    res.**status**(200).**json**(req.**user**);
});
router.get(**'/logout'**, *isLoggedIn*, (req, res) => {
    req.logout();
    res.**status**(200).**json**({
        **'message'**: **'successfully logout'
    **});
});

module.exports = router;

*//route middleware to ensure user is logged in
***function ***isLoggedIn*(req, res, next) {
    **if **(req.isAuthenticated())
        **return **next();
    res.**status**(400).**json**({
        **'message'**: **'access denied'
    **});
}
```


So we are done for **signIn**, **signOut**, **SignUp** and **viewProfile** Section.

## Secure Routing

Here we create two routing, one for the guest and another for the authenticated users.

Go to the **./routes/test/index.js** and it would be like this:

```
**var **express = require(**'express'**);
**var **router = express.Router();

router.get(**'/guest'**, (req, res) => {
    res.**status**(200).**json**({
        **'message'**: **"This is not secured guest routing"
    **});
});

router.get(**'/user'**, *isLoggedIn*, (req, res) => {
    res.**status**(200).**json**({
        **'message'**: **"This is secured user routing"
    **});
});

module.exports = router;

*//route middleware to ensure user is logged in
***function ***isLoggedIn*(req, res, next) {
    **if **(req.isAuthenticated())
        **return **next();
    res.**status**(400).**json**({
        **'message'**: **'access denied'
    **});
}
```


## Congratulation
> # If you have come this far, then congratulation, you implements the basic open authorization using passport js and secure specific routing.

## API Test

We will use postman to check the API.

***Create an user:***
> Request Type: POST
> Headers: { ‘content-type’: ‘application/json’ }
> Address: localhost:8080/auth/signup
> Body: raw

```

{
     “email”: “test[@mail.com](mailto:mail2@mail.com)”,
     “password”: “1234567890”
}
```


In response we will get user id and hashed password:

```
{
  “_id”: “59c7d5f7294b322b0321ad6a”,
  “__v”: 0,
  “local”: {
     “password”:  “$2a$08$varXSszNbVsFH85B3Ewk4.Q4qhXRJBeyDrZNLu7vrlJhoBefpc50S”,
     “email”: “[test@mail.com](mailto:test@mail.com)”
 }
}
```


![](https://cdn.hashnode.com/res/hashnode/image/upload/v1621505256592/5ZyfrBcPo.png)

When we create an user we will be automatically logged in.

Now Let say, A user already exist and wants to logged in,

***Log in an User:***
> Request Type: POST
> Headers: { ‘content-type’: ‘application/json’ }
> Address: localhost:8080/auth/login
> Body: raw

```
{
     “email”: “test[@mail.com](mailto:mail2@mail.com)”,
     “password”: “1234567890”
}
```


In response we will get Logged in user information:

```
{
  “_id”: “59c7d5f7294b322b0321ad6a”,
  “__v”: 0,
  “local”: {
   “password”: “$2a$08$varXSszNbVsFH85B3Ewk4.Q4qhXRJBeyDrZNLu7vrlJhoBefpc50S”,
   “email”: “[test@mail.com](mailto:test@mail.com)”
 }
}
```


![](https://cdn.hashnode.com/res/hashnode/image/upload/v1621505259193/fsnRH7-PX.png)

***Profile of a logged in user:***

To get the information of a logged in user,
> Request Type: GET
> Address: localhost:8080/auth/profile

In response we will get the users profile:

```
{
  “_id”: “59c7d5f7294b322b0321ad6a”,
  “__v”: 0,
  “local”: {
   “password”: “$2a$08$varXSszNbVsFH85B3Ewk4.Q4qhXRJBeyDrZNLu7vrlJhoBefpc50S”,
   “email”: “[test@mail.com](mailto:test@mail.com)”
 }
}
```


![](https://cdn.hashnode.com/res/hashnode/image/upload/v1621505261306/jFHtKBz1g.png)

***Log out of an user:***

To log out from the app,
> Request Type: GET
> Address: localhost:8080/auth/logout

In response we will get the message:

```
{
    "message": "successfully logout"
}
```

> Open authorization is completed here.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1621505263520/IVPQYe33t.png)

## **Securing Routing**

***When user is not logged in,***
> Request Type: GET
> Address: localhost:8080/test/user

```
{
     “message”: “access denied”
}
```


![](https://cdn.hashnode.com/res/hashnode/image/upload/v1621505265982/F9tqWbJ5C.png)
> Request Type: GET
> Address: localhost:8080/test/guest

```
{
     “message”: “This is not secured guest routing”
}
```


![](https://cdn.hashnode.com/res/hashnode/image/upload/v1621505269018/03oZxJroN.png)

***When user is logged in,***
> Request Type: GET
> Address: localhost:8080/test/user

```
{
     “message”: “access denied”
}
```


![](https://cdn.hashnode.com/res/hashnode/image/upload/v1621505272943/Rfp5wFDOE.png)
> Request Type: GET
> Address: localhost:8080/test/guest

```
{
     “message”: “This is not secured guest routing”
}
```


![](https://cdn.hashnode.com/res/hashnode/image/upload/v1621505274717/aMwl7uUa4.png)

## Conclusion

So Here we are, completed the basic open authentication using passport.js in node.js and express.js server. In future I will go through authentication using facebook, google, twitter and like other stuff. Stay tuned and if there is a confusing term or something, response below or create an issue in [***github](https://github.com/bmshamsnahid/passportLocalTutorial)***.
