我正在使用带有Passport的Sails进行身份验证。我正在使用passport-google-oauth(OAuth2Strategy)和passport-facebook来启用Google登录。
我对Passport并不太熟悉,所以请原谅我,如果这是一个菜鸟问题。我通过Facebook设置了登录,它运行得很好。使用Google,我确实在允许访问应用程序后收到了授权码,但我最终没有通过身份验证。我猜这些代码应该适用于Facebook和Google,因为这些策略都基于oauth2。
我甚至不确定要分享哪些代码,因为我正在使用sails-generate-auth中自动生成的代码,但如果还有其他任何我可以分享的内容,请告诉我。
关于为什么会发生这种情况的任何想法?该应用程序是本地托管的,但这不太可能成为问题,因为无论如何我都要进入授权阶段。
答案 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 fired和the 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
这是我追捕的结束,错误搜索的第一个结果导致了正确答案。奇怪的是修复了。