API Authentication using Passport JS and JSON Web Tokens.

Shreyam Duttagupta
Aug 27, 2017 · 6 min read

By Shreyam DUTTAGUPTA

Lately, I have been working on a MEAN stack Authentication Application using Node JS, Express & MongoDB in the backend and Angular JS and Bootstrap in the Front. I looked through different kind of authentication techniques and strategies but due to its sheer simplicity, Passport.js using JSON Web Tokens caught by eye.

I will go through step by step process of creating a simple mongoose schema and storing the user data in MongoDB server. Then we will start with API Authentication using bcrypt and JWT.

Prerequisites:

  1. Node JS
  2. MongoDB

Tools:

  1. JSON Web Token Package
  2. Bcrypt Package
  3. Passport package
  4. Nodemon: for monitoring any changes in Node application.
  5. Postman
  6. Atom

Directories: By the end of this article, the directory structure should look like:

STEPS:

1)Package.json and installing dependencies.

After creating directory for the application, we need to create our package.json file by “npm init” command. In this file, we put all the dependencies:

package.json

Now after bringing all the dependencies for our application, we have to hit “npm install” which will setup and install all the modules.

2) app.js file to bring in all the modules.

App.js -1
App.js -2
  • In this file, we bring in all the modules required for our application like express, passport, mongoose and etc. We create the database connection using mongoose.connect().
  • We are using port 3000 so everything will be routed through http://localhost:3000/
  • Homepage: For now, our homepage will show Invalid endpoint because we didn’t add any functionality.
  • This is the file where we initialize the passport middleware using app.use(passport.initialize());
    app.use(passport.session());
    require(‘./config/passport’)(passport);

3) users.js file to define the routes:

users.js -1
users.js -2
  • The above user.js defines 3 routes which are “/profile” for registering the user and adding it to our database using addUser function, “/authenticate” for authentication of the username, password and generating JWT Tokens(explained later) and “/profile” for accessing profile using the JWT token generated in the authenticate module.
  • The underlying process of token generation and functions used will be explained shortly. (“/register” in point 5, “/Authenticate in point 6, “/profile” in point 7).

4)Config file for database: database.js:

database.js
  • Here we are using the mongoose default port 27017 and establishing the connection from app.js file.
  • Make sure your mongod client is running.

5)Defining User Model and Register with user.js:

user.js -1
user.js -2
  • In this file, we create our mongoose schema with the following properties: 1) Name, 2) Email, 3) Username and 4) Password.
  • We also define our functions:-

getUserById() : retrieves user data by ID,

getUserByUsername() : retrieves user data by Username,

addUser(): adds user to the database. We use bcrypt.genSalt() which is generating a random key, used to hash the password. Here we can use Postman to check this:

Open Postman

POST request to http://localhost:3000/users/register

Headers -> Key: Content-Type -> Value: application/json

Body -> raw

Postman screen 1
  • Once you have described all the fields, make sure your mongo client is up and running. Hit send.
  • If it is a success, you will find the below screen:
  • Now, to reconfirm your data being stored in database, you can open your mongo client and do the following:

Now you can see all the entries to your database. We have all the fields and password which is encrypted.

comparePassword(): checks the user's password with the one stored in the database. It will be explained in point 6.

6)API Authentication and Token:

In this part, we initialize the passport.js and define strategies. Check line 39,40,41 of App.js

Here in our config folder, we create passport.js file where we define our JWT Strategy.

