将多个第三方和本地帐户与Passport链接在一起

时间:2013-11-14 05:34:50

标签: node.js authentication express authorization passport.js

我已按照建议here成功将AccountsUsers相关联。如果登录用户授权使用OAuth 2.0的第三方(例如Google Contacts API),我可以将该信息保存在帐户中,然后将该帐户与登录用户绑定。

我想更进一步,尽可能地使登录体验无缝。一旦用户将他们的身份绑定到第三方帐户,我希望他们不仅能够使用本地策略(用户名/密码)登录,然后提取相关的第三方信息,但另一方面也是如此:注销后,连接到Google会将其作为我的应用的用户登录,使req.user =他们的User信息就像他们使用本地策略登录时一样。这是相关的代码块(显示的内容还有很多,但重点在于。

passport.use(new GoogleStrategy({
        clientID: google_params.client_id,
        clientSecret: google_params.client_secret,
        callbackURL: google_params.callbackURL,
        passReqToCallback: true
    },
    function(req, token, refreshToken, profile, done) {

...
        // If no user in session, set the req.user to the associated user
        User.findOne({
        'username': account.userId
        }, function(err, user) {
            console.log('Account exists already in DB, and is already tied to a user. Logging into users account.');
            req.user = user;
            return done(null, account);
        });

etc...

在检查序列化/反序列化函数时,此代码从不将用户或帐户信息序列化到会话中,因此虽然该信息确实在验证回调结束时传递,但它在页面刷新时消失(同样,因为什么都没有保存到会话中)。我该怎么办?我是否正确地考虑过这个问题?

2 个答案:

答案 0 :(得分:1)

答案有点晚了,但我一直在研究这个应用程序,我可以帮助其他人。

答案是肯定的是,您可以让用户链接他们的帐户,而无需他们创建本地帐户(如Scotch.io教程中所述)。诀窍在于管理帐户的重复数据删除。

无论他们登录什么提供商,我们都会按顺序处理以下检查:

  1. 如果此提供商的用户已存在:请将其重新登录。
  2. 如果此提供商尚未存在用户:请检查用户是否存在电子邮件地址(或提供商之间的其他常见字段)。如果是这样,请链接帐户并将其登录。
  3. 如果此用户或其他提供商尚未有用户:创建一个新的用户模型,其中包含从提供商处提取的信息,然后将其登录。
  4. 应该为您支持的所有提供商执行此操作。通过使用由第三方服务(例如电子邮件地址)预先验证的公共字段,我们可以删除帐户。另一个功能可能是允许用户手动将它们链接在一起,以便他们想要链接具有不同电子邮件地址的帐户(这种情况与github一起发生,他们使用他们的个人帐户,然后想要将其连接到工作帐户,例如CI供应商)

    希望这会有所帮助。如果你来到另一个解决方案,最好在这里添加它,或者如果遇到任何问题。我认为这是一个很常见的案例,它可以变成一个维基。

    **更新**

      

    如果你想"链接"来自多个提供商的帐户在一起   那一点,你想要一个具有特定于你的用户记录的数据库   应用程序,它又与第三方帐户记录相关联。   然后,在验证回调中,您将要执行任何查询   是必要的,并提供您的应用程序特定用户记录完成。那   将保持一致,以便如果有人将两者联系起来   Facebook和Twitter,他们可以返回应用程序并登录   任何一个。

         

    有关该主题的进一步讨论如下:   http://passportjs.org/guide/authorize.html

         

    如果你走那条路(就像我在我的应用程序中那样),我会使用这样的中间件   将身份验证和授权合并到一个路由中:

    function authnOrAuthzFacebook(req, res, next) {
      if (!req.isAuthenticated()) {
        passport.authenticate('facebook', { successRedirect: '/settings/accounts',
                                            failureRedirect: '/login' })(req, res, next);
      } else {
        passport.authorize('facebook-authz')(req, res, next);
      }
    }
    
    app.get('/facebook-login', authnOrAuthzFacebook);
    

    此评论在can be seen here on GitHub上的应用示例(最终版本)。

    因此,有一些替代版本将执行相同的工作(取决于您希望如何处理它)。

答案 1 :(得分:0)