facebook login using node and express

Facebook Login Implementation Using Nodejs and Express

Facebook Login is widely used as an authentication module on websites. Instead of asking user manual details such as email and password and then verify them, it’s better to use already verified user details.

In this article, we are going to learn and implement a Facebook Login System using Nodejs and ExpressJS. You can download the code by clicking the button below.

DOWNLOAD

app

If you are new to Node and Express then you won’t regret taking our Node course. It’s FREE!

Creating Facebook App:

Very first thing you going to need is AppID and AppSecret from Facebook App. Please go to Facebook Developers and create your app.

create facebook app

Choose Website as platform when it ask. Give the proper name and you can leave the namespace field blank.

add web platform

It will ask for Captcha, enter it carefully and once done it will redirect you to the app page. By authenticating your facebook account again you can view the App secret. Now go to Setting and add the Web as a platform.

If you want to test the app in localhost environment then add localhost:3000 as an site address.

add website details

The app is set. Let’s go ahead and create our App using Node.

Configuring our Node App:

In the source directory go to the configuration/config.js and update the Facebook AppID and AppSecret. If you want to use Database to store and validate user information you can put the configuration field as true or false. To know the database design for the app please visit twitter login using node article.

configuration/config.js
module.exports={
  "facebook_api_key"      :     "FB APP ID",
  "facebook_api_secret"   :     "FB API SECRET",
  "callback_url"          :     "http://localhost:3000/auth/facebook/callback",
  "use_database"          :      false,
  "host"                  :     "localhost",
  "username"              :     "root",
  "password"              :     "",
  "database"              :     "Database Name"
}

Update the code with Facebook App information.

Route of Our App:

Routes Action
/auth/facebook Authenticate User with Facebook
/auth/facebook/callback Get the user information from if login successfully
/logout Logging out from App.

Configuring Passport:

I am using Passport node package for the OAuth authentication. It requires configuration of some parameters. Here is our Passport configuration code.

app.js
/*config is our configuration variable.*/
passport.use(new FacebookStrategy({
    clientID: config.facebook_api_key,
    clientSecret:config.facebook_api_secret ,
    callbackURL: config.callback_url
  },
  function(accessToken, refreshToken, profile, done) {
    process.nextTick(function () {
      //Check whether the User exists or not using profile.id
      if(config.use_database) {
         //Further code of Database.
      }
      return done(null, profile);
    });
  }
));

Complete Server Code:

Here is our app.js with complete routing and Passport code.

app.js
const express         =     require('express')
  , passport          =     require('passport')
  , FacebookStrategy  =     require('passport-facebook').Strategy
  , session           =     require('express-session')
  , cookieParser      =     require('cookie-parser')
  , bodyParser        =     require('body-parser')
  , config            =     require('./configuration/config')
  , mysql             =     require('mysql')
  , app               =     express();

//Define MySQL parameter in Config.js file.
const pool = mysql.createPool({
  host     : config.host,
  user     : config.username,
  password : config.password,
  database : config.database
});

// Passport session setup.
passport.serializeUser(function(user, done) {
  done(null, user);
});

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


// Use the FacebookStrategy within Passport.

passport.use(new FacebookStrategy({
    clientID: config.facebook_api_key,
    clientSecret:config.facebook_api_secret ,
    callbackURL: config.callback_url
  },
  function(accessToken, refreshToken, profile, done) {
    process.nextTick(function () {
      //Check whether the User exists or not using profile.id
      if(config.use_database) {
        // if sets to true
        pool.query("SELECT * from user_info where user_id="+profile.id, (err,rows) => {
          if(err) throw err;
          if(rows && rows.length === 0) {
              console.log("There is no such user, adding now");
              pool.query("INSERT into user_info(user_id,user_name) VALUES('"+profile.id+"','"+profile.username+"')");
          } else {
              console.log("User already exists in database");
          }
        });
      }
      return done(null, profile);
    });
  }
));


app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({ secret: 'keyboard cat', key: 'sid'}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res){
  res.render('index', { user: req.user });
});

