Ibtisam Ur Rehman
Ibtisam Ur Rehman

Reputation: 119

How to use session variable req.user in passport-twitter strategy

As I can use req.user to get the logged in user in any of route by passing in:

passport.authenticate("jwt", { session: false })

I want to allow the user to sign in with twitter other than local login, so I have a passport-twitter strategy in node.js API. How can I access locally logged in user with req.user?

module.exports = passport => {
  passport.use(
    new Strategy({
        consumerKey: "",
        consumerSecret: "",
        callbackURL: "http://localhost:3000"
      },
      function(token, tokenSecret, profile, cb) {
        Profile.findOne({
          user: req.user._id
        }).then(
          userdetail => {
            userdetail.twuser = profile._json.screen_name;
            userdetail.token = token;
            userdetail.tokenSecret = tokenSecret;

            userdetail.save().then();
            return cb(null, profile);
          }
        )
      }
    )
  );
};

Upvotes: 7

Views: 849

Answers (2)

jneander
jneander

Reputation: 1190

The Google Passport strategy provides an option to pass the request to the verify callback. It seems to do exactly what we are looking for. This stackoverflow answer from a similar question pointed it out, but specifically for that strategy. The example below is copied from that answer.

passport.use(new GoogleStrategy({
  clientID: process.env.GOOGLE_CLIENTID,
  clientSecret: process.env.GOOGLE_CLIENTSECRET,
  callbackURL: "http://127.0.0.1:7777/google/callback",
  passReqToCallback: true
},
// google will send back the token and profile
function(req, token, refreshToken, profile, done) {
  // req.user is the currently logged-in user
  …
})

This comment in the passport-twitter Github repo suggests that the option is available to that strategy as well. I have not yet confirmed, as I have not implemented Twitter as an OAuth strategy in my own project.

Upvotes: 3

Stefan F.
Stefan F.

Reputation: 138

First of all, i would check if there is already a user in your system with the given twitter profile id. Then i would check if there is a user with the same email address. That means, that the user already signed up with his email. If there is no user with the given email address or twitter id in your database, create a new one and assign the twitter id and email to this profile.

Dont forget to add the includeEmail options to the Strategy:

TwitterStrategy({
    consumerKey: "",
    consumerSecret: "",
    callbackURL: "http://localhost:3000"
    includeEmail: true, // <======= this
  }
)

The callback of the twitter oauth can look like that:

async (token, tokenSecret, profile, cb) => {
   const existingProfileWithTwitterId = await Profile.findOne({ twid: profile.id }
   if (existingProfileWithTwitterId) {
     return callback(null, profile)
   }

   const existingProfileWithEmail = await Profile.findOne({ email: profile.emails[0].value }
   if (existingProfileWithEmail) {
     existingProfileWithEmail.twid = profile.id
     // Add some more stuff from twitter profile if you want
     await existingProfileWithEmail.save()
     return callback(null, existingProfileWithEmail)
   }

   // Create a new Profile
   const profile = new Profile({
      twid: profile.id,
      // add some more properties
   })
   return callback(null, profile)
})

After that, you can access to user profile in the next middlewares with req.user.

Upvotes: 3

Related Questions