OWIN的GetExternalLoginInfoAsync始终返回null

问题描述 投票:65回答:16

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

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

因为它总是为null,所以它只是重定向回登录页面并且过程重新开始。我怎样才能解决这个问题?

c# .net asp.net-mvc owin google-openid
16个回答
100
投票

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

  1. https://console.developers.google.com/project设置Google OpenId帐户
  2. 将回调URL设置为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为您的项目提供的任何端口号。

  1. 启用Google+ API。这是一个隐藏的问题,这是问题的根本原因 - 如果你不这样做,很容易错过对/account/ExternalLoginCallback的请求包括&error=access_denied,这是因为谷歌说否为OWIN为用户的Google+基本个人资料提供的权限请求。我不知道这是谁的错,谷歌或微软的。

要在开发者控制台中启用Google+ API,请点击左侧的API,搜索Google+,点击该按钮,然后点击启用。是的,你真的需要这样做。如果你不这样做,你就被冲洗了。

  1. 将Google在开发人员控制台中为您提供的ClientId和ClientSecret添加到Startup.Auth,但改进过程中的代码以明确使用OAuth2,并明确询问用户的电子邮件地址: 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/externallogincallbackexternalloginconfirmation,因为这些都与/signin-google分开并且在OWIN / Google中必要的步骤处理。


1
投票

对于那些遇到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;
        }

0
投票

虽然上面的答案都很好,但在我的例子中,这些都没有奏效 - 我检查并仔细检查了谷歌的设置,并同意克里斯莫斯基尼认为有很多误导性的信息。

对我而言,当我意识到我的Out of Process状态服务没有开始时,这是一个'那个时刻!没有错误(作为登录是我在重新启动后尝试的第一件事,其中状态服务设置为在机器上手动启动)只是来自GetExternalLoginInfoAsync的Null

希望这有助于其他人。


0
投票

在Stackoverflow上进行了大量的搜索和搔痒以及跟踪无数红鲱鱼答案后,我最终在我的Google开发控制台上查看了所有选项,并在Google + API概述页面上发现了一个蓝色的[启用]按钮。我点击了这个,嘿它presto它工作。忘掉你读到的关于回调网址和路由配置的所有内容,OWIN在任何情况下都会覆盖google默认/ signin-google重定向uri并将你发回到ExternalLoginCallback。只要您启用Google + API,只要坚持默认实施一切都会很好。


0
投票

我也想为这个做出贡献。我刚刚开始工作了。我遇到的问题是GetExternalLoginInfoAsync返回null但仅在生产中。

经过大量的搜索,我终于找到了答案,这只是我数据库的一个问题。在生产中我设置了错误的连接字符串,因此它无法正确连接,但它基本上是无声的。唯一发生的事情是GetExternallLoginInfoAsync返回null。如果发生这种情况,请检查数据库连接字符串

另外在旁注中,使这项工作所需的唯一事情是:

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

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


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


0
投票

对我来说,我正在迁移,但是将.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的类型为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 Pages的样本。我将继续我拥有的东西。

因此,接下来我将研究将其他Google用户JSON有效负载项映射到声明中。我想如果我的谷歌帐户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


-1
投票

所有其他答案都没有为我解决这个问题,所以如果您在同一条船上,请确保您的注册控制器操作具有RequireHttps属性:

    // GET: /Account/LoginRegister
    [AllowAnonymous]
    [RequireHttps]
    public ActionResult LoginRegister()
    {
        return View(new RegisterLoginViewModel());
    }

46
投票

好的,我发现为什么它是空的。您必须在Google控制台中启用Google + API。在将密钥粘贴到代码后,还要确保密钥不与末尾的空格连接。为什么他们不能返回正常错误?我不知道。


19
投票

似乎Nuget包Microsoft.Owin.Security.Facebook 3.0.1版不再适用于Facebook登录。

将此软件包更新到预发布3.1.0版本,您可以使用以下内容:

安装包Microsoft.Owin.Security.Facebook -Pre


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

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


3
投票

我知道这很愚蠢,但经过长时间的努力,重新启动IIS为我解决了这个问题。


3
投票

这解决了我的问题:

启用Google+ API。这是问题,并且是问题的根本原因 - 如果你不这样做,很容易错过对/account/ExternalLoginCallback的请求包括&error=access_denied,那是因为谷歌对OWIN所做的权限请求没有说用户的Google+基本个人资料。我不知道这是谁的错,谷歌或微软的。

要在开发者控制台中启用Google+ API,请点击左侧的API,搜索Google+,点击该按钮,然后点击启用。


3
投票

我通过简单地更新应用程序中的所有块包来实现它的工作。


1
投票

我做了以下工作以使其正常工作。

登录到开发人员门户,找到您的应用程序并执行以下操作。

应用程序详细信息>以应用为中心的列出平台>为网站选择是


1
投票

我今天遇到了这个问题,事实证明我在分配了提供程序后定义了远程cookie。

确保你放置......

app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

之前...

app.UseFacebookAuthentication(
                   appId: "",
                   appSecret: "");
© www.soinside.com 2019 - 2024. All rights reserved.