c# - 为什么新的 fb api 2.4 在具有身份和 oauth 2 的 MVC 5 上返回空电子邮件?

标签 c# facebook facebook-graph-api asp.net-mvc-5 asp.net-identity-2

在 fb 将它的 api 升级到 2.4 之前,一切都很完美(我之前的版本是 2.3项目)。

今天,当我在 fb developers 上添加一个新应用程序时,我使用 api 2.4 获得了它。

问题:现在我从 fb (loginInfo.email = null) 收到空电子邮件。

当然我检查了用户电子邮件在 fb 个人资料上处于公开状态,

我查看了 loginInfo 对象,但没有找到任何其他电子邮件地址。

我用谷歌搜索但没有找到任何答案。

请帮忙..我有点迷路..

谢谢,

我的原始代码(适用于 2.3 api):

在 AccountController.cs 中:

//
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        return RedirectToAction("Login");
    }
    //A way to get fb details about the log-in user: 
    //var firstNameClaim = loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:first_name");  <--worked only on 2.3
    //var firstNameClaim = loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:name"); <--works on 2.4 api

    // Sign in the user with this external login provider if the user already has a login
    var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
    switch (result)
    {
        case SignInStatus.Success:
            return RedirectToLocal(returnUrl);
        case SignInStatus.LockedOut:
            return View("Lockout");
        case SignInStatus.RequiresVerification:
            return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
        case SignInStatus.Failure:
        default:
            // If the user does not have an account, then prompt the user to create an account
            ViewBag.ReturnUrl = returnUrl;
            ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
            return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });  //<---DOESN'T WORK. loginInfo.Email IS NULL
    }
}

在 Startup.Auth.cs 中:

    Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions fbOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions()
    {
        AppId = System.Configuration.ConfigurationManager.AppSettings.Get("FacebookAppId"),
        AppSecret = System.Configuration.ConfigurationManager.AppSettings.Get("FacebookAppSecret"),
    };
    fbOptions.Scope.Add("email");
    fbOptions.Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
    {
        OnAuthenticated = (context) =>
        {
            context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
            foreach (var claim in context.User)
            {
                var claimType = string.Format("urn:facebook:{0}", claim.Key);
                string claimValue = claim.Value.ToString();
                if (!context.Identity.HasClaim(claimType, claimValue))
                    context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));

            }
            return System.Threading.Tasks.Task.FromResult(0);
        }
    };
    fbOptions.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
    app.UseFacebookAuthentication(fbOptions);

最佳答案

取自Katana Thread我设计了以下内容:

更改 FacebookAuthenticationOptions 以包含 BackchannelHttpHandlerUserInformationEndpoint,如下所示。确保包含您想要和实现所需的字段名称。

var facebookOptions = new FacebookAuthenticationOptions()
{
    AppId = "*",
    AppSecret = "*",
    BackchannelHttpHandler = new FacebookBackChannelHandler(),
    UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=id,name,email,first_name,last_name"
}

然后创建一个自定义 FacebookBackChannelHandler,它将拦截对 Facebook 的请求并根据需要修复格式错误的 url。

更新:FacebookBackChannelHandler 根据 2017 年 3 月 27 日对 FB api 的更新进行了更新。

public class FacebookBackChannelHandler : HttpClientHandler
{
    protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        if (!request.RequestUri.AbsolutePath.Contains("/oauth"))
        {
            request.RequestUri = new Uri(request.RequestUri.AbsoluteUri.Replace("?access_token", "&access_token"));
        }

        var result = await base.SendAsync(request, cancellationToken);
        if (!request.RequestUri.AbsolutePath.Contains("/oauth"))
        {
            return result;
        }

        var content = await result.Content.ReadAsStringAsync();
        var facebookOauthResponse = JsonConvert.DeserializeObject<FacebookOauthResponse>(content);

        var outgoingQueryString = HttpUtility.ParseQueryString(string.Empty);
        outgoingQueryString.Add("access_token", facebookOauthResponse.access_token);
        outgoingQueryString.Add("expires_in", facebookOauthResponse.expires_in + string.Empty);
        outgoingQueryString.Add("token_type", facebookOauthResponse.token_type);
        var postdata = outgoingQueryString.ToString();

        var modifiedResult = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent(postdata)
        };

        return modifiedResult;
    }
}

public class FacebookOauthResponse
{
    public string access_token { get; set; }
    public string token_type { get; set; }
    public int expires_in { get; set; }
}

一个有用的补充是检查库的版本 3.0.1 并在它发生变化时抛出异常。这样你就会知道是否有人在发布此问题的修复程序后升级或更新 NuGet 包。

(更新为构建,在没有新名称功能的情况下在 C# 5 中工作)

关于c# - 为什么新的 fb api 2.4 在具有身份和 oauth 2 的 MVC 5 上返回空电子邮件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32059384/

相关文章:

c# - 更改 PDF - 文本重新定位

使用 Open Graph 的 iOS Facebook 发布失败 - 错误代码 102

facebook - 有没有办法获取特定城市的所有 Facebook 事件?

facebook - 使用组别名通过 Graph API 获取组对象?

php - Facebook OAuth,找不到页面

c# - CORS asp.net 核心 webapi - 缺少 Access-Control-Allow-Origin header

c# - FluentValidation 命令验证器未由 AutoFac 注册

c# - 当应用程序以 xsession 启动时如何全屏显示 GTK# 窗口?

java - Facebook 登录无法正常工作(解析)

php - 如何从 Facebook 个人资料或页面 URL 获取数字 ID? PHP,Facebook 图形 API