visual studio por example ejemplo crear autenticacion c# facebook facebook-graph-api asp.net-mvc-5 asp.net-identity-2

c# - studio - web api ejemplo



¿Por qué el nuevo fb api 2.4 devuelve correo electrónico nulo en MVC 5 con Identity y oauth 2? (6)

Lea el changelog , esto es por diseño. Debe solicitar explícitamente los campos y bordes que desea volver a ajustar en la respuesta:

Campos declarativos Para tratar de mejorar el rendimiento en redes móviles, los nodos y bordes en v2.4 requieren que solicite explícitamente los campos que necesita para sus solicitudes GET . Por ejemplo, GET /v2.4/me/feed ya no incluye me gusta y comentarios de forma predeterminada, pero GET /v2.4/me/feed?fields=comments,likes devolverá los datos. Para obtener más detalles, consulte los docs sobre cómo solicitar campos específicos.

Todo solía funcionar perfectamente hasta que fb actualizó su api a 2.4 (tenía 2.3 en mi proyecto anterior).

Hoy, cuando agrego una nueva aplicación en desarrolladores de fb, la obtengo con api 2.4.

El problema: ahora recibo un correo electrónico nulo de fb ( loginInfo.email = null ).

Por supuesto, verifiqué que el correo electrónico del usuario está en estado público en el perfil de fb,

y loginInfo objeto loginInfo pero no encontré ninguna otra dirección de correo electrónico.

y lo busqué en Google pero no encontré ninguna respuesta.

por favor cualquier ayuda ... estoy un poco perdido ...

Gracias,

Mi código original (que funcionó en 2.3 api):

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

En el 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);


Para mí, este problema se resolvió actualizando a Microsoft.Owin.Security.Facebook 3.1.0 y agregando ''correo electrónico'' a la colección 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);


Para resolver esto, necesita instalar el SDK de Facebook desde los paquetes NuGet.

En el archivo de inicio

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

En controlador o ayudante

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

Con esto puede obtener el EmailId, nombre, apellido, género.

También puede agregar sus propiedades adicionales requeridas en esa cadena de consulta.

Espero que esto ayude a alguien.


Solo quiero agregar a la respuesta de Mike que esta línea

facebookOptions.Scope.Add("email");

todavía necesita ser agregado despué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" }

Y si ya registró su cuenta de Facebook en su sitio web de desarrollo sin "permiso de correo electrónico". Después de cambiar el código y volver a intentarlo, aún no recibirá el correo electrónico porque el permiso de correo electrónico no se otorga a su sitio web de desarrollo. La forma en que lo hago es ir a https://www.facebook.com/settings?tab=applications , eliminar mi aplicación de Facebook y volver a hacer el proceso nuevamente.


Tomado de un hilo de Katana, ideé lo siguiente:

Cambie las UserInformationEndpoint FacebookAuthenticationOptions para incluir UserInformationEndpoint y UserInformationEndpoint como se ve a continuación. Asegúrese de incluir los nombres de los campos que desea y necesita para su implementación.

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

Luego, cree un FacebookBackChannelHandler personalizado que interceptará las solicitudes a Facebook y reparará la URL con formato incorrecto según sea necesario.

ACTUALIZACIÓN: FacebookBackChannelHandler se actualiza según una actualización del 27 de marzo de 2017 a la API de FB.

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

Una adición útil sería verificar la versión 3.0.1 de la biblioteca y lanzar una excepción si cambia. De esa manera sabrá si alguien actualiza o actualiza el paquete NuGet después de que se haya publicado una solución para este problema.

(Actualizado a la compilación, funciona en C # 5 sin el nuevo nombre de la función)