我正在使用Sails with Passport进行身份验证。我正在使用passport-google-oauth(OAuth2Strategy)和passport-facebook来启用Google登录。
我不太熟悉Passport,如果这是一个菜鸟问题,请原谅。我已经通过Facebook设置了登录名,并且效果很好。使用Google,在允许访问该应用程序后,我确实会收到授权码,但最终我没有通过身份验证。我猜测相同的代码应同时适用于Facebook和Google,因为这些策略均基于oauth2。
我什至不知道共享什么代码,因为我使用的是Sails-generate-auth的自动生成的代码,但是请告诉我是否还有其他可以共享的代码。
关于为什么会发生这种情况的任何想法?该应用程序是本地托管的,但这不太可能成为问题,因为无论如何我都进入了授权阶段。
我遇到了同样的问题,它位于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。
好,因此最终证明这是API的已知问题。
TL; DR:如here所述,启用Google+ API和Contacts API。 (不必使用Contacts API,正如@ AlexisN-o在评论中指出的那样。我的设置在禁用Contacts API的情况下可以正常工作。这显然取决于您使用的范围。)
我相信这不是失败的好方法,因为这是一个API错误,可以防止它冒泡。无论如何,我挖了passport.authenticate
以找出问题所在。最终,这将调用与策略相对应的包中定义的authenticate
方法(在这种情况下为oauth2)。在这里(passport-google-oauth/lib/passport-google-oauth/oauth2.js
)中,我发现accessToken
确实是从Google处获取的,因此一切正常。这表明对令牌URL的请求存在问题。因此,我进一步冒险进入passport-oauth2/lib/strategy.js
,最后设法记录了此错误:
{ [InternalOAuthError: failed to fetch user profile]
name: 'InternalOAuthError',
message: 'failed to fetch user profile',
oauthError:
{ statusCode: 403,
data: '{
"error": {
"errors": [{
"domain": "usageLimits",
"reason": "accessNotConfigured",
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration.",
"extendedHelp": "https://console.developers.google.com"
}],
"code": 403,
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration."
}
}'
} }
这对我来说是狩猎的结尾,错误搜索的第一个结果导致了正确的答案。不过很奇怪。
我遇到了同样的问题,并通过执行此操作解决了问题:
在package.json中,将“ passport”值更改为“ ^ 0.4.0”,将“ passport-google-oauth”更改为“ ^ 2.0.0”。再次运行“ npm install”。