Using PassportJS In Your Node.js And Couchbase Web App

I was at an event not too long ago where someone recommended I take a look at PassportJS for my Node.js applications. In case you’re unfamiliar with PassportJS, it is an authentication middleware that makes it easy to work with logins, whether they are with basic login, or with social media accounts such as Facebook and Twitter.

Being that I’m into different authentication techniques, as seen in my other oauth articles, I figured it wouldn’t be a bad idea to do a walkthrough on PassportJS with Express Framework for Node.js.

There is a prerequisite that must be taken care of before pressing on into this tutorial. You need to have Node.js already installed and the Node Package Manager (NPM) functioning. You also need to have a functional Facebook account with access to your Facebook developer dashboard.

Create a New Node.js Project

With everything ready to go, let’s start by creating a new Express Framework project on our desktop. Using the Command Prompt (Windows) or Terminal (Mac & Linux), execute the following:

npm init

Answer all the questions to the best of your ability. If you prefer, you can just create a package.json file at the root of your project with the following in it:

The couchbase package will allow us to interface from our application to Couchbase Server. The express package will allow us to use Express Framework. The body-parser package will allow us to accept POST requests. The cookie-parser and express-session packages will allow PassportJS to store authentication sessions while we use the application. The jade package will allow us to use Jade Markdown and the uuid package will allow us to generate unique values. Finally we include passport and passport-facebook to allow us to use PassportJS and authenticate with Facebook.

If this is your first time hearing of Passport, not a problem. It functions by using what they call Strategies in your project. When you try to authenticate in your application, a particular strategy will be executed that contains all your authentication logic, whether that be simple username and password login, or through social media. We’ll see more on this later on.

Couchbase Server & Facebook Configuration

Before we start coding our project we need to do a few more things in terms of configuration. At the root of your project, create a file called config.json and add the following:

This configuration file will hold all our static values to be used within the application.

Configuring Couchbase Server

If you haven’t already installed Couchbase Server 4.0 or higher, do so now because we need to set it up to work with our configuration file.

In the Couchbase Server dashboard, create a new bucket called passportjs-example or whatever you’ve named it in your config.json file. Because we’re going to be using what is called N1QL further in our project, this bucket needs to have a primary index created.

Both these commands will launch the Couchbase Query Client (CBQ) which will allow us to create indices, among other things. Execute the following in CBQ to create the index that we need for our project:

CREATE PRIMARY INDEX ON `passportjs-example` USING GSI;

Couchbase Server is now good to go.

Configuring Facebook

The final configuration we need to make, as seen in our config.json file is the Facebook configuration.

In your Facebook developer dashboard, create a new application. Copy the application id and the client secret from your dashboard into the appropriate places in your config.json file. Finally, navigate to Settings -> Advanced -> Valid OAuth redirect URIs in your developer dashboard and add whatever Facebook callback URL that you placed in the config.json file. This is where Facebook will drop users after a successful login.

Wew, configuration and initialization is now complete! We are now ready to start coding our project.

Creating Our Node.js Server File

Our Node.js server file, represented by app.js found at the root of our project, is responsible for including and configuring various dependencies and telling our application what port to start listening on. Our file will look like this:

Because we plan on using Jade Markdown in our project we need to tell our application where to find these files and what engine to use. All Jade files will be in the views directory found at the root of our project.

When PassportJS stores and retrieves our sessions, they go through a serialization and de-serialization process. For simplicity, we are only planning to store the user id in our session. This user id will represent a particular NoSQL document that contains our user data.

Finally we are including the files that contain our routes and authentication strategies. We are also telling our server to listen for requests on port 3000.

Adding Database Models

Before we worry about application routes and authentication strategies let’s worry about the functions that will connect our application to Couchbase Server. For simplicity we’re going to place all these functions in a class called AccountModel found in the project’s models/accountmodel.js file.

This class will contain the following functions:

