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);
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)
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);
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.
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.
- Mise À Niveau De Microsoft.Owin to 3.0.1 (Install-Package Microsoft.Owin.Sécurité.OAuth)
- dans la start-up.Auth.cs add facebookOptions.UserInformationEndpoint = " https://graph.facebook.com/v2.4/me?fields=id,nom, courriel ";
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, maisGET /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.