One of the toughest topics while building API is, for sure, implementing user authentication. In this piece, we will take a look at how to build a simple and solid authentication approach in NodeJS with PassportJs.
We will create a demo express app that you will be able to use as an authentication boilerplate in your ExpressJs applications.
Before we start, let's go over the technologies we will be using:
- MongoDB and Mongoose
What will we build?
This is Part 1 in the series of guides on creating an authentication & authorization system using Node.js, Express and Permify for your SaaS app.
In this part we will build a token-based authentication with Passport. In particular, we will;
- Use JSON web tokens for token-based user authentication
- Use the Passport module together with passport-local and passport-local-mongoose for setting up local authentication within your server.
Source Code: https://github.com/EgeAytin/node-express-authentication
Passport is nothing but an authentication middleware that supports various strategies. It can be used for user authentication;
- Including a local strategy like using username and password.
- Even third-party authentication.
- Or using OAuth or OAuth 2.0, like using Facebook, Twitter, Google, and so on.
For more detail check out their documentation.
Step 1: Setting up our demo Express app
As a start, we need to create a demo express application. Let’s quickly creatine with the express app generator tool, express-generator.
Run the following command to create;
For earlier Node versions, install the application generator as a global npm package, and then launch it.
Packages we need to install:
In addition to predefined packages on express-generator, we will use the following packages in our project;
You can install them with a single line of command:
Let's add a file named confi.js in the root folder of our project.
In this config.js file, I’ll specify the secret key that we are going to be using for signing my JSON Web Token.
And also I’ll specify a Mongo URL here, which will be the URL for my MongoDB server.
So once we have completed creating the config.js file, we need to update the app.js file in order to initialize PassportJS and connect to our MongoDB server.
Step 2: Creating User Schema and Model
We will create the User schema and model to use the passport-local-mongoose. Let's create a models folder in the root folder and create user.js within:
Note: If you aren't familiar with MongoDB or Mongoose, I highly suggest reading this article first.
We don't need to add username or password fields, because these would be automatically added in by the passport-local-mongoose plugin. So, I’ve just define role names and attributes fields for the authorization part which we cover in next chapter.
Note that to use passport-local-mongoose in our mongoose schema and model, we need to assign the User model to the Plugin:
Step 3: Creating Authentication Strategy
Let's create a new file called authenticate.js in the project folder. We're going to use this file to store the authentication strategies that we will configure.
We will implement a strategy that has the following logic: If the Bearer token is included in the incoming request; then it will be extracted to authenticate the user based upon the token.
Step 4: Defining User Routes
Since our project was generated with an express-generator, the user's route was already created for us. For simplicity purposes, we will use the users' route, and won't add an extra route.
Let's open the user.js file in the routes folder, and add the necessary routes in order to complete the authentication flow.
We will add login, sign up, register and log out endpoints:
When the user is successfully authenticated on the “/login” endpoint, the token will be created by the server and sent back to the client or the user.
So, the client will include the token in every subsequent incoming request in the authorization header with ExtractJWT.fromAuthHeaderAsBearerToken() method, which we defined in authenticate.js file.
I'll show you how this is done in the following Test With Postman section.
The authentication scheme that we have built so far can also be used for third-party authentication based on OAuth 2.0, etc.
We'll create a separate guide just for this. To get updated, join our newsletter below.
Step 5: Verify User in incoming requests
So now, any place that we want to verify the user, We can use the verifyUser function which is exported from authenticate.js.
How do we make use of this?
We're going to implement it into the “/users” endpoint that is predefined with express generator, so lets update the routes/user.js :
Step 6: Test with Postman
We just simply implemented token-based authentication with Passport in the Express app. So let’s test our authentication layer with Postman.
Let's start our server with npm start,
Note: Do not forget that your MongoDB server also needs to be started
Then check the index route on Postman as below,
As you can see we access our server index endpoint because we didn’t configure an authentication check for that route.
Now let's test our users index endpoint. We should get “unauthorized” as a result.
To register users to our mongo database we should send a payload object which consists of username and password fields on the body:
Login and test authentication
Let's log in with the user we just created above:
On successful login, our server will return the JWT. We will use this token to set the Authorization header on protected endpoint requests as below:
As you can see we filled the Authorization header field with Bearer -token-, and fetched all the users on our database.
That's the end of our demo project. We implemented a simple authentication mechanism with the Passport on Express app.
Do not forget that Passport is just an authentication middleware, hence it doesn't cover the other parts of authentication for us; such as API token mechanisms, password reset token mechanisms etc.
To sum up, this mechanism only can be a boilerplate, or a starter for your full authentication implementation unless you have a test or lightweight application. If you wonder what you need to consider when building a robust authentication in NodeJs take a look at this article.
Apart from these, if you have any questions or doubts, feel free to ask them. For more content like this, join our newsletter to get best practices on Authentication, Authorization, and Subscriptions to build ultimate B2B SaaS apps.