Skip to main content

Facebook authentication using NodeJS and PassportJS

Passport is authentication middleware for Node, which authenticates requests and delegates all other functionality to the application. Considering the unique application requirements, passport has stuck to authentication mechanisms known as strategies. In the blog, we will be implementing a similar strategy for Login with Facebook.

Pre -Requisites:

  1. Basic Knowledge of NodeJS
  2. Node JS should be installed on your system.

Steps to configure

  1. Creating Facebook APP_ID and APP_SECRET
  2. Go to http://developers.facebook.com and login with your Facebook account.
  3. Once you have registered, click on the create app link and you will need to enter the details in the following pop-up

Create Facebook APP

  • After creating an app you need to add the product of Facebook, here we are going to use Facebook Login

Add a Facebook product

  • After adding up the product you can now choose to have 'web' and while setting up the URL, you can simply write 'http://localhost:3000'
  • After this go to tab 'MyApps' and select the App name. Select the 'Basic` from settings options in the sidebar as shown below. You can now copy your secret and ID from here

App ID and Secret

  1. Now enough, let's move to code, First of all, create a directory named facebook-node-authentication

    mkdir facebook-node-authentication
  2. Move to the directory facebook-node-authentication/
  cd facebook-node-authentication
  1. In the root create a file package.json and copy the following code

The dependencies, we are going to use in the projects are

  • express : Node web framework
  • express-session Session managment of express
  • passport Authentication middleware for NodeJS
  • passport-facebook Facebook Plugin for passport
  • ejs - Templating engine
{
  "name": "facebook_login_node",
  "version": "1.0.0",
  "description": "\"Basic application for setting up Facebook logij using node and passport\"",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ejs": "^3.1.2",
    "express": "^4.17.1",
    "express-session": "^1.17.1",
    "passport": "^0.4.1",
    "passport-facebook": "^3.0.0"
  }
}
  1. After this run the following command in the terminal

    npm install
  2. Now create a file named server.js and paste the following code
const express = require('express');
const app = express();
const session = require('express-session');
const passport = require('passport');
const FacebookStrategy = require('passport-facebook').Strategy;
const routes = require('./routes.js');
const config = require('./config')

app.set('view engine', 'ejs');

app.use(session({
  resave: false,
  saveUninitialized: true,
  secret: 'SECRET'
}));

app.use(passport.initialize());
app.use(passport.session());

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

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

passport.use(new FacebookStrategy({
    clientID: config.facebookAuth.clientID,
    clientSecret: config.facebookAuth.clientSecret,
    callbackURL: config.facebookAuth.callbackURL
  }, function (accessToken, refreshToken, profile, done) {
    return done(null, profile);
  }
));

app.use('/', routes);

const port = 3000;

app.listen(port, () => {
  console.log('App listening on port ' + port);
});
  1. Now create a file named route.js in the root directory and paste the following code
const passport = require('passport');
const express = require('express');
var router = express.Router();

router.get('/', function (req, res) {
  res.render('pages/index.ejs'); // load the index.ejs file
});

router.get('/profile', isLoggedIn, function (req, res) {
  res.render('pages/profile.ejs', {
    user: req.user // get the user out of session and pass to template
  });
});

router.get('/error', isLoggedIn, function (req, res) {
  res.render('pages/error.ejs');
});

router.get('/auth/facebook', passport.authenticate('facebook', {
  scope: ['public_profile', 'email']
}));

router.get('/auth/facebook/callback',
  passport.authenticate('facebook', {
    successRedirect: '/profile',
    failureRedirect: '/error'
  }));

router.get('/logout', function (req, res) {
  req.logout();
  res.redirect('/');
});

function isLoggedIn(req, res, next) {
  if (req.isAuthenticated())
    return next();
  res.redirect('/');
}

module.exports = router;
  1. Create a directory views and under this create a directory named pages. Under this folder create two pages named profile.ejs and index.ejs
// index.ejs
<!doctype html>
<html>

<head>
  <title>Facebook Node Authentication</title>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  <link rel="stylesheet" type="text/css"
    href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
  <style>
    .facebook {
      background-color: #3b5998 !important;
      color: #fff !important;
    }
    .fa-facebook-f:before,
    .fa-facebook:before {
      content: "\f09a";
    }
  </style>
</head>

<body>
  <nav class="light-blue lighten-1" role="navigation">
    <div class="nav-wrapper container">
      <a id="logo-container" href="#" class="brand-logo">Node Authentication</a>
    </div>
  </nav>
  <div class="section no-pad-bot" id="index-banner">
    <div class="container">
      <br><br>
      <div class="row center">
        <div class="col s6 offset-s3">
          <div class="card">
            <div class="card-content">
              <span class="card-title">Facebook Login using Node and passport</span>
            </div>
            <div class="card-action">
              <a href="/auth/facebook" class="waves-effect waves-light btn social facebook">
                <i class="fa fa-facebook"></i> Sign in with facebook
              </a>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>
