Yes, there are a lot of posts regarding Facebook login with passport.js. But, I didn’t find anything where the frontend and backend are on different servers, like React as frontend, and Node.js as Backend. That costs me a lot of time. Hopefully, this post will save you some time.
In this article we’ll use:
- React as Frontend (you can use anything)
- Node.js as Backend (express)
- Passport.js as Facebook Login strategy
The full source code is available here.
Configure the Backend
Run yarn init -y
to initialize package.json
. Then, install express, passport, and passport-facebook by running this command:
yarn add express express-session passport passport-facebook
Install other utilities with:
yarn add cookie-parser body-parser
And finally, copy and paste the full code of the backend
Server:
const express = require('express');
const app = express();
const port = 8080;
const passport = require('passport');
const Strategy = require('passport-facebook').Strategy;
const config = require('./config');
passport.use(new Strategy({
clientID: config.FACEBOOK_CLIENT_ID,
clientSecret: config.FACEBOOK_CLIENT_SECRET,
callbackURL: '/facebook/callback'
},
function(accessToken, refreshToken, profile, cb) {
// save the profile on the Database
// Save the accessToken and refreshToken if you need to call facebook apis later on
return cb(null, profile);
}));
passport.serializeUser(function(user, cb) {
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
cb(null, obj);
});
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
app.get('/facebook', passport.authenticate('facebook'));
app.get('/facebook/callback', passport.authenticate('facebook', { failureRedirect: `${config.FRONTEND_HOST}/error`}), (req, res) => {
res.send(`${config.FRONTEND_HOST}/success`);
}) ;
app.listen(port, () => {
console.log(`App is listening on ${port}`);
})
Now let’s go through the code line by line:
const express = require('express');
const app = express();
const port = 8080;
const passport = require('passport');
const Strategy = require('passport-facebook').Strategy;
const config = require('./config');
The part above imports all the libraries and the config files.
The part below is the config file where I have set all the environment variables:
module.exports = {
FRONTEND_HOST: '',
FACEBOOK_CLIENT_ID: '',
FACEBOOK_CLIENT_SECRET: '',
}
FROTEND_HOST
is the domain name of your frontendFACEBOOK_CLIENT_ID
is the client ID of your Facebook appFACEBOOK_CLIENT_SECRET
is the client secret of your Facebook app
passport.use(new Strategy({
clientID: config.FACEBOOK_CLIENT_ID,
clientSecret: config.FACEBOOK_CLIENT_SECRET,
callbackURL: '/facebook/callback',
profileFields: ['id', 'displayName', 'email', 'name', 'photos'],
passReqToCallback: true,
},
function(req, accessToken, refreshToken, profile, cb) {
// save the profile on the Database
// Save the accessToken and refreshToken if you need to call facebook apis later on
return cb(null, profile);
}));
Above, I have configured the Facebook strategy. callbackURL
is the URL which will be called after authentication.profileFields
are the pieces of information we want to be returned from Facebook, and passReqToCallback
says the req
param to be present on the callback function.
On the callback function, we will get:
req
param from the get callaccessToken
is used to call Facebook API next time, it can be used oncerefreshToken
is used to get the newaccessToken
profile
is the param where we will get the information of the usercb
is a callback function, MUST be called at the end of this function
passport.serializeUser(function(user, cb) {
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
cb(null, obj);
});
These two functions are used to serialize and deserialize the pieces of information passed from the Facebook callback function.
app.use(passport.initialize());
app.use(passport.session());
passport.initialize()
is used to initialize the passport authenticationpassport.session()
is used to initialize the passport session
app.get('/facebook', passport.authenticate('facebook'));
app.get('/facebook/callback', passport.authenticate('facebook', { failureRedirect: `${config.FRONTEND_HOST}/error`}), (req, res) => {
res.send(`${config.FRONTEND_HOST}/success`);
}) ;
First, the /facebook
endpoint is called from the frontend. Second, the /facebook/callback
endpoint is called from Facebook after authentication.
And that’s it for the Backend part. Easy, right? 🤔
Configure the Frontend
Use create-react-app to initialize a simple react app:
yarn create react-app frontend
I have kept the Frontend part real simple. Just add the anchor
tag to call http://localhost:8080
and that’s it. Everything will work on backend and return to the URL res.send(`${config.FRONTEND_HOST}/success`);
.
That’s it! The Frontend part is complete.
Configure the FaceBook app
Now, let’s configure the Facebook app and get ClientId
& ClientSecret
.
- Add a new app from here
- Go to Settings → Basic
- You will get the Client ID and Client Secret here

4. On the left side of the bar, click on the + sign beside products
5. Select Facebook LogIn
setup
6. You don’t have to do anything here, passport.js
has done everything for you

7. Go to the settings
on Facebook Login

8. Set up the app like the above image. You must add the redirect URI as described on the backend.

9. Go to the app settings and add localhost
as an app domain
That’s it! Everything should work as expected.