【问题标题】:Facebook-passport with JWT带有 JWT 的 Facebook 护照
【发布时间】:2017-07-19 10:01:12
【问题描述】:

我一直在我的服务器上使用 Passport 进行用户身份验证。 当用户在本地登录(使用用户名和密码)时,服务器会向他们发送一个 JWT,该 JWT 存储在 localstorage 中,并在每次需要用户身份验证的 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});
    });

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

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

【问题讨论】:

  • 您找到解决方案了吗?我也有同样的问题。
  • 我的解决方案不是最好的,但我所做的是使用查询参数进行重定向。我本可以发送 JWT - 但这不安全(因为查询参数是 url 的一部分并保存在浏览器的历史记录中,因此很容易被滥用)。我所做的是使用新的用户 ID 进行重定向,并且在该重定向页面加载时,我向我的服务器发送了一个请求,以使用其 ID 接收用户的 JWT。为了使其尽可能安全,我在数据库上的用户对象中添加了时间戳,以便可以在 30 秒内检索 JWT(假设重定向不会花费更长的时间)

标签: node.js mongodb passport.js passport-facebook express-jwt


【解决方案1】:

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

简单使用:

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

如果你是客户端收到token,然后从那里重定向到主页,如果登录不成功,它会直接被服务器重定向。

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

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中,否则重定向到登录页面。

【讨论】:

  • @Bar Kedem 这是否解决了您的问题?你能提供更多信息吗?
【解决方案2】:

添加到 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 />;
  }
}

【讨论】:

    【解决方案3】:

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

    使用res.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 更安全,并且您仍然可以使用安全解决方案来使其更加安全,这与查询参数不同,后者显然是不安全的。

    【讨论】:

      猜你喜欢
      • 2016-08-14
      • 2015-01-18
      • 2019-01-06
      • 2023-04-06
      • 2019-06-23
      • 2018-01-13
      • 2020-03-08
      • 1970-01-01
      • 2018-08-11
      相关资源
      最近更新 更多