Step wise tutorial for Node.js authentication using passport js and JWT using API’s.
Near about every meaningful application needs an authentication system. Any general authentication system has 4 pages on the frontend for the user. Sign in page, signup page,forgot password page and edit password page and one logout link. Using a MERN stack these pages are created on react while the backend API’s are written on the express app on the backend.
While implementing the authentication system it seemed quite cumbersome to write my complete implementation from scratch for the backend. Thankfully we have a library passport.js to help us with that. Now passport.js helps with basic authentication helpers and maintaining separation of concerns for our authentication system. We can add many authentication strategies with passport in our application. We will be covering the local strategy in this tutorial.(Might cover additional strategies like authentication using google or facebook based on the responses for this tutorial.)
Now as per the documentation on its official github page we need to install the library first on our backend.For this tutorial we will need to install bodyparser, cors, mongroose, bcrypt,jwt,nodemailer and crypto libraries as well.
To setup mongoose(mongo DB). Follow this link
npm install passport
Now that it is installed we need to expose some routes for the frontend to hit to create or login a user.
(All the code below is written assuming the frontend is handled by some frontend framework like react)
I follow a very strict directory structure for MVC applications.So in the backend folder I have seperate folders for my controllers i.e /backend/controllers/ . For routes /backend/routes/ . For config /backend/config/ . For models /backend/models/ etc.
I have created a single gist with all the files and have embed the same down below.
So the basic flow goes something like this.
STEP 1 : Sign up API
Assuming that the frontend is on react js. A user visits the signup page and on form completion a request is sent on the backend for creating a user. The route below for the same is /user/signup. Now the body consists of the email and password(can be encrypted while sending from the frontend- Not covered in this tutorial) Using the mongoose connection we check if the user exists on our DB. If yes then we send a response that the user already exists. However if the user does not exist we create an encrypted password for the user and save the user in the database.
STEP 2: Login API
Now we have created a user and the user can login on the login page on the frontend. The route below for the same is /user/login. Now using the local strategy we have to login the user. The passport has some additional options which can be configured in a config file. The file can be added with new strategies to the implementation. The same can be found in the config/passport.js file below. In the controller method for login below we are authenticating using the local strategy for passport after checking for email and password.Once a user is authenticated we generate a jwt token for the same and send it to the frontend which can be saved on the frontend and sent in the headers of requests sent after.
STEP 3:Forgot password API
Now in case a user forgets his/her password. On the frontend he/she must add his/her email address for us to send an email to. We send an email to the user on the email provided with a token which expires in an hour. This can be handled on the frontend on a specific route and the token needs to be handled on the backend.
STEP 4 :Edit password API
When the user clicks the link on the email for the new password in his inbox he must be redirected to edit password page with a form with 2 fields for a password and confirm password. On filling this form the request must be sent to the API /users/change_password. Now you will have to add logic to check if the the token has been expired or not. This is a self exercise that is left upon for the readers to accomplish. But once the user successfully creates a new password , he/she should be redirected to the login page.
STEP 5: Logout
Delete any sessions or saved tokens in the frontend. If you save JWT tokens on the backend. Also the backend token can removed from the database in case you wish to save it.(Saving token in the backend is not a good practise to follow)
The code might seem over whelming but once implemented the authentication goes a long way for any application.
The things to add to the application now might be authorization for authenticated routes etc. Adding google/facebook strategies help the users authenticate easily to your platform.
P.S In case I miss anything which I am pretty sure that I would have please let me know in the responses below. I when implementing the same could not find many resources for the same. So in case some logic is not as per you, definitely let me know. Will try and solve the same.