Passport&JWT和谷歌/ Facebook战略 - 我如何结合JWT和谷歌/ Facebook战略?

问题描述 投票:7回答:3

这个问题适合任何熟悉的人

  • Node.js的
  • 表达
  • 护照
  • 带护照的JWT认证(JSON Web令牌)
  • Facebook OAuth2.0或Google OAuth2.0

我一直在做一些在线课程,并了解如何做以下两件事:

  1. 使用Passport本地策略+ JWT令牌进行身份验证
  2. 使用Passport Google / Facebook策略+ Cookie /会话进行身份验证。

我试图基本上结合这两门课程的内容。我想使用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')时,我收到以下错误:

enter image description here

我是如何尝试解决问题的:

  • 我在我的npm服务器上安装了cors,并将app.use(cors());添加到我的index.js中。
  • 我采取了一个刺,并在Google开发者控制台的“授权JavaScript起源”中添加了“http://localhost:3000”。

这些解决方案都没有解决问题,所以现在我真的感到困惑。我想使用axios / ajax方法,但我不确定如何克服这个cors错误。

抱歉这么长的消息,但我真的觉得我必须给你所有的信息,以便你能够正确地帮助我。

再次感谢,期待收到您的来信!

oauth-2.0 jwt passport.js google-oauth2 facebook-oauth
3个回答
13
投票

我用这种方式解决了这个问题:

  1. 在前端(可以是移动应用程序)我向谷歌(或Facebook)提出登录请求,在用户选择了他的帐户并登录后,我得到了包含谷歌身份验证令牌和基本用户信息的回复。
  2. 然后我将google身份验证令牌发送到后端,我的API又向Google API发送了一个请求以确认该令牌。 (See step 5
  3. 成功请求后,您将获得基本的用户信息和电子邮件。此时,您可以假设用户通过Google登录是好的,因为谷歌检查返回它没关系。
  4. 然后,您只需使用该电子邮件注册或登录用户并创建该JWT令牌。
  5. 将令牌返回给您的客户端,并将其用于将来的请求。

我希望它有所帮助。我实施了多次,它显示了一个很好的解决方案。


2
投票

虽然有很好的答案,但我想通过示例添加更多信息。

  • Passport的google / facebook策略是基于会话的,它将用户信息存储在cookie中,这是不可取的。所以我们需要先禁用它

要禁用会话,我们需要修改我们的重定向路由器。例如,如果我们有重定向路径/ 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战略。


-1
投票

我发现的解决方案是在弹出窗口(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)您的实际令牌。这样您就不会遇到浏览器历史记录安全问题。

© www.soinside.com 2019 - 2024. All rights reserved.