OWIN的GetExternalLoginInfoAsync始终返回null

时间:2013-11-04 19:18:17

标签: c# .net asp.net-mvc owin google-openid

我创建了一个新的MVC5 Web应用程序,当我尝试使用Google或Facebook登录时,ExternalLoginCallback中的AccountController操作被调用,但GetExternalLoginInfoAsync()始终返回null :

var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
    return RedirectToAction("Login");
}

因为它总是为null,所以它只是重定向回登录页面并且流程重新开始。我该如何解决这个问题?

16 个答案:

答案 0 :(得分:98)

要让OWIN Google登录在标准的Visual Studio 2013,ASP.Net MVC5网站上正常运行,我必须:

  1. https://console.developers.google.com/project

  2. 设置Google OpenId帐户
  3. 将回调网址设置为blah/signin-google
    需要做的事情的重要说明:

    • 您不需要使用HTTPS让Google重定向;您甚至可以重定向回普通http://localhost,没问题。

    • 您不需要为重定向网址设置任何内容 - 在Web.Config中没有路由,控制器操作或特殊权限。重定向网址始终为/ signin-google,OWIN会在幕后为您处理此问题。

  4. 例如,如果您的网站是me.com,那么您可能会在Google Developer Console中拥有这3个回调网址:

    http://localhost:53859/signin-google
    http://test.me.com/signin-google
    https://me.com/signin-google
    

    第一个包括VS为您的项目提供的任何端口号。

    1. 启用Google+ API 。这是一个隐藏的问题,这是问题的根本原因 - 如果你不这样做,很容易错过请求{{1 }}包括/account/ExternalLoginCallback,这是因为Google对用户的Google+基本个人资料提供的权限请求OWIN拒绝。我无法说出这是谁的错,谷歌或微软。
    2. 要在开发者控制台中启用Google+ API,请点击左侧的API,搜索Google+,点击该按钮,然后点击启用。是的,你真的需要这样做。 如果您不这样做,就会被冲洗。

      1. 将Google在开发者控制台中为您提供的ClientId和ClientSecret添加到Startup.Auth,但改进过程中的代码以明确使用OAuth2,并明确要求用户的电子邮件地址:

        &error=access_denied
      2. 那就是它。最终让它发挥作用。

        只想再重申一次,有很多关于此问题的答案以及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

第1步。从顶部组合框中选择您的项目,然后转到信息中心>启用API enter image description here

第2步:搜索Google plus并选择它 enter image description here

第3步:启用它! enter image description here

如果您返回该项目的仪表板,您可以在底部看到该项目的已启用API列表 enter image description here

答案 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。如果发生这种情况,请检查数据库连接字符串!

同样在旁注中,使这项工作成功的唯一方法是:

  • 在Google控制台中设置项目
  • 启用Google+ API
  • 将您的客户端ID和客户端密钥复制到Startup.Auth.cs文件。

您不必启用HTTPS,也不必创建自定义路由。但请确保您的数据库正常运行!

答案 13 :(得分:0)

的确,您将需要Google plus Enabled。对我来说最大的事情是项目URL。在VS中打开属性窗口(“视图”->“属性窗口”),然后右键单击该项目并选择属性。在小型属性窗口中复制SSL URL,然后在较大属性窗口中选择“ Web”选项卡,然后将该URL粘贴到“项目URL”中。

为我修复了此问题。

详细信息:https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on

答案 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的类型为CookieAuthenticationHandlera的所有声明和信息都来自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(我想是数字)已映射,则一切正常。

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/additional-claims?view=aspnetcore-2.2

最终修订

我终于解决了该问题,添加了“声明操作”,将我的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());
    }