Search code examples
reactjsexpressreduxtwitter-oauthpassport-twitter

Linking Twitter account to user account (twitter-passport)


Currently, a user is able to login in and sign up for my application no problem. I've then added a "Link your twitter user to account" button which when clicked takes the user to '/auth/twitter'. This then kicks off passport-twitter and the oAuth process begins.

Right now, I'm using passport-twitter as the package for twitter oAuth. This process works. I'm able to get the user successfully authenticated. Here is the code.

However two problems: I don't see a way to 1) keep the user signed into Twitter so they don't have to keep doing this flow of reconnecting their twitter every time they want to push content to it from my app. and 2) associate the Twitter user and the signed in user to my application. Long term, I plan to add other social media accounts, so the user will have multiple social media linked. Twitter will be just one.

Problem #2: I wasn't able to do an axios.get call from my redux store or from the front end to '/auth/twitter/' otherwise I could then just get the information back from the call and then post it to the user's table (right?). So, instead I'm accessing '/auth/twitter' from an tag in the front end to kick off the flow.

passport.use(
  new TwitterStrategy(
    {
      consumerKey: "XXX",
      consumerSecret: "XXX",
      callbackURL: "http://localhost:8080/auth/twitter/callback",
      // callbackURL: "http://www.localhost:8080/home",
      includeEmail: true,
    },
    async(accessToken, refreshToken, profile, cb) => {
      console.log('got the prodile')
      const twitterIDforOAuth = profile.id
      const { id, username } = profile;


      let theuser = await User.findOne({
        where: {
          twitterID: id
        }
      })


      if(theuser){
        console.log('FOUND USER', '\n', theuser)
      } else {
        try {
          console.log('NO USER FOUND')
          var passwordUser = (Math.random() + 1).toString(36).substring(7);
          console.log('CREATING USER')
           theuser = await Promise.all([
            User.create({
              twitterID: id,
              username : username,
              password: passwordUser
            })
          ])
          console.log('USER CREATED');
        } catch (error) {
          console.log(error);
        }
      }
      //this callback calls the auth/callback url to kick off the redirect process
      // need to send username and password to /auth/signup
      return cb(null, {username: username, password: passwordUser})
      
      //Line below sends too much data that is irrelevant for the user... lets review it?
      // return cb(null, {username: twitterIDforOAuth})
    }
  )
);
app.get('/auth/twitter', passport.authenticate("twitter"));

app.get(
  "/auth/twitter/callback",
    passport.authenticate("twitter", {
      failureRedirect: "/login",
      failureMessage: true,
      session: false
    }),
   async (req, res) => {

    var user = req.user;
    console.log(user.username, user.password);
    //GET USERNAME AND PASSWORD
    var username = user.username;
    var password = user.password;
    ///they need to login the app 
    //auth/login

    res.redirect('/AccountSettings')
  }
);

The user is being redirected to /AccountSettings while they go through this flow, so I know that the user is 100% authenticated and signed in with Twitter (otherwise they'd be pushed to /login, which isn't happen).

Most people in this flow create a user in their database using the information returned from Twitter.

However, I'm trying to link this information to the signed in user, and keep them signed into Twitter so the user doesn't need to keep reconnecting their Twitter account (at least not often). (With access to their Twitter account, my plan is to allow them to push content to it)

Currently I'm hitting the '/auth/twitter' route with an tag which's href takes it to '/auth/twitter'. Is this the right way about it or is this approach causing my linkage issue?

What are people's recommendation for this issue? Whats the right way to approach linking social media accounts to a signed in user's account?

I'm using Express, Redux, React, Postgres, and passport-twitter


Solution

  • SOLUTION: How to passing data in TwitterStrategy, PassportJS?

    had to create a state object outside the /auth/twitter route and then added a id param to the /auth/twitter route so the full route was /auth/twitter/:id

    once I got the id I saved it to a state route outside the route in the server file that was accessible to the callback function later in the proces.