这个问题适合任何熟悉的人
我一直在做一些在线课程,并了解如何做以下两件事:
我试图基本上结合这两门课程的内容。我想使用Google Strategy + JWT身份验证。我想使用JWT而不是cookie,因为我的应用程序将是一个网络/移动/平板电脑应用程序,我需要从不同的域访问api。
我对此有两个问题:要启动Google / facebook OAuth管道,您需要调用'/ auth / facebook'或'/ auth / google'。两个Oauth流程基本相同,所以当我从现在开始说“/ auth / google”时,我指的是其中之一。现在我遇到的问题是:在客户端,我是否通过href按钮链接或axios / ajax调用调用'/ auth / google'路由?如果我使用href或axios / ajax方法,我仍然会遇到两种解决方案的问题。
href方法问题:当我将带有href的<a>
标签分配给'/ auth / google'时,身份验证工作完全正常。用户被推送到Google Auth流程,他们登录并调用'/ auth / google / callback'路由。我现在遇到的问题是如何从'/ auth / google / callback'正确地将JWT令牌发送回客户端?
经过大量的谷歌搜索后,我看到人们只是通过重定向查询参数中的oauth回调将JWT传递回客户端。例如:
res.redirect(301, `/dashboard?token=${tokenForUser(req.user)}`);
我遇到的问题是,现在我的浏览器历史记录中保存了身份验证功能!我可以注销(破坏localStorage中保存的令牌),然后只需查看我的浏览器URL历史记录,回到查询参数中包含令牌的URL,我会自动再次登录而无需经过谷歌策略!这是一个巨大的安全漏洞,显然是接近它的错误方法。
axios / ajax方法问题:在我解释这个问题的问题之前,我肯定知道如果我得到这个工作,它将解决我以前的href问题所遇到的所有问题。如果我设法从axios.get()调用中调用'/ google / auth'并在响应正文中接收JWT,我将不会将该令牌作为url param发送,并且它不会保存在浏览器历史记录中!完美对吗?这种方法还存在一些问题:(
当尝试调用axios.get('/auth/google')
时,我收到以下错误:
我是如何尝试解决问题的:
app.use(cors());
添加到我的index.js中。这些解决方案都没有解决问题,所以现在我真的感到困惑。我想使用axios / ajax方法,但我不确定如何克服这个cors错误。
抱歉这么长的消息,但我真的觉得我必须给你所有的信息,以便你能够正确地帮助我。
再次感谢,期待收到您的来信!
我用这种方式解决了这个问题:
我希望它有所帮助。我实施了多次,它显示了一个很好的解决方案。
虽然有很好的答案,但我想通过示例添加更多信息。
要禁用会话,我们需要修改我们的重定向路由器。例如,如果我们有重定向路径/ google / redirect,如下所示,我们需要传递{session:false}对象作为参数。
router.get('/google/redirect', passport.authenticate('google', { session: false }), (req, res)=> {
console.log(":::::::::: user in the redirect", req.user);
//GENERATE JWT TOKEN USING USER
res.send(TOKEN);
})
那么这个用户来自哪里?该用户来自护照的回调功能。在前面的代码片段中,我们添加了passport.authenticate(....)这个中间件启动了护照的google-strategy的回调,用于处理用户。例如
passport.use(
new GoogleStrategy({
callbackURL: '/google/redirect',
clientID: YOUR_GOOGLE_CLIENT_ID
clientSecret: YOUR_GOOGLE_SECRET_KEY
},
(accessToken, refreshToken, profile, done)=>{
console.log('passport callback function fired');
// FETCH USER FROM DB, IF DOESN'T EXIST CREATE ONE
done(null, user);
})
)
而已。我们已成功结合JWT和Google / Facebook战略。
我发现的解决方案是在弹出窗口(window.open
)中执行OAuth流程,它使用预定义的回调函数在成功验证后将令牌传递给前端。
以下是本教程中的相关代码示例:https://www.sitepoint.com/spa-social-login-google-facebook/
这是从您的前端调用的预定义回调和初始打开方法:
window.authenticateCallback = function(token) {
accessToken = token;
};
window.open('/api/authentication/' + provider + '/start');
以下是您的OAuth回调网址在成功进行身份验证后应返回的内容(这是弹出窗口中的最后一步/页面):
<!-- src/public/authenticated.html -->
<!DOCTYPE html>
<html>
<head>
<title>Authenticated</title>
</head>
<body>
Authenticated successfully.
<script type="text/javascript">
window.opener.authenticateCallback('{{token}}');
window.close();
</script>
</body>
</html>
您的令牌现在可用于您的前端预定义回调函数,您可以在其中轻松将其保存在localStorage中。
我想,您可以在同一窗口中执行OAuth流程(无弹出窗口)并返回一个HTML页面(类似于上面的内容),它只保存令牌并立即将用户重定向到仪表板。
但是,如果您的前端域与您的api / auth服务器不同,您可能需要使用一次性时间敏感令牌(由您的api /生成)从api / auth服务器重定向到前端auth服务器),您的前端可以用来调用和接收(使用axios)您的实际令牌。这样您就不会遇到浏览器历史记录安全问题。