Skip to content

Multiple social account for same user #1681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gpessa opened this issue Mar 2, 2016 · 14 comments
Closed

Multiple social account for same user #1681

gpessa opened this issue Mar 2, 2016 · 14 comments

Comments

@gpessa
Copy link

gpessa commented Mar 2, 2016

I know I'm not the first one asking for it but I still try :)
I spend my last week trying to solve this problem but I can't find a solution.

I created a new route to connect to the current account another one but in the callback i always have the req.user empty and I can't figure out why.

Please help us :)

@mikealche
Copy link

Hey! I had the same problem, not an expert but I was able to solve it this way (feel free to correct me)

First, be sure to use auth.isAuhtenticated() in the route.
After that you'll need a way to keep track of the user that made the request which is a bit longer to explain but basically I just pass the state parameter to passport.authenticate.
This is my code for adding a facebook account to an already authenticated user:
facebook/index.js

router
   .get('/', auth.isAuthenticated(), function (req, res, next) {
    // console.log('user is: ', req.user)
    passport.authenticate('facebook', {
      scope: ['email', 'user_about_me', 'user_status', 'user_photos', 'user_posts', 'publish_actions','manage_pages', 'publish_pages', 'read_insights', 'pages_show_list','pages_manage_cta', 'email', 'read_audience_network_insights'],
        failureRedirect: '/signup',
        session: false,
        state: JSON.stringify(req.user)
    })(req, res, next)
  })

then later in facebook/passport.js

import passport from 'passport';
import {Strategy as FacebookStrategy} from 'passport-facebook';

var util = require('util');

exports.setup = function(User, config) {
  passport.use(new FacebookStrategy({
    clientID: config.facebook.clientID,
    clientSecret: config.facebook.clientSecret,
    callbackURL: config.facebook.callbackURL,
    profileFields: [
      'displayName',
      'emails'
    ],
    passReqToCallback: true //IMPORTANT!
  },
  function (req, accessToken, refreshToken, profile, done) { //notice how now the first parameter is req!
    var user = JSON.parse(req.query.state) //get the user from the query
    User.findOne({where: { //actually get handle of that user model
          '_id': user._id
        }})
      .then(function(user) { //then here do what you want! :)
        if (!user) {
          console.log('handle me please')
          return done(new Error())
        } 

        user.getFacebookAccount()
            .then(function (FacebookAccount) {
              if(!FacebookAccount){
                console.log(util.inspect(profile, {showHidden: true, depth: null}));
                user.createFacebookAccount({
                  name: profile.displayName,
                  id: profile.id,
                  token: accessToken,
                  refreshToken: refreshToken,
                  email: profile.emails[0].value
                }).then(function  (data) {
                  // console.log('everything good: ', data)
                   return done(null,user)
                }).catch(function (err) {
                  console.log('smthinghappend: ', err)
                   return done(err)
                })

              } else {
                 console.log('were there')
              return done(null, user);
            }
            })
      })
      .catch(function(err) {
        return done(err);
      });
  }));
};

@gpessa
Copy link
Author

gpessa commented Mar 3, 2016

OMG! I love you!
Damn i spent so much time on it!

@gpessa
Copy link
Author

gpessa commented Mar 3, 2016

I really think this could be part of the core

@remicastaing
Copy link
Contributor

There is a caveat to this case: with a FB or a Google strategy, you will have a verified email, with a local strategy the email won't be verified and with Twitter you won't have an email at all. Linking an FB account with an unverified local account will bring some security issues along.

@gpessa
Copy link
Author

gpessa commented Mar 3, 2016

yes, it's true. Interesting point.
Idea about how to solve it?!
I mean the solution is :

  1. no twitter linking
  2. email to verify the local strategy

@remicastaing
Copy link
Contributor

Last year, I spend some time on this problem. You take a look at my code, @gpessa .

@gpessa
Copy link
Author

gpessa commented Mar 3, 2016

Cool! I'll give a look at it!
Do you think you solution may be part of the core?

@gpessa
Copy link
Author

gpessa commented Mar 4, 2016

@miguelalche maybe I'm wrong but with your solution you actually pass to facebook your user. Am I wrong ?

@mikealche
Copy link

@gpessa Glad it could help! 😄
I don't understand what you mean by that!
I do have created an endpoint (using the generator) called FacebookAccount which has a relation with the User model, and then I link them, is that what you asked?

@gpessa
Copy link
Author

gpessa commented Mar 4, 2016

Sorry. So, you copy the user into the request and you send it to Facebook. That means that Facebook can read it.
All the user data are not encrypted.
I'm not an expert but I think this is the scenario

@gpessa
Copy link
Author

gpessa commented Mar 4, 2016

What happen with the passport Facebook authentication is this:

  1. User try to connect the account from your website
  2. Is redirect to the Facebook page where he can log in to the Facebook account
  3. Facebook redirect the user back to the ‘callback page' of your website and pass back the facebook user details

Between the 1 and 2 you attach your user info to the request.
Those info are passed to Facebook in clear, without encryption.
Facebook can theoretically read those info.
What usually happen is that the info are encrypted and send to facebook (like you are doing), everything already work like that in the generator-angular-fullstack but I think there is some and the user info can not be found again in the callback function

@mikealche
Copy link

This is one of the cases when helping others ends up heping you!
I hadn't thought of that (that facebook could actually look at the user data you pass to req.query.state)!!
Although I doubt that facebook does something with it (well you never know), it could just be avoided by passing just the user._id into the state and not the full user object (which contains the tokens).
Maybe that simple trick could solve the security problem?

@Awk34
Copy link
Member

Awk34 commented Mar 10, 2016

Duplicate of #359

@Awk34 Awk34 closed this as completed Mar 10, 2016
@zaphinath
Copy link

@miguelalche Just to clarify- this approach requires the user to be logged in with the local provider in order to attach Facebook to the local user. What if the user doesn't have an account with local and wants to create one. What is your recommended approach instead of checking if isAuthenticated as the middleware?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants