passport / discuss

A forum for discussing topics related to the usage of Passport.js.
1 stars 0 forks source link

Implementing Passport-Twitter and Passport-Local #63

Open theodorusandi opened 2 years ago

theodorusandi commented 2 years ago

Hi guys! I tried to implement twitter strategy using PassportJS alongside local strategy for my ExpressJS application. The local strategy works fine. However, for twitter strategy, it doesn't move from this page (image below) when calling the callback URL. Twitter actually called the callback route (I tried replacing passport.authenticate() with res.json()) but somehow when I put passport.authenticate() it got stuck. What could be the problem?

server

const express = require("express");
const cors = require("cors");
const session = require("express-session");
const csrf = require("csurf");
const compression = require("compression");
const helmet = require("helmet");
const MongoStore = require("connect-mongo");

const router = require("./routes/api.routes");
const passport = require("./middlewares/passport.middleware");

const app = express();

app.use(
  cors({
    origin: [
      "https://api.twitter.com",
    ],
    credentials: true,
  })
);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
  session({
    secret: process.env.SECRET,
    resave: true,
    rolling: true,
    saveUninitialized: true,
    store: MongoStore.create({
      mongoUrl: process.env.MONGODB_URI,
    }),
    cookie: {
      // 1 hour
      maxAge: 1000 * 60 * 60 * 1,
      httpOnly: true,
    },
  })
);
app.use(passport.initialize());
app.use(passport.session());
app.use(csrf());
app.use(helmet());
app.use(compression());
app.use(router);

// error handler
app.use(function (err, req, res, next) {
  if (err.code === "EBADCSRFTOKEN") {
    // handle CSRF token errors here
    return res.status(403).send({ message: "form tampered with" });
  }

  res.status(err.status || 500);
});

module.exports = app;

routes

// OAuth 1
router.route("/auth/twitter").get(passport.authenticate("twitter"));

router
  .route("/auth/twitter/callback")
  .get(passport.authenticate("twitter", { failureRedirect: "/error" }), (req, res) => {
    // it never reached here
    res.status(200).send({ msg: "success!" });
  });

router.route("/error").get((req, res) => {
  res.status(403).send({ msg: "authentication failed" });
});

passport config

passport.use(
  new TwitterStrategy(
    {
      consumerKey: process.env.TWITTER_CONSUMER_KEY,
      consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
      callbackURL: "http://127.0.0.1:5000/auth/twitter/callback",
    },
    async function (token, tokenSecret, profile, cb) {
      try {
        const user = await users.upsertUser(profile.id);
        return cb(null, user);
      } catch (err) {
        return cb(err);
      }
    }
  )
);

passport.serializeUser((user, cb) => {
  cb(null, user.email);
});

passport.deserializeUser(async (username, cb) => {
  try {
    const user = await users.findUserBy("email", username);
    // filter out data
    cb(null, user);
  } catch (err) {
    cb(err);
  }
});