我创建了一个新的MVC5 Web应用程序,当我尝试使用Google或Facebook登录时,ExternalLoginCallback
中的AccountController
操作被调用,但GetExternalLoginInfoAsync()
始终返回null :
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
因为它总是为null,所以它只是重定向回登录页面并且流程重新开始。我该如何解决这个问题?
答案 0 :(得分:98)
要让OWIN Google登录在标准的Visual Studio 2013,ASP.Net MVC5网站上正常运行,我必须:
将回调网址设置为blah/signin-google
。
您不需要做的事情的重要说明:
您不需要使用HTTPS让Google重定向;您甚至可以重定向回普通http://localhost,没问题。
您不需要为重定向网址设置任何内容 - 在Web.Config中没有路由,控制器操作或特殊权限。重定向网址始终为/ signin-google,OWIN会在幕后为您处理此问题。
例如,如果您的网站是me.com,那么您可能会在Google Developer Console中拥有这3个回调网址:
http://localhost:53859/signin-google
http://test.me.com/signin-google
https://me.com/signin-google
第一个包括VS为您的项目提供的任何端口号。
/account/ExternalLoginCallback
,这是因为Google对用户的Google+基本个人资料提供的权限请求OWIN拒绝。我无法说出这是谁的错,谷歌或微软。要在开发者控制台中启用Google+ API,请点击左侧的API,搜索Google+,点击该按钮,然后点击启用。是的,你真的需要这样做。 如果您不这样做,就会被冲洗。
将Google在开发者控制台中为您提供的ClientId和ClientSecret添加到Startup.Auth,但改进过程中的代码以明确使用OAuth2,并明确要求用户的电子邮件地址:
&error=access_denied
那就是它。最终让它发挥作用。
只想再重申一次,有很多关于此问题的答案以及OWIN / Google无法正常工作的问题,而且目前的VS2013 / MVC5 / OWIN模板几乎都是错误的。
你根本不需要修改Web.Config。
您不需要创建任何特殊的路线。
你不应该试图将var google = new GoogleOAuth2AuthenticationOptions()
{
ClientId = "123abc.apps.googleusercontent.com",
ClientSecret = "456xyz",
Provider = new GoogleOAuth2AuthenticationProvider()
};
google.Scope.Add("email");
app.UseGoogleAuthentication(google);
指向其他地方,或使用不同的回调网址,你绝对不应该尝试将其直接绑定到/signin-google
或{{1因为这些都与/account/externallogincallback
分开,并且是OWIN / Google流程中的必要步骤。
答案 1 :(得分:46)
好的,我发现了为什么它是空的。您必须在Google控制台中启用Google + API。在将密钥粘贴到代码后,还要确保密钥不与末尾的空格连接。为什么他们无法恢复正常错误?我不知道。
答案 2 :(得分:19)
似乎Nuget包Microsoft.Owin.Security.Facebook 3.0.1版不再适用于Facebook登录。
将此软件包更新到3.1.0之前的版本,您可以使用以下内容:
Install-Package Microsoft.Owin.Security.Facebook -Pre
答案 3 :(得分:7)
正如其他人正确提到的那样,大部分时间都是因为您没有Google+ API的权限,所以这里是如何获得Google API管理器中的项目权限到Google+ API
答案 4 :(得分:3)
我知道这很愚蠢,但经过长时间的努力,重新启动IIS为我解决了这个问题。
答案 5 :(得分:3)
这解决了我的问题:
启用Google+ API。这是一个问题,这是问题的根本原因 - 如果你不这样做,很容易错过请求/account/ExternalLoginCallback
包括&error=access_denied
,这是因为谷歌说否为OWIN为用户的Google+基本个人资料提供的权限请求。我不知道这是谁的错,谷歌或微软的。
要在开发者控制台中启用Google+ API,请点击左侧的API,搜索Google+,点击该按钮,然后点击启用。
答案 6 :(得分:3)
我通过简单地更新应用程序中的所有块包来实现它的工作。
答案 7 :(得分:1)
我做了以下工作以使其正常工作。
登录开发人员门户,找到您的应用程序并执行以下操作。
答案 8 :(得分:1)
我今天遇到了这个问题,事实证明我在分配了提供商后定义了远程cookie。
确保放置......
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
...前
app.UseFacebookAuthentication(
appId: "",
appSecret: "");
答案 9 :(得分:1)
对于那些遇到Web Api问题的人。其他解决方案无法帮助AuthenticationManager.GetExternalLoginInfoAsync();
返回始终为null,即使启用了Google + api也是如此。
使用此自定义函数获取logininfo。显然,当通过web api请求时,Microsoft有一个GetExternalLoginInfoAsync的错误。
private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer()
{
ExternalLoginInfo loginInfo = null;
var result = await Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalBearer);
if (result != null && result.Identity != null)
{
var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier);
if (idClaim != null)
{
loginInfo = new ExternalLoginInfo()
{
DefaultUserName = result.Identity.Name == null ? "" : result.Identity.Name.Replace(" ", ""),
Login = new UserLoginInfo(idClaim.Issuer, idClaim.Value)
};
}
}
return loginInfo;
}
答案 10 :(得分:0)
虽然上面的答案都很好,但在我的例子中,这些都没有奏效 - 我检查并仔细检查了谷歌的设置,并同意克里斯莫斯基尼认为有很多误导性的信息。
对我而言,当我意识到我的流程州服务尚未开始时,这是一个'呃!没有错误(作为登录是我在重启后尝试的第一件事,其中状态服务设置为在机器上手动启动)只是来自GetExternalLoginInfoAsync
希望这有助于其他人。
答案 11 :(得分:0)
在Stackoverflow上进行了大量搜索和搔痒以及跟踪无数红鲱鱼答案后,我最终在我的Google开发控制台上查看了所有选项,并在Google + API概述页面上发现了一个蓝色的[启用]按钮。我点击了这个,嘿它presto它工作。忘掉你读到的关于回调网址和路由配置的所有内容,OWIN在任何情况下都会覆盖google默认/ signin-google重定向uri并将你发回到ExternalLoginCallback。只要您启用Google + API,只要坚持默认实施一切都会很好。
答案 12 :(得分:0)
我也想为这个做出贡献。我刚刚开始工作了。我遇到的问题是GetExternalLoginInfoAsync返回null但仅在生产中。
经过大量搜索,我终于找到了答案,这只是我数据库的一个问题。在生产中我设置了错误的连接字符串,因此它无法正确连接,但它基本上是无声的。唯一发生的事情是GetExternallLoginInfoAsync返回null。如果发生这种情况,请检查数据库连接字符串!
同样在旁注中,使这项工作成功的唯一方法是:
您不必启用HTTPS,也不必创建自定义路由。但请确保您的数据库正常运行!
答案 13 :(得分:0)
的确,您将需要Google plus Enabled。对我来说最大的事情是项目URL。在VS中打开属性窗口(“视图”->“属性窗口”),然后右键单击该项目并选择属性。在小型属性窗口中复制SSL URL,然后在较大属性窗口中选择“ Web”选项卡,然后将该URL粘贴到“项目URL”中。
为我修复了此问题。
答案 14 :(得分:0)
对我来说,我虽然很旧,但是正在将.NET 4.6.1 MVC网站迁移到核心1.1。在我恢复正常工作之前,工作就停止了,当我将其备份后,便开始迁移到2.x。
我的问题是Google网站上的404
遇到了来自Google的回调。我以为应该按一下AccountController.ExternalLoginCallback
,所以我给它添加了一个[Route(...)]
,而且确实可以肯定,Google的回调可以实现这一目标。
然后击中此行返回的null
(什么样的疯子会返回null
?)
var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
我对它进行了反向工程,以发现它最终获得ExternalScheme
的处理程序,而对我来说,这是cookie处理程序!
这一切似乎都是错误的,我觉得中间件应该以某种方式截获回调URI,所以我删除了[Route(...)]
,然后又出现了404
问题。
然后我发现我需要在启动过程中添加它。
applicationBuilder.UseAuthentication();
这解决了404
,但又带来了另一个问题。
未指定authenticationScheme,也没有找到DefaultSignInScheme。
通过在此处添加默认方案,我可以解决上述错误。
serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme)
.AddGoogle(googleOptions => Configuration.Bind("OAuth2:Providers:Google", googleOptions))
.AddExternalCookie();
现在AccountController.ExternalLoginCallback
被某种魔术再次调用,但是我回到了null
的返回值。
我将此代码添加到了令人反感的行上方,这实际上是幕后发生的事情(查看GitHub上的Microsoft代码)。有趣的是,h
的类型为CookieAuthenticationHandler
,a
的所有声明和信息都来自Google!
var authHandler = this.HttpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
var h = await authHandler.GetHandlerAsync(this.HttpContext, IdentityConstants.ExternalScheme);
var a = await h.AuthenticateAsync();
var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
深入GitHub并将其内部运行代码粘贴到我的控制器中,可以发现它在我的声明中找不到ClaimTypes.NameIdentifier
,这是以后使用的ProviderKey
。
嗯......
关于我正在使用旧的1.x AccountController
代码和更新的2.x标识位,我确实找到了一些仍在使用这些东西的示例,以及一些同样使用Razor页面的示例。我将继续我拥有的东西。
因此,我接下来将研究将其他Google用户JSON有效负载项目映射到声明中。我认为,如果我的Google帐户ID(我想是数字)已映射,则一切正常。
最终修订
我终于解决了该问题,添加了“声明操作”,将我的Google标识符从Google传回的JSON中拉出来!
serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme)
.AddGoogle(googleOptions =>
{
Configuration.Bind("OAuth2:Providers:Google", googleOptions);
googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
})
.AddExternalCookie();
sub
字段包含最终出现在nameidentifier
声明中,然后到ProviderKey
想要的AccountController
中的内容。
答案 15 :(得分:-1)
所有其他答案都没有解决这个问题,所以如果您在同一条船上,请确保您的注册控制器操作具有RequireHttps属性:
// GET: /Account/LoginRegister
[AllowAnonymous]
[RequireHttps]
public ActionResult LoginRegister()
{
return View(new RegisterLoginViewModel());
}