node.jsreactjsexpresspassport.jspassport-facebook

Having trouble implementing Passport.js with React for Facebook login


I am having trouble utilizing Passport.js with React for Facebook login.

I was able to set up everything from the server with Express and Node.js to the client-side using React.js. From the client-side, I created a login button component that opens a new window which then hits my server and signs me into Facebook within the second window. Now the problem is how do I properly route the information back to the original window and update my state?

Here is my React code:

import React, { useState } from "react";

function Facebook() {
  const [state, setState] = useState({
    isAuth: false,
    user: "",
    token: "",
  });

  let content = !state.isAuth ? (
    <>
      <div>
        <a href="http://localhost:4000/facebook">
          <button
            style={{
              display: "inline-block",
              fontSize: "14px",
              padding: "13px 30px 15px 44px",
              background: "#3A5A97",
              color: "#fff",
              textShadow: "0 -1px 0 rgba(0,0,20,.4)",
              textDecoration: "none",
              lineHeight: "1",
              position: "relative",
              borderRadius: "5px",
            }}
          >
            Login with Facebook
          </button>
        </a>
      </div>
    </>
  ) : (
    <>
      <div>
        <button onClick={handleLogout}>logout</button>
      </div>
    </>
  );

  return <>{content}</>;
}

export default Facebook;

Here is my Express server (I took out a lot of things that are unnecessary for your view):

const express = require("express");
const app = express();
const port = 4000;
const passport = require("passport");
const Strategy = require("passport-facebook").Strategy;
const cors = require("cors");
const jwt = require("jsonwebtoken");

passport.use(
  new Strategy(
    {
      clientID: "<CLIENT_APP_ID>",
      clientSecret: "<CLIENT_SECRET>",
      // callbackURL: "http://localhost:3000/auth/facebook/callback",
      callbackURL: "/auth/facebook/callback",
      profileFields: ["id", "displayName", "email", "name"],
      enableProof: true,
    },
    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
      console.log(accessToken, "<-------------what is access token");
      console.log(profile, "<--------------------what is the profile?");
      cb(null, profile);
    }
  )
);

passport.serializeUser(function (user, cb) {
  console.log("<--------should be serialized first");
  cb(null, user);
});

passport.deserializeUser(function (obj, cb) {
  console.log("<--------should be deserialized second");
  cb(null, obj);
});

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

app.get("/facebook", passport.authenticate("facebook"));
app.get(
  "/auth/facebook/callback",
  passport.authenticate("facebook", {
    session: false,
    failureRedirect: "http://localhost:3000/error",
    successRedirect: "http://localhost:3000/success",
  }),
  (req, res) => {
    res.json(); 
  }
);

app.listen(port, () => {
  console.log(`App is listening on ${port}`);
});

Solution

  • I was having the same problem but implementing passport-steam strategy. I found this post about how to set up the Twitter OAUth with passport and react, and since the workflow was the same I was able to adapt it for my needs. Hope it help you too.