facebookFindOrCreate which will be responsible for taking Facebook authentication data and either getting user account information or creating it if it doesn’t already exist.

findByUserId which will take a user id stored in either a session or the Facebook reference document and getting the user account information associated with it.

updateUser which will update the user account information for a particular user based on their user id and whatever change information was passed with it.

This is our beefiest function of the three. First we run a Couchbase N1QL query against information that Facebook returned when authenticating (we’ll see it soon). If data was found then return it, otherwise the user hasn’t been created yet and we need to create it.

If result.length <= 0 it means our query came up dry. We will be doing two inserts as part of the creation process. The first insert will create the actual user document where all user data is stored. If that insert succeeds, we will proceed to doing our second insert for our Facebook reference. By having a Facebook reference, a relationship is established between the two documents because the Facebook reference document contains the user id to our user document.

In other words, when Facebook information is provided we can then do a lookup for user information. This is particularly useful if you want to have multiple methods of login (Facebook, Twitter, Google+) for a single user.

Regardless on if a user existed or not, we’re going to return the same information back to the route that called it.

Much smaller than our last query, it still uses N1QL. Here we are trying to find a particular user document. The user document will have a key prefixed with user:: and the unique id will be appended to it. The appended value is what is passed from our route.

We are doing two database calls with this function. First we are getting the document that should already exist in Couchbase Server. Then we are changing various information in that document based on what was passed in as profile data from the parent route. With the user document updated, we can now replace what exists in Couchbase.

Creating Routes For Our Application

Our application will have many routes, but only two render data from within our application. Before we worry about the routes, let’s add some skeleton code to our routes/routes.js file:

The route /auth/facebook will take us to the Facebook oauth flow because of our use of passport.authenticate("facebook") which we’ll define in a bit. When the oauth flow has completed we will land on /facebook/callback which we also defined in our config.json file earlier. If we land here and login was successful we’ll be redirected to the /secure route that we define next.

Because we have sessions running, our authorization status can always be seen in the req.user variable. If it is null it means we are not authenticated. If we are authenticated, go ahead and find the user account information via the findByUserId function that we created earlier.

Again we make sure the user is authenticated, but after we take our POST body and pass it to the updateUser function we created earlier for updating the user document in Couchbase.

Designing Views in Jade Markdown to Compliment Our Routes

Everything that renders to the screen will be done using Jade Markdown. There will be only two screens, but we’ll have a base template that includes all of our scripts and CSS to prevent code duplication.

Creating the Layout View

The layout view will be a single location for all scripts and CSS. Any other view will be nested inside it. Inside your project’s views/layout.jade file, add the following code:

If this is your first time playing with Jade, it is indent sensitive, kind of like Python. You can see here that we’re only including Twitter Bootstrap, so now is a good time to download it. Place the min.css files from the download in your project’s public/css directory and the min.js files from the download in your project’s public/js directory. Also copy over the fonts directory from Bootstrap and place it in your project’s public directory.

Creating the Index View

Now we can create our child views. The index view, found at views/index.jade, will only contain a button for signing in with Facebook. This is for simplicity. It can be seen below:

This view contains a form that is pre-populated with data passed in from the route. Data passed in will be formatted with #{}, for example #{profile.firstname} which came from the profile variable we passed from the route.

When the user submits the form they will be taken to the POST route where data is then updated in Couchbase.

Developing Our PassportJS Authentication Strategy

Now for the thing you came here to see! Although small, here is the PassportJS logic found in our project’s auth/strategies.js file:

It uses the PassportJS Facebook strategy and includes the configuration information we set in the config.json file. Upon successfully signing into Facebook, we choose to pass the full profile object into our facebookFindOrCreate function that we created earlier.

That is all there is to it!

Conclusion

We just saw how to use the PassportJS middleware to authenticate users in a Node.js application. Data accessed with PassportJS is saved and retrieved from Couchbase Server, typical in applications that allow users to login or register via their social media accounts.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.