适用于REST API的Google Plus身份验证

Eri*_*ric 6 rest google-authentication node.js express passport.js

我正在尝试为我正在开发的服务创建一个rest api.该服务有两个部分 - 网站和移动客户端.基本上,移动设备通过api保持其位置是最新的,网站通过api显示数据.

看到我的应用程序仅针对Android,我希望使用"登录Google"作为移动和网站客户端的身份验证机制.

API使用Node.js和Express.js.我在生成新的用户帐户时遇到了麻烦.看到我不想信任客户端的数据,我预期的注册过程是这样的:

通过网站:

  1. 用户访问网站,点击"使用Google注册".
  2. 用户接受应用请求以查看其Google详细信息.
  3. 网站获取google身份验证令牌,然后发送给api.
  4. API与该身份验证令牌联系以获取用户详细信息.
  5. API在数据库中创建一个新用户以及我自己的访问令牌形式.
  6. API将我自己的访问令牌返回给客户端以供将来请求签名.

通过Android应用程序:

  1. 用户下载应用,运行并点击"使用Google注册".
  2. 用户接受谷歌提供的授权步骤.
  3. 应用程序获取一个令牌,并将其发送给API.
  4. API与该身份验证令牌联系以获取用户详细信息.
  5. API实现用户存在并向该用户注册此新设备.
  6. API将我自己的访问令牌返回给应用程序以供将来请求签名.

一旦令牌到达服务器,我就遇到了很多麻烦.每次我使用生成的令牌时,我都会收到错误"无效凭据".

最初我开始使用Passport.js,但我发现的是这个.在文档中,它声明设置如下:

passport.use(new GoogleStrategy({
   returnURL: 'http://www.example.com/auth/google/return',
   realm: 'http://www.example.com/'
},
function(identifier, profile, done) {
   User.findOrCreate({ openId: identifier }, function(err, user) {
      done(err, user);
   });
}));
Run Code Online (Sandbox Code Playgroud)

但是当我记录'标识符'的内容时,它实际上就像是

https://www.google.com/accounts/o8/id?id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

我认为ID对我来说是独一无二的,但我似乎无法确切地发现它是什么.此外,我不知道它是否有时间限制或将永远持续下去.作为最后一个问题,我甚至不知道在通过Android注册时是否能获得相同的价值,因为我不知道价值来自哪里.它不是我期望的那种API访问令牌.当我输出个人资料的内容时,它只是我的姓名和电子邮件地址 - 我无法用于联系Google API以验证用户.

上面的解决方案我不喜欢,因为它意味着托管客户端站点的服务器必须发出api请求才能将id传递给api.或者它将id详细信息发送给客户端,以便它可以将它们传递给api服务器.或者,网站服务器将其放入api数据库,这也是一个糟糕的解决方案.

接下来我想我会使用Google登录文档中的javascript库.我有这样的事情:

网站客户:

<script type="text/javascript">
function createUser(token)
{
     $.ajax({
       url:"http://api.example.com/user",
       dataType: 'jsonp',
       data: 'token='+token,
       success:function(json){
          alert("Success: "+json);
       },
       error:function(jqXHR, textStatus, errorThrown){
          alert("Error "+textStatus+" "+errorThrown);
       }
     });
}

function signinCallback(authResult)
{
  if(authResult['access_token'])
  {
    document.getElementById('signinButton').setAttribute('style', 'display: none');

    alert('RES: '+JSON.stringify(authResult));
    createUser(authResult['access_token']);
  }
  else if(authResult['error'])
  {
    alert('There was an error: ' + authResult['error']);
  }
}
</script>
Run Code Online (Sandbox Code Playgroud)

Node API用户处理函数:function(req,res){var callback = req.query.callback; if(callback == null){res.send("{valid:false}"); } else {var token = req.query.token;

        if(token == null)
        {
           res.send("{valid:false}");
        }
        else
        {
           var oauth2Client = new OAuth2Client('xxxxxx', 'xxxxxx', '');

           oauth2Client.credentials = {
              access_token: token
           };

           googleapis
              .discover('plus', 'v1')
              .execute(function(err, client){
                 if(client == null)
                 {
                    console.log("Client is null");
                 }
                 else
                 {
                    var request1 = client.plus.people.get({ userId: 'me' })
                    .withApiKey('xxxxxx');

                    request1.execute(function(err, result){
                       console.log("Result: " + (err ? err.message : result.displayName));
                    });
                 }
       });
           res.set('Content-Type', 'text/javascript');
           res.send(callback+"({ret:'User Test'});");
        }
     }
  }
Run Code Online (Sandbox Code Playgroud)

这在客户端工作正常 - 我看到带有访问令牌的警报框和其他一些细节.麻烦的是,当我在我的api服务器上调用google api函数来获取用户详细信息时,我收到了"Invalid Credentials".我假设这是因为我在javascript中为网站生成了访问令牌,而我正在从其他地方使用它.

所以,这几乎让我失去了想法.有没有一种简单的方法可以实现这一目标,我很想念?我只是希望能够从网站和Android应用程序生成令牌,我可以在服务器上使用它来验证用户的详细信息.生成的令牌甚至不需要在网站或Android应用程序上工作,只需从api服务器即可.API服务器无法执行将用户定向到Google进行授权的过程,因为用户不直接与其进行交互.