Passport Authentication for Node.js Applications

Share this article

Passport Authentication for Node.js Applications

In this tutorial, we’ll be implementing authentication via Facebook and GitHub in a Node.js web application. For this, we’ll be using Passport, an authentication middleware for Node.js. Passport supports authentication with OpenId/OAuth providers.

Express Web App

Before getting started, make sure you have Node.js installed on your machine.

We’ll begin by creating the folder for our app and then accessing that folder on the terminal:

mkdir AuthApp
cd AuthApp

To create the node app we’ll use the following command:

npm init

You’ll be prompted to provide some information for Node’s package.json. Just hit enter until the end to leave the default configuration.

Next, we’ll need an HTML file to send to the client. Create a file called auth.html in the root folder of your app, with the following contents:

<html>
  <head>
    <title>Node.js OAuth</title>
  </head>
  <body>
    <a href=auth/facebook>Sign in with Facebook</a>
    <br></br>
    <a href=auth/github>Sign in with Github</a>
  </body>
</html>

That’s all the HTML we’ll need for this tutorial.

You’ll also require Express, a framework for building web apps that’s inspired by Ruby’s Sinatra. In order to install Express, from the terminal type the following command:

npm install express --save

Once you’ve done that, it’s time to write some code.

Create a file index.js in the root folder of your app and add the following content to it:

/*  EXPRESS SETUP  */

const express = require('express');
const app = express();

app.get('/', (req, res) => res.sendFile('auth.html', { root : __dirname}));

const port = process.env.PORT || 3000;
app.listen(port , () => console.log('App listening on port ' + port));

In the code above, we require Express and create our Express app by calling express(). Then we declare the route for the home page of our app. There we send the HTML file we’ve created to the client accessing that route. Then, we use process.env.PORT to set the port to the environment port variable if it exists. Otherwise, we’ll default to 3000, which is the port we’ll be using locally. This gives you enough flexibility to switch from development, directly to a production environment where the port might be set by a service provider like, for instance, Heroku. Right below, we call app.listen() with the port variable we set up, and a simple log to let us know that it’s all working fine, and on which port is the app listening.

Now we should start our app to make sure all is working correctly. Simply write the following command on the terminal:

node index.js

You should see the message: App listening on port 3000. If that’s not the case, you probably missed a step. Go back and try again.

Moving on, let’s see if our page is being served to the client. Go to your web browser and navigate to http://localhost:3000.

If you can see the page we created in auth.html, we’re good to go.

Head back to the terminal and stop the app with ctrl + c. So remember, when I say start the app, you write node index.js, and when I say stop the app, you do ctrl + c. Clear? Good, you’ve just been programmed :-)

Setting up Passport

As you’ll soon come to realize, Passport makes it a breeze to provide authentication for our users. Let’s install Passport with the following command:

npm install passport --save

Now we have to set up Passport. Add the following code at the bottom of the index.js file:

/*  PASSPORT SETUP  */

const passport = require('passport');
app.use(passport.initialize());
app.use(passport.session());

app.get('/success', (req, res) => res.send("You have successfully logged in"));
app.get('/error', (req, res) => res.send("error logging in"));

passport.serializeUser(function(user, cb) {
  cb(null, user);
});

passport.deserializeUser(function(obj, cb) {
  cb(null, obj);
});

