如何在 MVC 中的 OAuth 期间获取 Facebook/Google/Twitter 详细信息?

How do I get Facebook/Google/Twitter details during OAuth in MVC?

我意识到这个问题在过去 10 年里被问到并得到了很多回答,但我需要一个比我能找到的大多数答案都更现代的答案。

我有一个 ASP.Net MVC 项目 (C#),并已按照 MS 指南启用 Facebook 和 Google+ 身份验证。这非常简单,在提供程序中注册应用程序并在 startup.auth.cs 中取消注释每行三行 - 非常非常简单。它也“正常工作”,bango 我在数据库中创建了可以通过这些提供商登录的新用户。奇妙吧。

像许多应用程序一样,尽管我需要的不仅仅是身份验证,我还需要少量身份信息 - 名字、姓氏、电子邮件、生日、可用的个人资料图片。

在 FacebookAuthenticationOptions 中结合使用 Scope 和 Fields 我已经设法让 Facebook 授权屏幕警告用户该应用程序想要他们的生日,但我可能会尝试我无法在任何地方找到此信息在 OAuth 过程中返回或任何可能代表我要求的六个其他字段的声明。

许多在线“解决方案”讨论了覆盖 FacebookAuthenticationOptions.Provider(这是一个 FacebookAuthenticationProvider)的“OnAuthenticated”委托。我已经粘贴了一些偷来的代码,但它从未在那里遇到断点。

在我与 Facebook 合作后,我曾希望与 Google+、Twitter 和 Microsoft 帐户提供商重复,我希望这是一种标准化方法,我可以告诉每个提供商我的字段想要他们的格式,然后在某处使用标准 getter 将它们全部取出。据我了解,这实际上是 OAuth 的全部基础点 - 不?

所以在我的startup.auth.cs(当然是假身份证和秘密):

app.UseFacebookAuthentication(new FacebookAuthenticationOptions
      {
        AppId = "xxxxxxxxxxx",
        AppSecret = "xxxxxxxxxxxxxxxxxxxxx",
        Scope = { "user_birthday", "public_profile", "email" },
        Fields = { "user_birthday", "picture", "name", "email", "gender", "first_name", "last_name" },
        Provider = new FacebookAuthenticationProvider
        { 
          OnAuthenticated = async ctx =>
          {
            Console.WriteLine("auth"); //this breakpoint never hits
            ctx.Identity.AddClaim(new Claim("FacebookAccessToken", ctx.AccessToken));
            foreach (var claim in ctx.User)
            {
              var claimType = string.Format("urn:facebook:{0}", claim.Key);
              string claimValue = claim.Value.ToString();

              if (!ctx.Identity.HasClaim(claimType, claimValue))
              {
                ctx.Identity.AddClaim(new Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
              }
            }
          }

        }
      });

感谢@Jeremy Thompson 在评论中指出我最初认为只是我一开始偷的同一件东西的另一个副本,但实际上促使我以某种方式自己解决这个问题。

Jeremy 链接到“有效”的解决方案,除了触发 OnAuthenticated 方法外,它看起来很像我的原始代码。不幸的是它实际上并没有生日,所以我添加了它,然后它停止了工作。啊哈...

所以对我是如何做到这一点的,问题似乎是发生了一个静默异常,它阻止了这个 OnAuthenticated 触发,在我的情况下,这是因为我的字段名称不正确。这是工作代码,其中 returns 我的姓名、电子邮件、生日、当前城镇和个人资料图片(在您自己的系统中创建个人资料所需的要素!)

在 OWIN 启动 class 当然:

app.UseFacebookAuthentication(new FacebookAuthenticationOptions
      {
        AppId = "...", //Your App Id of course
        AppSecret = "...", //Your App Secret of course
        Scope = { "user_birthday", "public_profile", "email", "user_gender", "user_location" },
        Fields = { "birthday", "picture", "name", "email", "gender", "first_name", "last_name", "location" }, //notice the fields are not prefixed with "user_". This was 
        Provider = new FacebookAuthenticationProvider
        {
          OnAuthenticated = async ctx =>
          {
            ctx.Identity.AddClaim(new Claim("FacebookAccessToken", ctx.AccessToken));
            foreach (var claim in ctx.User)
            {
              var claimType = string.Format("urn:facebook:{0}", claim.Key);
              string claimValue = claim.Value.ToString();

              if (!ctx.Identity.HasClaim(claimType, claimValue))
              {
                ctx.Identity.AddClaim(new Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
              }
            }
          }

        }
      });

现在,在我的 AccountController 的 ExternalLoginCallback 函数中,我可以通过查看 loginInfo.Claims 属性(如下所示的 loginInfo)来访问大量属性。

      var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();