<!- profile.ejs->
<!doctype html>
<html>

<head>  
  <title>Facebook Node Authentication</title>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" type="text/css"
    href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
  <style>
    .card:hover {
      box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
      margin-bottom: 54px;
    }
  </style>
</head>

<body>
  <nav class="light-blue lighten-1" role="navigation">
    <div class="nav-wrapper container">
      <a id="logo-container" href="#" class="brand-logo">Node Authentication</a>
      <a href="/logout" class="right">Logout</a>
    </div>
  </nav>
  <div class="section no-pad-bot" id="index-banner">
    <div class="container">
      <br><br>
      <div class="row center">
        <div class="col s12">
          <div class="card">
            <div class="card-content blue lighten-3">
              <span class="card-title white-text"><strong><i class="large material-icons">person</i>
                </strong></span>
            </div>
            <div class="card-action">
              <h5><b><%= user.displayName %></b></h5>
              <p><strong>Facebook id</strong>: <%= user.id %></p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>
  1. Finally, when you are done with the above code you can now write all your app details gathered in step 1 to config.js file created in the root directory
module.exports = {
	'facebookAuth': {
		'clientID':  '<APP_ID>', // your App ID
		'clientSecret':  '<APP_SECRET>', // your App Secret
		'callbackURL':  'http://localhost:3000/auth/facebook/callback'
	}
}
  1. Let's have a final check with the repository, aftre follwoing all the steps in the same pordr the directory structure of your code will look like below:
// Final directory structure
facebook-node-authentication/
  --|node_modules
  --|views/
    |--|pages/
    |----|error.ejs
    |----|profile.ejs
    |----|index.ejs
  --|config.js
  --|package.json
  --|package-lock.json
  --|routes.js
  --|server.js
  1. Now run the server by executing below command in the directory facebook-node-authentication/
npm start
  1. Visit the browser with the URL http://localhost:3000

Comments

Popular posts from this blog

How to use Ngx-Charts in Angular ?

Charts helps us to visualize large amount of data in an easy to understand and interactive way. This helps businesses to grow more by taking important decisions from the data. For example, e-commerce can have charts or reports for product sales, with various categories like product type, year, etc. In angular, we have various charting libraries to create charts.  Ngx-charts  is one of them. Check out the list of  best angular chart libraries .  In this article, we will see data visualization with ngx-charts and how to use ngx-charts in angular application ? We will see, How to install ngx-charts in angular ? Create a vertical bar chart Create a pie chart, advanced pie chart and pie chart grid Introduction ngx-charts  is an open-source and declarative charting framework for angular2+. It is maintained by  Swimlane . It is using Angular to render and animate the SVG elements with all of its binding and speed goodness and uses d3 for the excellent math functio...

Understand Angular’s forRoot and forChild

  forRoot   /   forChild   is a pattern for singleton services that most of us know from routing. Routing is actually the main use case for it and as it is not commonly used outside of it, I wouldn’t be surprised if most Angular developers haven’t given it a second thought. However, as the official Angular documentation puts it: “Understanding how  forRoot()  works to make sure a service is a singleton will inform your development at a deeper level.” So let’s go. Providers & Injectors Angular comes with a dependency injection (DI) mechanism. When a component depends on a service, you don’t manually create an instance of the service. You  inject  the service and the dependency injection system takes care of providing an instance. import { Component, OnInit } from '@angular/core'; import { TestService } from 'src/app/services/test.service'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.compon...

How to solve Puppeteer TimeoutError: Navigation timeout of 30000 ms exceeded

During the automation of multiple tasks on my job and personal projects, i decided to move on  Puppeteer  instead of the old school PhantomJS. One of the most usual problems with pages that contain a lot of content, because of the ads, images etc. is the load time, an exception is thrown (specifically the TimeoutError) after a page takes more than 30000ms (30 seconds) to load totally. To solve this problem, you will have 2 options, either to increase this timeout in the configuration or remove it at all. Personally, i prefer to remove the limit as i know that the pages that i work with will end up loading someday. In this article, i'll explain you briefly 2 ways to bypass this limitation. A. Globally on the tab The option that i prefer, as i browse multiple pages in the same tab, is to remove the timeout limit on the tab that i use to browse. For example, to remove the limit you should add: await page . setDefaultNavigationTimeout ( 0 ) ;  COPY SNIPPET The setDefaultNav...