Here we require Passport and initialize it along with its session authentication middleware, directly inside our Express app. Then, we set up the '/success' and '/error' routes, which will render a message telling us how the authentication went. It’s the same syntax for our last route, only this time instead of using [res.SendFile()](http://expressjs.com/en/api.html#res.sendFile) we’re using [res.send()](http://expressjs.com/en/api.html#res.send), which will render the given string as text/html in the browser. Then we’re using serializeUser and deserializeUser callbacks. The first one will be invoked on authentication and its job is to serialize the user instance and store it in the session via a cookie. The second one will be invoked every subsequent request to deserialize the instance, providing it the unique cookie identifier as a “credential”. You can read more about that in the Passport documentation.

As a side note, this very simple sample app of ours will work just fine without deserializeUser, but it kills the purpose of keeping a session, which is something you’ll need in every app that requires login.

That’s all for the actual Passport setup. Now we can finally get onto business.

Implementing Facebook Authentication

The first thing we’ll need to do in order to provide Facebook Authentication is installing the passport-facebook package. You know how it goes:

npm install passport-facebook --save

Now that everything’s set up, adding Facebook Authentication is extremely easy. Add the following code at the bottom of your index.js file:

/*  FACEBOOK AUTH  */

const FacebookStrategy = require('passport-facebook').Strategy;

const FACEBOOK_APP_ID = 'your app id';
const FACEBOOK_APP_SECRET = 'your app secret';

passport.use(new FacebookStrategy({
    clientID: FACEBOOK_APP_ID,
    clientSecret: FACEBOOK_APP_SECRET,
    callbackURL: "/auth/facebook/callback"
  },
  function(accessToken, refreshToken, profile, cb) {
      return cb(null, profile);
  }
));

app.get('/auth/facebook',
  passport.authenticate('facebook'));

app.get('/auth/facebook/callback',
  passport.authenticate('facebook', { failureRedirect: '/error' }),
  function(req, res) {
    res.redirect('/success');
  });

Let’s go through this block of code step by step. First, we require the passport-facebook module. Then, we declare the variables in which we’ll store our app id and app secret (we’ll see how to get those shortly). After that, we tell Passport to use an instance of the FacebookStrategy we required. To instantiate said strategy we give it our app id and app secret variables and the callbackURL that we’ll use to authenticate the user. As a second parameter, it takes a function that will return the profile info provided by the user.

Further down, we set up the routes to provide authentication. As you can see in the callbackURL we redirect the user to the /error and /success routes we defined earlier. We’re using passport.authenticate, which attempts to authenticate with the given strategy on its first parameter, in this case facebook. You probably noticed that we’re doing this twice. On the first one, it sends the request to our Facebook app. The second one is triggered by the callback URL, which Facebook will use to respond to the login request.

Now you’ll need to create a Facebook app. For details on how to do that, consult Facebook’s very detailed guide Creating a Facebook App, which provides step by step instructions on how to create one.

When your app is created, go to Settings on the app configuration page. There you’ll see your app id and app secret. Don’t forget to change the variables you declared for them on the index.js file with their corresponding values.

Next, enter “localhost” in the App Domains field. Then, go to Add platform at the bottom of the page and choose Website. Use http://localhost:3000/auth/facebook/callback as the Site URL.

On the left sidebar, under the Products section, you should see Facebook Login. Click to get in there.

Lastly, set the Valid OAuth redirect URIs field to http://localhost:3000/auth/facebook/callback.

If you start the app now and click the Sign in with Facebook link, you should be prompted by Facebook to provide the required information, and after you’ve logged in, you should be redirected to the /success route, where you’ll see the message You have successfully logged in.

That’s it! you have just set up Facebook Authentication. Pretty easy, right?

Implementing GitHub Authentication

The process for adding GitHub Authentication is quite similar to what we did for Facebook. First, we’ll install the passport-github module:

npm install passport-github --save

Now go to the index.js file and add the following lines at the bottom:

/*  GITHUB AUTH  */

const GitHubStrategy = require('passport-github').Strategy;

const GITHUB_CLIENT_ID = "your app id"
const GITHUB_CLIENT_SECRET = "your app secret";

passport.use(new GitHubStrategy({
    clientID: GITHUB_CLIENT_ID,
    clientSecret: GITHUB_CLIENT_SECRET,
    callbackURL: "/auth/github/callback"
  },
  function(accessToken, refreshToken, profile, cb) {
      return cb(null, profile);
  }
));

app.get('/auth/github',
  passport.authenticate('github'));

app.get('/auth/github/callback',
  passport.authenticate('github', { failureRedirect: '/error' }),
  function(req, res) {
    res.redirect('/success');
  });

This looks familiar! It’s practically the same as before. The only difference is that we’re using the GithubStrategy instead of FacebookStrategy.

So far so … the same. In case you hadn’t yet figured it out, the next step is to create our GitHub App. GitHub has a very simple guide, Creating a GitHub app, that will guide you through the process.

When you’re done, in the configuration panel you’ll need to set the Homepage URL to http://localhost:3000/ and the Authorization callback URL to http://localhost:3000/auth/github/callback, just like we did with Facebook.

Now, simply restart the Node server and try logging in using the GitHub link.

It works! Now you can let your users log in with GitHub.

Conclusion

In this tutorial, we saw how Passport made the task of authentication quite simple. Implementing Google and Twitter authentication follows a nearly identical pattern. I challenge you to implement these using the passport-google and passport-twitter modules. In the meantime, the code for this app is available on GitHub.

Frequently Asked Questions (FAQs) on Passport Authentication for Node.js Applications

How can I implement Facebook login in Node.js using Passport?

Implementing Facebook login in Node.js using Passport involves several steps. First, you need to install the necessary packages, including express, passport, and passport-facebook. Then, you need to set up your Facebook application on the Facebook developers platform and get your App ID and App Secret. These will be used in your Node.js application to authenticate users. You will also need to configure Passport to use the Facebook strategy and set up routes for users to log in and log out. Finally, you will need to handle the authentication callback from Facebook and create or find a user in your database based on the Facebook profile information.

What is the role of the ‘done’ function in Passport?

The ‘done’ function in Passport is a callback that Passport calls when it has finished authenticating a user. It takes two arguments: an error, if one occurred, and the user object. If authentication was successful, the user object is serialized and stored in the session. If authentication failed, the error is passed to the Express error handling middleware.

How can I verify a Facebook login access token from Node.js?

Verifying a Facebook login access token from Node.js can be done using the ‘fb’ package. After installing the package, you can use the ‘FB.api’ method to make a GET request to the ‘/me’ endpoint of the Facebook Graph API, passing the access token as a parameter. If the access token is valid, the API will return the user’s Facebook profile information. If the access token is invalid, the API will return an error.

How can I handle errors in Passport?

Errors in Passport can be handled in the ‘done’ callback function. If an error occurs during authentication, you can pass it as the first argument to the ‘done’ function. This will pass the error to the Express error handling middleware, which can then handle the error appropriately.

How can I log out a user in Node.js using Passport?

Logging out a user in Node.js using Passport is straightforward. You can simply call the ‘logout’ method on the ‘req’ object in your route handler. This will remove the ‘req.user’ property and clear the login session.

How can I use Passport with other OAuth providers?

Passport supports a wide range of OAuth providers through its various strategies. To use Passport with another OAuth provider, you need to install the appropriate Passport strategy for that provider. Then, you can configure Passport to use that strategy in the same way as you would for the Facebook strategy.

How can I protect routes in Node.js using Passport?

You can protect routes in Node.js using Passport by creating a middleware function that checks if a user is authenticated. If the user is authenticated, the middleware function should call ‘next’ to proceed to the route handler. If the user is not authenticated, the middleware function should redirect the user to the login page.

How can I store user sessions in Node.js using Passport?

Passport uses the Express session middleware to store user sessions. When a user is authenticated, Passport serializes the user object and stores it in the session. When a user makes a subsequent request, Passport deserializes the user object from the session and attaches it to the ‘req’ object.

How can I customize the user profile information returned by Passport?

You can customize the user profile information returned by Passport in the ‘verify’ callback function. This function receives the user profile information from the OAuth provider and can modify it before passing it to the ‘done’ function.

How can I handle multiple authentication strategies with Passport?

Passport allows you to use multiple authentication strategies in your application. You can specify the strategy to use for each route by passing the strategy’s name as a string to the ‘passport.authenticate’ function. If you want to use multiple strategies for the same route, you can pass an array of strategy names.

BeardscriptBeardscript
View Author

Aside from being a software developer, I am also a massage therapist, an enthusiastic musician, and a hobbyist fiction writer. I love traveling, watching good quality TV shows and, of course, playing video games.

nodenode-hubNode-JS-Tutorialsoauthpassport
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week