app.get('/account', ensureAuthenticated, function(req, res){
  res.render('account', { user: req.user });
});

app.get('/auth/facebook', passport.authenticate('facebook',{scope:'email'}));


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

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


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

app.listen(3000);

Designing our View:

index.ejs
<% if (!user) { %>
  <div style="width:500px;height:180px;">
    <h2 style="font-size:40px;">Welcome! Please log in.</h2>
    <a href="/auth/facebook"><img src="fb-login.jpg" width="151" height="24"></a>
    </div>
<% } else { %>
    <h2>Hello, <%= user.displayName %>.</h2>
<% } %>

Once user login we just have to show the values return from Facebook. Here it is.

<p>ID: <%= user.id %></p>
<p>Name :<%= user.displayName %></p>

Running our App:

Download the code and update the config.js with the Facebook app information. Then run

npm install

to install dependencies and then run app using

node app.js

Visit localhost:3000 to view the app.

Login using your Facebook account and allow the app permission. After successful authentication, you will be redirected to your specified callback URL.

Facebook login user details

Conclusion

We learned how to use and implement Facebook login system using Passport module. We used to express to develop the web server and MySQL to store user information.

Further Study

Learn more!
Twitter Login Using Node and MySQL
Facebook Status Box using Node.js and MySQL
HTML5 Push Notification System Using Nodejs MySQL Socket.io
How to Replace All Occurrences of a String in JavaScript

Shahid

Founder of Codeforgeek. Technologist. Published Author. Engineer. Content Creator. Teaching Everything I learn!

Related Posts

