Экспресс-паспорт с использованием логина Facebook и локального логина

Я использую промежуточное программное обеспечение Passport для ExpressJS и не могу найти способ использовать стратегию passport-local и стратегию passport-facebook вместе. Я хотел бы настроить его так, чтобы пользователь создал учетную запись на моем сайте, а затем, если он этого захочет, он мог войти в Facebook, чтобы вы могли видеть своих друзей, которые также используют сайт. Однако я не знаю, что такое вошедший в систему пользователь, когда возвращаются данные API Facebook.

Когда кто-то создает учетную запись, его данные (имя пользователя, электронная почта, т. Д.) Хранятся в базе данных. Когда они затем войдут в Facebook, я хотел бы просто обновить базу данных и сеанс, чтобы теперь включить часть информации, возвращаемой API Facebook (facebookID, AccessToken и т. Д.). Как этого достичь?

Вот код, который я могу использовать для доступа к возвращенным данным Facebook. Строка с User.findOne работает только в том случае, если запись базы данных уже была синхронизирована с Facebook ранее. Можно ли как-то передать данные req.session, чтобы определить, кто в данный момент вошел в систему, и обновить свой профиль?

passport.use(new FacebookStrategy({
    clientID: FACEBOOK_APP_ID,
    clientSecret: FACEBOOK_APP_SECRET,
    callbackURL: "http://localhost:3000/auth/facebook/callback",
    //callbackURL: "http://localhost:3000"
    profileFields: ['id', 'displayName']
  },
  function(accessToken, refreshToken, profile, done) {
    User.findOne({facebookID: profile.id}, function(err, user) {
      if (err) { return done(err); }
      user.facebookID = profile.id;
      user.facebookToken = accessToken;
      user.save();
      return done(null, user);
    });
  }
));

2 ответа

Решение

Чтобы получить текущего пользователя, вам нужно добавить passReqToCallback : true вариант в facebookStrategy

passport.use(new FacebookStrategy({
    clientID: FACEBOOK_APP_ID,
    clientSecret: FACEBOOK_APP_SECRET,
    callbackURL: "http://localhost:3000/auth/facebook/callback",
    //callbackURL: "http://localhost:3000"
    profileFields: ['id', 'displayName'],

    passReqToCallback : true // NEED THIS!!

  },
  function(req, accessToken, refreshToken, profile, done) {
    if (req.user) {
      User.findOne({username: req.user.username}, function(err, user) {
        if (err) { return done(err); }
        user.facebookID = profile.id;
        user.facebookToken = accessToken;
        user.save();
        return done(null, user);
      });
    }
    else{
      console.log("attempted facebook auth from non-logged in user");
      return done(null, null);    
    }
  }
));

Я не знаком с модулем Facebook паспорта, но я думаю, что вы можете получить доступ к своей локальной базе данных пользователей внутри этого:

  function(accessToken, refreshToken, profile, done) {
    User.findOne({facebookID: profile.id}, function(err, user) {
      if (err) { return done(err); }
      user.facebookID = profile.id;
      user.facebookToken = accessToken;
      user.save();
      return done(null, user);
    });

Примерно так должно быть хорошо:

  var User = require('./models/user');
  passport.use(User.createStrategy());
  passport.serializeUser(User.serializeUser());
  passport.deserializeUser(User.deserializeUser());


  function(accessToken, refreshToken, profile, done) {
    //Make sure you have your user's email field and match that with 
    //the email field you got from Facebook

    User.findOne({email: profile.email}, function(err, user) {
      if (err) { return done(err); }
      user.facebookID = profile.id;
      user.facebookToken = accessToken;
      user.save();
      return done(null, user);
    });

Я не уверен, если profile есть поле электронной почты, но я думаю, что это должно быть где-то в профиле.

Тем не менее, я понимаю, что это не будет работать, если ваш пользователь имеет только имя пользователя и пароль.

Другие вопросы по тегам