版本弃用Facebook Graph API v2.2

时间:2017-03-27 23:53:36

标签: asp.net-mvc facebook facebook-graph-api asp.net-mvc-5

我们的Facebook登录目前无效。我们收到了Facebook Developer Portal的消息:

  

“应用程序名称”目前可以访问Graph API v2.2,该API将到达其末尾   2017年3月27日为期2年。为确保顺利过渡,   请将所有调用迁移到Graph API v2.3或更高版本。

     

要检查您的应用是否会受到此升级的影响,您可以使用   版本升级工具。这将显示哪些呼叫(如果有)   受此更改影响以及更新的更换电话   版本。如果您没有看到任何电话,您的应用可能不会受到影响   这种变化。

     

您还可以使用我们的更改日志查看所有更改的完整列表   图谱API版本。

我们正在使用ASP.NET MVC 5,我们正在使用或认证如下:

var facebookAuthenticationOptions = new FacebookAuthenticationOptions()
            {
                AppId = "****",
                AppSecret = "****",
                AuthenticationType = "Facebook",
                SignInAsAuthenticationType = "ExternalCookie",
                Provider = new FacebookAuthenticationProvider
                {
                    OnAuthenticated = async ctx => ctx.Identity.AddClaim(new Claim(ClaimTypes.Email, ctx.User["email"].ToString()))
                }
            };

            facebookAuthenticationOptions.Scope.Add("email");

但今天,我们的登录信息对象在ExternalLoginCallback中为空:

        [HttpGet]
        [AllowAnonymous]
        [RequireHttps]
        public async Task<ActionResult> ExternalLoginCallback(string returnUrl = null)
        {
            try
            {
                var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
                if (loginInfo == null)
                {
                    return RedirectToAction("Login");
                }
... more code here...

在Facebook Dev。 Portal我们的API版本是2.3

我们测试了很多选项,没有结果:

Access email address in the OAuth ExternalLoginCallback from Facebook v2.4 API in ASP.NET MVC 5

Why new fb api 2.4 returns null email on MVC 5 with Identity and oauth 2?

非常感谢您的帮助。

3 个答案:

答案 0 :(得分:10)

我遇到了同样的问题,这就是我如何设法修复它并从Facebook获取电子邮件。

  • 更新NuGet Pacakges
    • Microsoft.Owin到版本3.1.0-rc1
    • Microsoft.Owin.Security到版本3.1.0-rc1
    • Microsoft.Owin.Security.Cookies到版本3.1.0-rc1
    • Microsoft.Owin.Security.OAuth到版本3.1.0-rc1
    • Microsoft.Owin.Security.Facebook到版本3.1.0-rc1

然后将以下代码添加到Identity Startup

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

        app.UseFacebookAuthentication(facebookOptions);

这是FacebookBackChannelHandler()的定义类:

using System;
using System.Net.Http;

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

        return await base.SendAsync(request, cancellationToken);
    }
}

答案 1 :(得分:0)

只需更新与OWIN相关的所有参考 最新的OWIN版本是3.1.0rc1。

这修复了登录按钮,而不是电子邮件,我无法弄清楚这些问题。

答案 2 :(得分:0)

如果由于语言包而无法更新OWIn包(我的情况),你可以

  1. 修改Identity Startup类代码:

    var facebookOptions = new FacebookAuthenticationOptions()
    {
        AppId = "your app id",
        AppSecret = "your app secret",
        BackchannelHttpHandler = new FacebookBackChannelHandler(),
        UserInformationEndpoint = "https://graph.facebook.com/v2.8/me?fields=id,name,email,first_name,last_name",
        Scope = { "email" }
    };
    
    app.UseFacebookAuthentication(facebookOptions);
    
  2. 这是FacebookBackChannelHandler()的定义类:

    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(nameof(facebookOauthResponse.access_token), facebookOauthResponse.access_token);
            outgoingQueryString.Add(nameof(facebookOauthResponse.expires_in), facebookOauthResponse.expires_in + string.Empty);
            outgoingQueryString.Add(nameof(facebookOauthResponse.token_type), facebookOauthResponse.token_type);
            var postdata = outgoingQueryString.ToString();
    
            var modifiedResult = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(postdata)
            };
    
            return modifiedResult;
        }
    }
    
    private class FacebookOauthResponse
    {
        public string access_token { get; set; }
        public long expires_in { get; set; }
        public string token_type { get; set; }
    }