JWT 的 Facebook 护照
Facebook-passport with JWT
我一直在我的服务器上使用 Passport 进行用户身份验证。
当用户在本地登录时(使用用户名和密码),服务器向他们发送一个 JWT 存储在 localstorage 中,并且每 api 发送回服务器需要用户身份验证的调用。
现在我想支持 Facebook 和 Google 登录。自从我开始使用 Passport 以来,我认为最好继续使用 Passport 策略,使用 passport-facebook 和 passport-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,我确实获得了令牌,但我没有被重定向到我的应用程序。
有什么解决办法吗?我的方法错了吗?任何建议都可以。
正确的解决方案是在客户端实现重定向。
只需使用:
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 中,否则重定向到登录页面。
我找到的针对该问题的最佳解决方案是使用包含 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 更安全,并且您仍然可以使用安全解决方案使其更安全,这与显然不安全的查询参数不同。
添加到 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 />;
}
}
我一直在我的服务器上使用 Passport 进行用户身份验证。 当用户在本地登录时(使用用户名和密码),服务器向他们发送一个 JWT 存储在 localstorage 中,并且每 api 发送回服务器需要用户身份验证的调用。
现在我想支持 Facebook 和 Google 登录。自从我开始使用 Passport 以来,我认为最好继续使用 Passport 策略,使用 passport-facebook 和 passport-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,我确实获得了令牌,但我没有被重定向到我的应用程序。
有什么解决办法吗?我的方法错了吗?任何建议都可以。
正确的解决方案是在客户端实现重定向。
只需使用:
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 中,否则重定向到登录页面。
我找到的针对该问题的最佳解决方案是使用包含 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 更安全,并且您仍然可以使用安全解决方案使其更安全,这与显然不安全的查询参数不同。
添加到 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 />;
}
}