passport.js
  • In Passport.js line 12, we use “passport.use(new JwtStrategy(opts, (jwt_payload, done) => {” which defines our JWT strategy. The callback includes payload, which includes user information.
  • We are using our self defined function getUserById() and pass and ID instead of an object.

Now we start working on /authenticate route.

  1. We start by getting the username and password by:
    const username = req.body.username;
    const password = req.body.password;
  2. Now we try to search that user by using getUserByUsername() function. If the user is not found, we show “User not found” message.
  3. If the username is found, now we try to compare the password using comparePassword() function we defined. If matched, we will show success = true i.e. JWT Token is generated(see picture below “JWT Token”).
  4. We can Store the JWT token in the client side in cookies or local storage and request to protected route to include the token within the header (See picture below “JWT Token in header”).

In order to check the JWT Token generated, we have to open Postman and type in following credentials:

POST request to http://localhost:3000/users/authenticate

Headers -> Key: Content-Type -> Value: application/json

Body -> raw

POST Request for Authenticate

Once we press send, we generate the JWT token with all the user information:

JWT Token

7) Testing JWT Token in header using route protection:

To test out our JWT token with header, we first have to protect our route by inlining the following code in user.js file at line 62:

router.get(‘/profile’, passport.authenticate(‘jwt’,{session:false}), (req, res, next) => {

Now to test it, we need to grab our JWT token from above postman body. In real life application, it will be available in your local storage or cookies. So we have our Token as:

JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyIkX18iOnsic3RyaWN0TW9kZSI6dHJ1ZSwic2VsZWN0ZWQiOnt9LCJnZXR0ZXJzIjp7fSwiX2lkIjoiNTlhMzNlNzFiOGVkYmEyY2ViMDg5MGY4Iiwid2FzUG9wdWxhdGVkIjpmYWxzZSwiYWN0aXZlUGF0aHMiOnsicGF0aHMiOnsicGFzc3dvcmQiOiJpbml0IiwidXNlcm5hbWUiOiJpbml0IiwiZW1haWwiOiJpbml0IiwiX192IjoiaW5pdCIsIm5hbWUiOiJpbml0IiwiX2lkIjoiaW5pdCJ9LCJzdGF0ZXMiOnsiaWdub3JlIjp7fSwiZGVmYXVsdCI6e30sImluaXQiOnsiX192Ijp0cnVlLCJwYXNzd29yZCI6dHJ1ZSwidXNlcm5hbWUiOnRydWUsImVtYWlsIjp0cnVlLCJuYW1lIjp0cnVlLCJfaWQiOnRydWV9LCJtb2RpZnkiOnt9LCJyZXF1aXJlIjp7fX0sInN0YXRlTmFtZXMiOlsicmVxdWlyZSIsIm1vZGlmeSIsImluaXQiLCJkZWZhdWx0IiwiaWdub3JlIl19LCJwYXRoc1RvU2NvcGVzIjp7fSwiZW1pdHRlciI6eyJkb21haW4iOm51bGwsIl9ldmVudHMiOnt9LCJfZXZlbnRzQ291bnQiOjAsIl9tYXhMaXN0ZW5lcnMiOjB9fSwiaXNOZXciOmZhbHNlLCJfZG9jIjp7Il9fdiI6MCwicGFzc3dvcmQiOiIkMmEkMTAkRnhzR2pITHdLWi9IMWkxdlBwMi80ZXI3QnNwem45Qld2cnMvdXZ5OC8uSy9GaUtSVlRqeHEiLCJ1c2VybmFtZSI6InNub3cxNSIsImVtYWlsIjoiamhvbi5zbm93QGdtYWlsLmNvbSIsIm5hbWUiOiJKaG9uIFNub3ciLCJfaWQiOiI1OWEzM2U3MWI4ZWRiYTJjZWIwODkwZjgifSwiJGluaXQiOnRydWUsImlhdCI6MTUwMzg3MzMzNywiZXhwIjoxNTA0NDc4MTM3fQ.1wJH05uwKQY2C74lAGiGf3Mi7wSrYsh8vOEIDGy-n7Q

Now we open postman again, and try with the following credentials:

GET request to http://localhost:3000/users/profile

But we get a restriction called: Unauthorized. We get this unauthorized message because we have secured our route, so not just anybody can access this. Now to access, we do the following changes:

GET request to http://localhost:3000/users/profile

Headers -> Key: Authorization -> Value: Paste JWT Token as generated

SEND

Since it got the Token, it displays the user information through a protected route.

Wrap Up:

I think these 7 steps was my stepping stones towards creating a JSON Web Token(JWT) for authentication. I think it is explicit and secure protocol for transmitting critical information. It is easy to learn and simple to implement.

Stay tuned for my next article on full MEAN Stack authentication application where I’ll use the exact model for by backend!

Some important links:

)

Shreyam Duttagupta

Written by

Software Developer, JavaScript enthusiast & a peaceful warrior.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade