Pourquoi la nouvelle api FB 2.4 renvoie-t-elle le courriel null sur MVC 5 avec Identity et oauth 2?

tout fonctionnait parfaitement jusqu'à ce que fb mette à jour son api 2.4 (j'ai eu 2.3 dans mon projet précédent).

aujourd'Hui, quand j'ajoute une nouvelle application sur fb développeurs-je l'obtenir avec l'api 2.4.

le problème: maintenant je reçois le courriel null De fb ( loginInfo.email = null ).

bien sûr, j'ai vérifié que l'email de l'utilisateur est en public statut sur fb profil,

et je suis allé sur l'objet loginInfo mais n'ai pas trouvé d'autre adresse e-mail.

et je google que mais n'a pas trouvé de réponse.

merci de toute aide.. Je suis un peu perdu..

Merci,

Mon code d'origine (qui a travaillé sur 2,3 api):

dans le 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
    }
}

dans la start-up.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);
45
demandé sur Dudi 2015-08-17 23:45:16

6 réponses

tiré d'un fil Katana j'ai conçu ce qui suit:

modifier le FacebookAuthenticationOptions pour inclure BackchannelHttpHandler et UserInformationEndpoint comme indiqué ci-dessous. Assurez-vous d'inclure les noms des champs que vous voulez et avez besoin pour votre application.

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"
}

crée alors une custom FacebookBackChannelHandler qui interceptera les requêtes vers Facebook et corrigera l'url mal formée si nécessaire.

mise à jour: le FacebookBackChannelHandler est mis à jour sur la base d'une mise à jour de l'api FB du 27 mars 2017.

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; }
}

un ajout utile serait de vérifier la version 3.0.1 de la bibliothèque et de jeter une exception si et quand elle change. De cette façon, vous saurez si quelqu'un met à jour le paquet NuGet après qu'un correctif pour ce problème a été publié.

(mis à Jour afin de construire, de travailler en C# 5 sans nouvelles nameof)

80
répondu Mike Trionfo 2017-04-08 22:39:19

pour moi ce problème a été résolu en passant à Microsoft.Owin.Security.Facebook 3.1.0 et en ajoutant "email" à la collection Fields :

var options = new FacebookAuthenticationOptions
{
    AppId = "-------",
    AppSecret = "------",    
};
options.Scope.Add("public_profile");
options.Scope.Add("email");

//add this for facebook to actually return the email and name
options.Fields.Add("email");
options.Fields.Add("name");

app.UseFacebookAuthentication(options);
22
répondu Issac 2017-05-07 16:47:15

pour résoudre ce problème, vous avez besoin de installer Facebook SDK à partir des paquets NuGet.

Dans Le Fichier De Démarrage

 app.UseFacebookAuthentication(new FacebookAuthenticationOptions
            {
                AppId = "XXXXXXXXXX",
                AppSecret = "XXXXXXXXXX",
                Scope = { "email" },
                Provider = new FacebookAuthenticationProvider
                {
                    OnAuthenticated = context =>
                    {
                        context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
                        return Task.FromResult(true);
                    }
                }
            });

dans Contrôleur ou Helper

var identity = AuthenticationManager.GetExternalIdentity(DefaultAuthenticationTypes.ExternalCookie);
var accessToken = identity.FindFirstValue("FacebookAccessToken");
var fb = new FacebookClient(accessToken);
dynamic myInfo = fb.Get("/me?fields=email,first_name,last_name,gender"); // specify the email field

avec ceci vous pouvez obtenir L'E-Mail,Le prénom, le sexe.

vous pouvez également ajouter vos propriétés supplémentaires requises dans cette chaîne de requête.

J'espère que cela aidera quelqu'un.

20
répondu Palak Patel 2015-11-23 10:19:17

je veux juste ajouter sur la réponse de Mike que cette ligne

facebookOptions.Scope.Add("email");

doit encore être ajouté après

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,location"
}

et si vous avez déjà enregistré votre compte facebook sur votre site web dev sans"autorisation par e-mail". Après avoir changé le code et essayer de nouveau, vous ne recevrez toujours pas l'email parce que l'autorisation email n'est pas accordée à votre site web dev. La façon dont je fais est d'aller à https://www.facebook.com/settings?tab=applications , supprimer mon application facebook, et refaire le processus à nouveau.

13
répondu paibamboo 2015-12-04 03:34:08
3
répondu Artur Edilyan 2016-08-25 13:37:04

Lire changelog , c'est par conception. Vous devez explicitement demander les champs et les bords que vous voulez retouner dans la réponse:

Champs Déclaratifs Pour essayer d'améliorer les performances sur les réseaux mobiles, Noeuds et arêtes en v2.4 exige que vous demandiez explicitement champ (s) nécessaire (s) pour vos requêtes GET . Par exemple, GET /v2.4/me/feed n'inclut plus les j'aime et les commentaires de par défaut, mais GET /v2.4/me/feed?fields=comments,likes renverra les données. Pour plus d' détails voir le docs sur la façon de demander des champs spécifiques.

1
répondu ifaour 2015-08-21 12:51:07