OAuth2回调-识别用户?

时间:2019-04-28 17:51:34

标签: node.js express google-oauth2

我正在使用Web应用程序,需要我要求用户授予对其Google日历的访问权限(以便我可以代表他们阅读和创建活动)。

总结我的问题,请考虑oauth流程:

客户端(会话)-> 后端(会话)-> google (授予访问权限)-> 后端(我如何知道用户在这一步中存储了refresh_token?)

可能的虚拟解决方案:

客户端(会话)-> 后端(会话)-> google (授予访问权限)-> 客户端(会话)-> 后端(会话)

更多详细信息

这是默认流程:

  • 用户登录到我的Web应用程序(客户端
  • 然后,网络应用要求用户启动oauth2流(客户端
  • 因此用户按下“启动身份验证流程”按钮,该按钮将“启动身份验证流程”请求发送到我的后端(客户端
  • 在后端,有一个oauth客户端,它生成请求url并将用户重定向到该url(后端):
const authUrl = new google.auth.OAuth2(clientId, secret, redirectUrl)).generateAuthUrl(options)
res.redirect(authUrl)
  • 这会将用户重定向到Google同意页面。 ( google
  • 一旦用户授予了权限,它们就会被重定向回OAuth2客户端(后端,即我的“回调”端点)中指定的网址
  • 这时,我需要将refresh_token保存到用户的数据库位置。 (后端

这里是一个问题:我如何在“回调”中了解到该用户仍然是发起流程的同一用户?

这听起来可能很愚蠢,但我对此坚持不懈。

我知道会话应该可以解决该问题,但是由于“回调”是由Google的服务器触发的,并且是我的后端端点(而不是浏览器页面),因此除非我缺少某些内容,否则就没有会话。

据我了解,这是如何实现的,其中涉及首先重定向到浏览器:

  • 用户登录到我的Web应用程序,然后设置会话cookie(客户端
  • 用户启动oauth2流(客户端/后端
  • 然后,回调将重定向回一些虚拟的客户端页面( google
  • 此虚拟页面提取从google传递的身份验证代码,并将其发送到我的后端端点,并沿( client
  • 传递会话
  • 现在服务器知道谁执行了“回调”(后端

但是,在客户端和后端之间来回进行所有操作似乎不是一个好方法

那么有没有一种方法可以在回调过程中标识用户,而无需在过程中间涉及浏览器?该怎么做?

我正在与nodejs合作,并在重要的时候表达意见

谢谢

3 个答案:

答案 0 :(得分:0)

您应将刷新令牌保留在数据库中的服务器上。这是最安全的方法,可以防止攻击者通过网络访问刷新令牌并使用它来访问其帐户。

为用户创建一个ID,使用该ID映射到服务器上的客户端数据,例如刷新令牌。将该ID通过Cookie或JWT传递回浏览器和客户端。然后,每当用户向您的服务器发出请求时,他们将始终传递您在cookie中创建的ID。您可以使用该ID在数据库中查找用户并获取刷新令牌。

答案 1 :(得分:0)

尝试使用passportJs,它使用第三方身份验证提供程序提供身份验证。

var GoogleStrategy = require( 'passport-google-oauth2' ).Strategy;

passport.use(new GoogleStrategy({
    clientID:     GOOGLE_CLIENT_ID,
    clientSecret: GOOGLE_CLIENT_SECRET,
    callbackURL: "http://yourdormain:3000/auth/google/callback",
    passReqToCallback   : true   },   function(request, accessToken, refreshToken, profile, done) {
    User.findOrCreate({ googleId: profile.id }, function (err, user) {
      return done(err, user);
    });   } ));

答案 2 :(得分:0)

似乎有一个名为state的参数,可以用来传递特定数据,Google会将其返回。因为我可以将用户ID或会话令牌作为状态传递并在回调中读取它,所以这解决了我的问题。

来自doc

  

状态推荐。

     

指定应用程序要使用的任何字符串值   用于维护您的授权请求和   授权服务器的响应。服务器返回准确值   您在名称的散列(#)片段中以名称=值对的形式发送的   用户同意或拒绝您的应用程序后,   访问请求。

对于nodejs谷歌oauth2库,可能如下所示:

oauth2ClientGlobal.generateAuthUrl({
            access_type: 'offline',
            scope: this.scopes(),
            state: base64UserId // <- google will return this param back
        });