使用Passportjs进行Google登录未通过身份验证

时间:2015-07-29 23:42:03

标签: sails.js passport-google-oauth

我正在使用带有Passport的Sails进行身份验证。我正在使用passport-google-oauth(OAuth2Strategy)和passport-facebook来启用Google登录。

我对Passport并不太熟悉,所以请原谅我,如果这是一个菜鸟问题。我通过Facebook设置了登录,它运行得很好。使用Google,我确实在允许访问应用程序后收到了授权码,但我最终没有通过身份验证。我猜这些代码应该适用于Facebook和Google,因为这些策略都基于oauth2。

我甚至不确定要分享哪些代码,因为我正在使用sails-generate-auth中自动生成的代码,但如果还有其他任何我可以分享的内容,请告诉我。

关于为什么会发生这种情况的任何想法?该应用程序是本地托管的,但这不太可能成为问题,因为无论如何我都要进入授权阶段。

2 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,它位于here in in api/services/passport.js

// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
  user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
  user.username = profile.username;
}

// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
  return next(new Error('Neither a username nor email was available'));
}

Google服务未返回profile.username媒体资源

因此,用户不会保存在数据库中,也无法进行身份验证。然后是护照回拨receives an empty user,所以the function that handles errors is firedthe user is redirected to the login page

此更改允许将displayName属性用作username

// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
  user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
  user.username = profile.username;
}


/** Content not generated BEGIN */
// If the username property was empty and the profile object
// contains a property "displayName", add it to the user.
if (!user.username && profile.hasOwnProperty('displayName')) {
  console.log(profile);  // <= Use it to check the content given by Google about the user
  user.username = profile.displayName;
}
/** Content not generated END */


// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
  return next(new Error('Neither a username nor email was available'));
}

您还可以使用profile.id属性,因为profile.displayName不一定是唯一的(即:两个Google帐户可以具有相同的displayName)。但在不同的服务中也是如此: Twitter 帐户也可以拥有与 Facebook 帐户相同的用户名。如果两者都在您的应用程序上注册,您将遇到错误。这是sails-generate-auth生成的代码中的一个问题,您应该根据需要调整它。

如果这个解决方案也适用于你,我会提出PR。

答案 1 :(得分:1)

好吧,所以这最终证明是API的一个已知问题。

TL; DR:按照here启用Google+ API和Contacts API。 (联系人API不是必需的,正如@ AlexisN-o在评论中指出的那样。我的设置可以根据需要禁用Contacts API。这显然取决于您使用的范围。)

我认为这不是一个很好的失败方法,因为这是一个API错误,无法冒泡。无论如何,我挖出var centroidCoord = R.converge( R.divide, R.compose( R.sum, R.map( R.converge( R.multiply, R.converge(R.add, R.__, R.__), diffOfProducts ) ), makeVertexPairs ), sixTimesPolyArea ); Geom.centroid = R.curry(function(vertices) { return [ centroidX(x1, x2, vertices), centroidY(y1, y2, vertices) ]; }); 来弄清楚出了什么问题。这最终调用与策略对应的包中定义的passport.authenticate方法(在本例中为oauth2)。在这里(authenticate),我发现passport-google-oauth/lib/passport-google-oauth/oauth2.js确实是从Google获取的,所以事情应该有效。这表明对令牌网址的请求存在问题。所以我进一步冒险进入accessToken并最终成功记录了这个错误:

passport-oauth2/lib/strategy.js

这是我追捕的结束,错误搜索的第一个结果导致了正确答案。奇怪的是修复了。