31

我一直在我的服务器上使用Passport进行用户身份验证。当用户在本地登录时(使用用户名和密码),服务器会向他们发送一个存储在本地存储中的JWT,并在每次需要用户身份验证的 api 调用时将其发送回服务器。

现在我也想支持Facebook 和 Google 登录。自从我开始使用 Passport 以来,我认为最好继续使用 Passport 策略,使用passport-facebookpassport-google-oauth

我将参考 Facebook,但两种策略的行为相同。它们都需要重定向到服务器路由(“/auth/facebook”“/auth/facebook/callback”)。该过程成功地保存了用户,包括他们的 facebook\google id 和数据库上的令牌。

在服务器上创建用户时,会创建一个 JWT(不依赖从 facebook\google 收到的令牌)。

     ... // Passport facebook startegy
     var newUser = new User();
     newUser.facebook = {};
     newUser.facebook.id = profile.id; 
     newUser.facebook.token = token; // token received from facebook
     newUser.facebook.name  = profile.displayName;   
     newUser.save(function(err) {
          if (err)
               throw err;
          // if successful, return the new user
          newUser.jwtoken = newUser.generateJwt(); // JWT CREATION!
          return done(null, newUser);
     });

问题是,在创建之后,我找不到将 JWT 发送到客户端的正确方法,因为我还应该重定向到我的应用程序。

app.get('/auth/facebook/callback',
    passport.authenticate('facebook', {
        session: false,
        successRedirect : '/',
        failureRedirect : '/'
    }), (req, res) => {
        var token = req.user.jwtoken;
        res.json({token: token});
    });

上面的代码将我重定向到我的应用程序主页,但我没有得到 token。如果我删除了successRedirect,我确实得到了令牌,但我没有被重定向到我的应用程序

有什么解决办法吗?我的方法错了吗?任何建议都可以。

4

3 回答 3

17

我为该问题找到的最佳解决方案是使用包含 JWT 的 cookie 重定向到预期页面。

Usingres.json只会发送一个 json 响应并且不会重定向。这就是为什么这里的其他建议答案不能解决我遇到的问题。

所以我的解决方案是:

app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
    session: false,
    successRedirect : '/',
    failureRedirect : '/'
}), (req, res) => {
    var token = req.user.jwtoken;
    res.cookie('auth', token); // Choose whatever name you'd like for that cookie, 
    res.redirect('http://localhost:3000'); // OR whatever page you want to redirect to with that cookie
});

重定向后,您可以安全地读取 cookie 并按预期使用该 JWT。(您实际上可以在每次页面加载时读取 cookie,以检查用户是否已登录)

正如我之前提到的,可以使用 JWT 作为查询参数进行重定向,但这非常不安全。使用 cookie 更安全,并且您仍然可以使用安全解决方案来使其更加安全,这与查询参数不同,后者显然不安全。

于 2018-02-18T12:28:49.257 回答
4

添加到Bar的答案。

我准备了一个登陆组件来提取cookie,将其保存到本地存储,删除cookie,然后重定向到授权页面。

class SocialAuthRedirect extends Component {
  componentWillMount() {
    this.props.dispatch(
      fbAuthUser(getCookie("auth"), () => {
        document.cookie =
          "auth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
        this.props.history.push("/profile");
      })
    );
  }

  render() {
    return <div />;
  }
}
于 2018-03-01T02:26:45.227 回答
3

一个合适的解决方案是在客户端实现重定向。

只需使用:

app.get('/auth/facebook/callback',
  passport.authenticate('facebook', {
    session: false,
    failureRedirect: '/login'
  }), (req, res) => {
    res.json({
      token: req.user.jwtoken
    })
  }
)

如果您是客户端收到令牌,然后从那里重定向到主页,如果登录不成功,它将直接由服务器重定向。

或者您可以像我一样进行完整的客户端管理:

app.get('/auth/facebook/callback',
  passport.authenticate('facebook', {
    session: false
  }), (req, res) => {
    if (req.user.jwtoken) {
      res.json({
        success: true,
        token: req.user.jwtoken
      })
    } else {
      res.json({
        success: false
      })
    }
  }
)

如果success === true是,则将 JWT 存储在 LocalStorage 中,否则重定向到登录页面。

于 2017-11-17T05:34:13.677 回答