我创建了一个新的MVC5 Web应用程序,当我尝试使用Google或Facebook登录时,调用ExternalLoginCallback
中的AccountController
Action,但GetExternalLoginInfoAsync()
始终返回null:
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
因为它总是为null,所以它只是重定向回登录页面并且过程重新开始。我怎样才能解决这个问题?
要让OWIN Google登录在标准的Visual Studio 2013,ASP.Net MVC5网站上正常运行,我必须:
blah/signin-google
。
关于您不需要做的事情的重要说明:
您无需使用HTTPS即可将Google重定向回来;你甚至可以重定向到普通的http://localhost,没问题。
您无需为重定向URL设置任何内容 - 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
的请求包括&error=access_denied
,这是因为谷歌说否为OWIN为用户的Google+基本个人资料提供的权限请求。我不知道这是谁的错,谷歌或微软的。要在开发者控制台中启用Google+ API,请点击左侧的API,搜索Google+,点击该按钮,然后点击启用。是的,你真的需要这样做。如果你不这样做,你就被冲洗了。
var google = new GoogleOAuth2AuthenticationOptions()
{
ClientId = "123abc.apps.googleusercontent.com",
ClientSecret = "456xyz",
Provider = new GoogleOAuth2AuthenticationProvider()
};
google.Scope.Add("email");
app.UseGoogleAuthentication(google);
而已。这终于让它运转了。
只想再重申一次,有很多关于此问题的答案以及OWIN / Google无法正常工作的问题,而且目前的VS2013 / MVC5 / OWIN模板几乎都是错误的。
您根本不需要修改Web.Config。
您无需创建任何特殊路由。
你不应该试图将/signin-google
指向另一个地方,或者使用不同的回调网址,你绝对不应该试图将它直接绑定到/account/externallogincallback
或externalloginconfirmation
,因为这些都与/signin-google
分开并且在OWIN / Google中必要的步骤处理。
对于那些遇到Web Api问题的人。其他解决方案没有帮助AuthenticationManager.GetExternalLoginInfoAsync();
返回始终为null甚至谷歌+ 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;
}
虽然上面的答案都很好,但在我的例子中,这些都没有奏效 - 我检查并仔细检查了谷歌的设置,并同意克里斯莫斯基尼认为有很多误导性的信息。
对我而言,当我意识到我的Out of Process状态服务没有开始时,这是一个'那个时刻!没有错误(作为登录是我在重新启动后尝试的第一件事,其中状态服务设置为在机器上手动启动)只是来自GetExternalLoginInfoAsync
的Null
希望这有助于其他人。
在Stackoverflow上进行了大量的搜索和搔痒以及跟踪无数红鲱鱼答案后,我最终在我的Google开发控制台上查看了所有选项,并在Google + API概述页面上发现了一个蓝色的[启用]按钮。我点击了这个,嘿它presto它工作。忘掉你读到的关于回调网址和路由配置的所有内容,OWIN在任何情况下都会覆盖google默认/ signin-google重定向uri并将你发回到ExternalLoginCallback。只要您启用Google + API,只要坚持默认实施一切都会很好。
我也想为这个做出贡献。我刚刚开始工作了。我遇到的问题是GetExternalLoginInfoAsync返回null但仅在生产中。
经过大量的搜索,我终于找到了答案,这只是我数据库的一个问题。在生产中我设置了错误的连接字符串,因此它无法正确连接,但它基本上是无声的。唯一发生的事情是GetExternallLoginInfoAsync返回null。如果发生这种情况,请检查数据库连接字符串
另外在旁注中,使这项工作所需的唯一事情是:
您不必启用HTTPS,也不必创建自定义路由。但请确保您的数据库正常运行!
确实,您需要Google plus Enabled。对我来说最重要的是项目URL。在VS中打开属性窗口(视图 - >属性窗口),然后右键单击项目并选择属性。在小属性窗口中复制您的SSL URL,然后在较大的属性窗口中选择Web选项卡并将该URL粘贴到项目URL中。
解决了我的问题。
对我来说,我正在迁移,但是将.NET 4.6.1 MVC网站运行到核心1.1。工作在我开始工作之前停止了,当我把它拿回来时,我正在迁移到2.x.
我的问题是来自谷歌的回调来自我的网站的404
。我认为应该打AccountController.ExternalLoginCallback
所以我添加了一个[Route(...)]
,果然,谷歌的回调击中了行动。
然后击中了在这一行返回的null
(什么样的疯子返回null
?)
var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
我对它进行了反向设计以找到它最终获得ExternalScheme
的处理程序,这对我来说是饼干处理程序!
这一切似乎都是错误的,我觉得中间件应该只是拦截回调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上查看微软的代码)。有趣的是,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 Pages的样本。我将继续我拥有的东西。
因此,接下来我将研究将其他Google用户JSON有效负载项映射到声明中。我想如果我的谷歌帐户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
。
所有其他答案都没有为我解决这个问题,所以如果您在同一条船上,请确保您的注册控制器操作具有RequireHttps属性:
// GET: /Account/LoginRegister
[AllowAnonymous]
[RequireHttps]
public ActionResult LoginRegister()
{
return View(new RegisterLoginViewModel());
}
好的,我发现为什么它是空的。您必须在Google控制台中启用Google + API。在将密钥粘贴到代码后,还要确保密钥不与末尾的空格连接。为什么他们不能返回正常错误?我不知道。
似乎Nuget包Microsoft.Owin.Security.Facebook 3.0.1版不再适用于Facebook登录。
将此软件包更新到预发布3.1.0版本,您可以使用以下内容:
安装包Microsoft.Owin.Security.Facebook -Pre
我知道这很愚蠢,但经过长时间的努力,重新启动IIS为我解决了这个问题。
这解决了我的问题:
启用Google+ API。这是问题,并且是问题的根本原因 - 如果你不这样做,很容易错过对/account/ExternalLoginCallback
的请求包括&error=access_denied
,那是因为谷歌对OWIN所做的权限请求没有说用户的Google+基本个人资料。我不知道这是谁的错,谷歌或微软的。
要在开发者控制台中启用Google+ API,请点击左侧的API,搜索Google+,点击该按钮,然后点击启用。
我通过简单地更新应用程序中的所有块包来实现它的工作。
我做了以下工作以使其正常工作。
登录到开发人员门户,找到您的应用程序并执行以下操作。
我今天遇到了这个问题,事实证明我在分配了提供程序后定义了远程cookie。
确保你放置......
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
之前...
app.UseFacebookAuthentication(
appId: "",
appSecret: "");