4

以下のpassport-facebook関連の操作を別の方法で処理したいです。

  1. Facebookでサインアップ
  2. Facebookでログイン
  3. 既存のアカウントを Facebook に接続する

「サインアップ」のために、私がしたい/確認したいこと:

  • ユーザーが既に存在する場合 (facebook oauth id に基づく)、ログインにリダイレクトします。
  • ユーザーが既に存在する場合 (Facebook プロファイルの電子メール アドレスに基づく)、電子メールでサインインするようにユーザーに促し、Facebook アカウントに接続します。
  • 新しいユーザーを作成してサインインします。

「ログイン」と「アカウントの接続」については、他の一連のチェック/操作を実行したいと考えています。

私は、facebook のパスポート ドキュメントと、パスポート フェイスブック モジュール、および関連するスタック オーバーフローに関する一連の質問を見てきましたが、これを実装する方法にまだ苦労しています。

異なる callbackURL とオプションを使用して (パスポート経由で) 異なる Facebook 戦略を実装するにはどうすればよいですか?

4

1 に答える 1

9

かなり掘り下げた後、これが私がやったことです:


3 つの個別のパスポート戦略を作成します。

それぞれに異なる名前 (facebookSignUp 対 facebookLogIn 対 facebookConnect) と異なる callbackURL パス (.../sign-up/clbk 対 .../log-in/clbk 対 .../connect/clbk) があります。

// facebook strategy 1 (sign-up with facebook)
passport.use('facebookSignUp', new FacebookStrategy({
        clientID: FACEBOOOK_APP_ID,
        clientSecret: FACEBOOK_APP_SECRET,
        callbackURL: 'http://website/auth/facebook/sign-up/clbk'
    },
    function(accessToken, refreshToken, profile, clbk) {
        return clbk(profile);
    }
));

// facebook strategy 2 (log-in with facebook)
...

// facebook strategy 3 (connect facebook to existing account) 
...

各戦略のルートを作成します。

facebook認証後の初期リクエストルート&コールバックルート。したがって、戦略ごとに 2 つのルートがあります。

var member = require('../member');              // member module controller

// sign-up with facebook
app.route('/auth/facebook/sign-up')
    .get(member.facebookSignUp);                // passport redirect to facebook for authentication

// sign-up with facebook callback
app.route('/auth/facebook/sign-up/clbk')
    .get(
    member.facebookSignUpClbk,                  // parse facebook profile to create new user & check for existing account -> redirect to log-in route
    member.checkEmail,                          // check if email is already used -> throw error 'please log in with email, then connect facebook in settings'
    member.checkUrl,                            // get unique url
    member.signUp,                              // create new user & sign-in
    member.email.welcome,                       // send welcome email
    member.facebookRedirectDashboard            // redirect to member dashboard
);

// log-in with facebook
app.route('/auth/facebook/log-in')
    .get(member.facebookLogIn);                 // passport redirect to facebook for authentication

// log-in with facebook callback
app.route('/auth/facebook/log-in/clbk')
    .get(
    member.facebookLogInClbk,                   // authenticate user and log-in & check if user exists (fb oauth id or email address) -> throw error 'please sign up with facebook or log in with email'
    member.lastLogin,                           // update user's last login field
    member.facebookRedirectDashboard            // redirect to dashboard
);

// connect facebook profile to existing account
...

// connect facebook profile to existing account clbk
...

実際のパスポート認証は、次のファイル/関数で実行されます。

member.facebookSignUp は、facebook にリダイレクトする Passport.authenticate() を呼び出すだけです。

// member.facebookSignUp
exports.facebookSignUp = function(req, res, next) {
    passport.authenticate('facebookSignUp', {          // use the 'facebookSignUp' strategy
        display: null,                                 // null = let facebook decide (or 'page' (default), 'popup', 'touch', etc)
        scope: [
            'public_profile',                          // profile returned by default, but specified here anywhere
            'email',                                   // ask for email address
            'user_location'                            // ask for location
        ]
    })(req, res);
};

member.facebookSignUpClbk は、facebook がユーザーを承認し、コールバック ルートにリダイレクトした後に実行されます。それは他のすべてが起こる場所です。

// member.facebookSignUpClbk
exports.facebookSignUpClbk = function(req, res, next) {

    // parse profile & plug into req.body for new user creation in later fxn
    function parseProfile(profile) {
        // user doc
        req.body = {};
        // facebook profile data
        req.body.facebook = (profile._json) ? profile._json : {id: profile.id};
        // name
        ...
        // email
        ...
        next();
    }

    // check existing users (mongoose/mongodb)
    function checkUser(profile) {
        User.findOne({query}, function(err, userDoc) {
            if (err) {
                return res.redirect(
                    'http://'+req.headers.host+
                    '?header=Sign-Up Error!'+
                    '&message=We had trouble signing you up with Facebook. Please try again'
                );
            } else if (userDoc) {
                // redirect to log-in fxn
                return res.redirect('http://website/auth/facebook/log-in');
            } else {
                parseProfile(profile);
            }
        });
    }

    // passport authentication
    function passportAuth() {
        passport.authenticate('facebookSignUp', function(profile) {
            if (!profile || !profile.id) {
                return res.redirect(
                    'http://'+req.headers.host+
                    '?header=Sign-Up Error!'+
                    '&message=We had trouble signing you up with Facebook. Please try again or sign-up via email.'
                );
            } else {
                checkUser(profile);
            }
        })(req, res);
    }

    // start process
    passportAuth();
};

member.facebookLogIn、.facebookLogInClbk、.facebookConnect、および .facebookConnectClbk は同様の方法で設定されますが、「Clbk」関数のロジックは、私がやろうとしていることによって異なります。


お役に立てれば!

于 2015-08-20T17:57:13.853 に答える