34 Comments

  1. Very on-point with your Node tutorials, Shahid, much obliged.

    Curious as to how you were going to make the index, layout, and account .ejs views work together…

  2. Well.. I downloaded your code and ran it. But “Hello undefined” is printed.
    Can you guess what is wrong?

    1. hey may b coz , the profile is object is returning like dz — >

      profile goes here –> { id: ‘1478199245840060’,
      username: undefined,
      displayName: ‘App Dev Axy’,
      name:
      { familyName: undefined,
      givenName: undefined,
      middleName: undefined },
      gender: undefined,
      profileUrl: undefined,
      provider: ‘facebook’,
      _raw: ‘{“name”:”App Dev Axy”,”id”:”1**********0″}’,
      _json: { name: ‘App Dev Axy’, id: ‘1**********0’ } }
      user —> { id: ‘1*********0’,
      username: undefined,
      displayName: ‘App Dev Axy’,
      name:
      { familyName: undefined,
      givenName: undefined,
      middleName: undefined },
      gender: undefined,
      profileUrl: undefined,
      provider: ‘facebook’,
      _raw: ‘{“name”:”App Dev Axy”,”id”:”1**********0″}’,
      _json: { name: ‘App Dev Axy’, id: ‘1**********0’ } }

      so go back to ur application and navigate to views -> index.ejs

      edit this –> Hello, . to —> Hello, .

      hope this should fix ur issue 🙂

        1. I do with console command as below:

          app.get(‘/account’, ensureAuthenticated, function(req, res){
          console.log(req.user);
          res.render(‘account’, { user: req.user });
          });

          it returns:
          2016-09-25T11:58:03.31+0700 [App/0] OUT { id: ‘10154xxxxxxxxxxxx’,
          2016-09-25T11:58:03.31+0700 [App/0] OUT displayName: ‘Jeerapong Putthanbut’,
          2016-09-25T11:58:03.31+0700 [App/0] OUT name: {},
          2016-09-25T11:58:03.31+0700 [App/0] OUT provider: ‘facebook’,
          2016-09-25T11:58:03.31+0700 [App/0] OUT _raw: ‘{“name”:”Jeerapong Putthanbut”,”id”:”10154623775144673″}’,
          2016-09-25T11:58:03.31+0700 [App/0] OUT _json: { name: ‘Jeerapong Putthanbut’, id: ‘10154623775144673’ } }

      1. I cant understand what you are saying to change. please be specific. I am also getting ‘Hello undefined’ as result.

  3. Not working.. says
    Given URL is not allowed by the Application configuration: One or more of the given URLs is not allowed by the App’s settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App’s domains.

    1. if you did not save your username then how facebook will show it to you then by default it shows undefined.

  4. Hello! Awesome work sir! I just needed to know, what fields more to add, if we want to extract more than just the user id, like name, email, etc? (for both twitter and facebook login)

      1. How can the operations of MySql converted to that of mongoDB? If i want to store and retrieve my data from mongoDB, how can that be done?

        1. Hey,

          I am not sure about it. But as far as i know you need extra permission to get user profile picture and that too you will get URL. So you need to write custom code to download that pic.

  5. I wasted nearly one week for implementing this thing in maa project….

    But Finally wen i found this module O:) #Made_my_day O:)

    Thanx a ton broh u helped me #Twice …. #Shaid O:)

    THanx Alot 🙂 Plz keep on post’n 🙂 will b supporting ur work 🙂 #peace ! 🙂

  6. hi shahid, ur tutorial is osssome and i want to know how to get the users profile pic too..pls give me a quick response

  7. This sql always returning 0, even if the number of rows is greater than 0 in MySQL database.
    SELECT * from user_info where user_id=”+profile.id

  8. Is it still possible to use OAuth2 with facebook without having https ?
    Because I’m trying this with localhost:8080/auth/facebook/callback and it doesn’t works…
    I get an error while adding a new user: it tries to add a random id and “unverified” as a username…
    Thanks

  9. FacebookTokenError: Error validating client secret.
    at Strategy.parseErrorResponse (C:\Users\Apple\Desktop\My_node_Programs\facebook-login-node-express-master\node_modules\passport-facebook\lib\strategy.js:196:12)
    at Strategy.OAuth2Strategy._createOAuthError (C:\Users\Apple\Desktop\My_node_Programs\facebook-login-node-express-master\node_modules\passport-oauth2\lib\strategy.js:376:16)
    at C:\Users\Apple\Desktop\My_node_Programs\facebook-login-node-express-master\node_modules\passport-oauth2\lib\strategy.js:166:45
    at C:\Users\Apple\Desktop\My_node_Programs\facebook-login-node-express-master\node_modules\oauth\lib\oauth2.js:191:18
    at passBackControl (C:\Users\Apple\Desktop\My_node_Programs\facebook-login-node-express-master\node_modules\oauth\lib\oauth2.js:132:9)
    at IncomingMessage. (C:\Users\Apple\Desktop\My_node_Programs\facebook-login-node-express-master\node_modules\oauth\lib\oauth2.js:157:7)
    at emitNone (events.js:111:20)
    at IncomingMessage.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1055:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)

  10. I am getting this error —>FacebookAuthorizationError: Can’t load URL: The domain of this URL isn’t included in the app’s domains. To be able to load this URL, add all domains and sub-domains of your app to the App Domains field in your app settings.
    at Strategy.authenticate (C:\Users\Junia\Desktop\node\node_modules\passport-facebook\lib\strategy.js:81:23)
    at attempt (C:\Users\Junia\Desktop\node\node_modules\passport\lib\middleware\authenticate.js:361:16)
    at authenticate (C:\Users\Junia\Desktop\node\node_modules\passport\lib\middleware\authenticate.js:362:7)
    at Layer.handle [as handle_request] (C:\Users\Junia\Desktop\node\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Users\Junia\Desktop\node\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (C:\Users\Junia\Desktop\node\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (C:\Users\Junia\Desktop\node\node_modules\express\lib\router\layer.js:95:5)
    at C:\Users\Junia\Desktop\node\node_modules\express\lib\router\index.js:281:22
    at Function.process_params (C:\Users\Junia\Desktop\node\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Users\Junia\Desktop\node\node_modules\express\lib\router\index.js:275:10)

Leave a Reply to Joey Anuff Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.