net mvc form example asp and facebook asp.net-mvc-5 owin

facebook - form - security asp net mvc



La autenticación ASP.NET MVC5 OWIN Facebook de repente no funciona (12)

Aunque hice todo lo que dijo sammy34 , no funcionó para mí. Estaba en el mismo punto con HaukurHaf : cuando hago apirequest manualmente en el navegador, funciona perfecto, pero si uso mi aplicación GetExternalLoginInfoAsync() , GetExternalLoginInfoAsync() siempre devuelve null .

Así que cambié algunas filas en los códigos de sammy34 como en este comentario: https://stackoverflow.com/a/43148543/7776015

Reemplazado:

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

En lugar de:

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

Y agregué esta fila en mis FacebookAuthenticationOptions :

UserInformationEndpoint = "https://graph.facebook.com/v2.8/me?fields=id,name,email,first_name,last_name,picture"

y ahora funciona. (campos y parámetros opcionales)

Nota: No actualicé Microsoft.Owin.Security.Facebook

Actualización 2017!

El problema que tuve cuando publiqué la pregunta original no tiene nada que ver con los cambios recientes que hizo Facebook cuando forzaron a todos a la versión 2.3 de su API. Para una solución a ese problema específico, vea la respuesta de sammy34 a continuación . La versión 2.3 del punto final / oauth / access_token ahora devuelve JSON en lugar de valores codificados en forma

Por razones históricas, aquí está mi pregunta / cuestión original:

Tengo una aplicación web MVC5 que está utilizando el soporte integrado para la autenticación a través de Facebook y Google. Cuando construimos esta aplicación hace unos meses, seguimos este tutorial: http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on y todo funcionó muy bien.

Ahora, de repente, la autenticación de Facebook acaba de dejar de funcionar en conjunto. La autenticación de Google todavía funciona de maravilla.

Descripción del problema: Hacemos clic en el enlace para conectarnos a través de Facebook. Nos redirigen a Facebook, donde nos preguntan si queremos permitir que nuestra aplicación de Facebook acceda a nuestro perfil. Cuando hacemos clic en "Aceptar", se nos redirige a nuestro sitio, pero en lugar de iniciar sesión simplemente terminamos en la pantalla de inicio de sesión.

He pasado por este proceso en modo de depuración y obtuve este ActionResult en mi controlador de cuenta según el tutorial mencionado anteriormente:

// GET: /Account/ExternalLoginCallback [AllowAnonymous] public async Task<ActionResult> ExternalLoginCallback(string returnUrl) { var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); if (loginInfo == null) { return RedirectToAction("Login"); } ............

Al recorrer el código y al regresar de Facebook, el objeto loginInfo es siempre NULL, lo que hace que el usuario sea redirigido al inicio de sesión.

Para entender lo que sucede realmente detrás de escena, instalé Fiddler y supervisé el tráfico HTTP. Lo que descubrí es que al hacer clic en "Aceptar" en el cuadro de diálogo de permisos de Facebook, Facebook redirige a nuestra aplicación con esta URL:

https://localhost/signin-facebook?code=<access-token>

Esta URL no es un archivo real y probablemente sea manejada por algún controlador / controlador incorporado en este marco OWIN, supongo. Lo más probable es que se esté conectando nuevamente a Facebook utilizando el código dado para consultar información sobre el usuario que está intentando iniciar sesión. Ahora, el problema es que en lugar de hacer eso, nos redirigen a:

/Account/ExternalLoginCallback?error=access_denied

Lo que estoy seguro es que algo está haciendo Facebook, es decir, en lugar de darnos los datos del usuario, nos redirige con este mensaje de error.

Esto hace que AuthenticationManager.GetExternalLoginInfoAsync(); fallar y siempre devolver NULL.

Estoy completamente sin ideas. Por lo que sabemos, no cambiamos nada de nuestro lado.

Intenté crear una nueva aplicación de Facebook, intenté seguir el tutorial nuevamente, pero siempre tengo el mismo problema.

Cualquier idea bienvenida!

¡Actualizar!

OK, esto me está volviendo loco! Ahora he realizado manualmente los pasos necesarios para realizar la autenticación y todo funciona bien cuando lo hago. ¿Por qué diablos no funciona cuando se usa el MVC5 Owin?

Esto es lo que hice:

// Step 1 - Pasted this into a browser, this returns a code https://www.facebook.com/dialog/oauth?response_type=code&client_id=619359858118523&redirect_uri=https%3A%2F%2Flocalhost%2Fsignin-facebook&scope=&state=u9R1m4iRI6Td4yACEgO99ETQw9NAos06bZWilJxJrXRn1rh4KEQhfuEVAq52UPnUif-lEHgayyWrsrdlW6t3ghLD8iFGX5S2iUBHotyTqCCQ9lx2Nl091pHPIw1N0JV23sc4wYfOs2YU5smyw9MGhcEuinvTAEql2QhBowR62FfU6PY4lA6m8pD3odI5MwBYOMor3eMLu2qnpEk0GekbtTVWgQnKnH6t1UcC6KcNXYY I was redirected back to localhost (which I had shut down at this point to avoid being redirected immediately away). The URL I was redirected to is this: https://localhost/signin-facebook?code=<code-received-removed-for-obvious-reasons> Now, I grabbed the code I got and used it in the URL below: // Step 2 - opened this URL in a browser, and successfully retrieved an access token https://graph.facebook.com/oauth/access_token?client_id=619359858118523&redirect_uri=https://localhost/signin-facebook&client_secret=<client-secret>&code=<code-from-step-1> // Step 3 - Now I''m able to query the facebook graph using the access token from step 2! https://graph.facebook.com/me?access_token=<access-token-from-step-2>

Sin errores, todo funciona genial! Entonces, ¿por qué demonios esto no funciona cuando usas MVC5 Owin? Obviamente, hay algo mal con la implementación de OWin.


Compruebe que obtiene una conexión de internet externa desde su aplicación. Si no, arregle su conexión de internet externa. Mi problema era que estaba usando una instancia de EC2 AWS que de repente dejó de conectarse a Internet. Me tomó un tiempo darme cuenta de que ese era el problema.


Esto me volvió loco. Todo estaba funcionando hasta que me desplegué en mi entorno de ensayo. Estaba usando Microsoft.Owin.Security.Facebook versión 3.0.1 de Nuget. Lo actualicé a la versión preliminar 3.1.0 de Nuget y ya no obtuve el error de acceso denegado ...


He estado trabajando en la solución por tres días. Y acabo de encontrarlo en github ( https://github.com/aspnet/AspNetKatana/issues/38#issuecomment-290400987 )

var facebookOptions = new FacebookAuthenticationOptions() { AppId = "xxxxx", AppSecret = "xxxxx", }; // Set requested scope facebookOptions.Scope.Add("email"); facebookOptions.Scope.Add("public_profile"); // Set requested fields facebookOptions.Fields.Add("email"); facebookOptions.Fields.Add("first_name"); facebookOptions.Fields.Add("last_name"); facebookOptions.Provider = new FacebookAuthenticationProvider() { OnAuthenticated = (context) => { // Attach the access token if you need it later on for calls on behalf of the user 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); var claimType = string.Format("{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 Task.FromResult(0); } }; app.UseFacebookAuthentication(facebookOptions);

Y para obtener valores

var info = await AuthenticationManager.GetExternalLoginInfoAsync(); if (info != null) { var firstName = info.ExternalIdentity.Claims.First(c => c.Type == "first_name").Value; var lastName = info.ExternalIdentity.Claims.First(c => c.Type == "last_name").Value; }


La última actualización de Facebook fue en 2015-02-09 ( https://www.nuget.org/packages/Microsoft.AspNet.WebPages.OAuth/ )

La última versión de la API en ese momento era la versión 2.2. La versión 2.2 expiró el 25 de marzo de 2017, que es coincidentemente cuando comenzó el problema. ( https://developers.facebook.com/docs/apps/changelog )

Supongo que Facebook probablemente actualizó automáticamente la API y ahora la biblioteca MS OAUTH no puede analizar la nueva respuesta.

tldr: la biblioteca OAuth de Microsoft WebPages está desactualizada (al menos para FB) y es probable que tengas que buscar otra solución


Las soluciones anteriores no funcionaron para mí. Al final, parecía estar relacionado con la Sesión. Al "despertar" la sesión en la llamada anterior, ya no devolvería nulo desde GetExternalLoginInfoAsync ()

[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public ActionResult ExternalLogin(string provider, string returnUrl) { Session["WAKEUP"] = "NOW!"; // Request a redirect to the external login provider return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl })); }

Al igual que el OP, hice que la autorización de terceros funcionara bien durante un tiempo prolongado y de repente se detuvo. Creo que fue debido a los cambios realizados en mi código cuando configuré la sesión para usar Redis Cache en Azure.


Noté este problema ayer. Facebook ya no es compatible con Microsoft.Owin.Security.Facebook versión 3.0.1. Para mí funcionó para instalar la versión 3.1.0. Para actualizar a 3.1.0, ejecute el comando Install-Package Microsoft.Owin.Security.Facebook en Package Manager Console: https://www.nuget.org/packages/Microsoft.Owin.Security.Facebook


Ok, tengo una solución al problema.

Este es el código que tenía previamente en mi archivo Startup.Auth.cs:

var x = new FacebookAuthenticationOptions(); //x.Scope.Add("email"); x.AppId = "1442725269277224"; x.AppSecret = "<secret>"; x.Provider = new FacebookAuthenticationProvider() { OnAuthenticated = async context => { //Get the access token from FB and store it in the database and //use FacebookC# SDK to get more information about the user context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken",context.AccessToken)); context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:name", context.Name)); context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:email", context.Email)); } }; x.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie; app.UseFacebookAuthentication(x);

Observe cómo el

x.Scope.Add("email")

línea ha sido comentada, pero aún estoy preguntando por el correo electrónico más tarde en el controlador OnAuthenticated? Sí, eso es correcto. Por alguna razón, esto funcionó perfectamente durante unas semanas.

Mi solución fue simplemente eliminar el comentario de x.Scope.Add ("email"); línea para asegurarse de que la variable scope = email estaba presente en la solicitud inicial a Facebook.

¡Ahora todo funciona como lo hizo!

No puedo entender por qué esto funcionó antes como antes. La única explicación que se me ocurre es que Facebook cambió algo de su parte.


También tuve este problema, pero no fue causado por la configuración del alcance. Me tomó mucho tiempo darme cuenta de eso, pero lo que finalmente me dio una OwinStartup.Configuration(IAppBuilder app) fue establecer un registrador personalizado configurando lo siguiente en OwinStartup.Configuration(IAppBuilder app) .

app.SetLoggerFactory(new LoggerFactory()); // Note: LoggerFactory is my own custom ILoggerFactory

Esto dio como resultado lo siguiente:

2014-05-31 21: 14: 48,508 [8] ERROR
Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware
[(nulo)] - 0x00000000 - Falló la autenticación
System.Net.Http.HttpRequestException: Se produjo un error al enviar la solicitud. ---> System.Net.WebException: el nombre remoto no podría
se resuelva: ''graph.facebook.com'' en
System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult)
en System.Net.Http.HttpClientHandler.GetResponseCallback (IAsyncResult ar) --- Fin de la pila de excepción interna trace --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (Tarea
tarea) en
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task task) en System.Runtime.CompilerServices.TaskAwaiter`1.GetResult () en
Microsoft.Owin.Security.Facebook.FacebookAuthenticationHandler.d__0.MoveNext ()

En función de la pila de llamadas anterior, descubrí que mi VM Azure no pudo resolver graph.facebook.com. Todo lo que tenía que hacer para solucionarlo era ejecutar "ipconfig / registerdns" y todo estaba arreglado ...


También tuve este problema. He leído muchos artículos y temas durante dos días, incluido esto. Ninguno de ellos funcionó para mí. El inicio de sesión de Facebook había funcionado perfectamente antes de la implementación, pero no lo hizo después de eso. Descubrí que algo está mal con mi conexión a Internet de VPS, así que probé NextVPN en mi VPS. Pero cuando intenté iniciar sesión en mi computadora, no había ninguna conexión nueva en ProxiFire interno de NextVPN. Finalmente, instalar OpenVPN en mi VPS solucionó el problema.



Actualización del 22 de abril de 2017: la versión 3.1.0 de los paquetes Microsoft.Owin. * Ya está disponible. Si tienes problemas después de los cambios de la API de Facebook del 27 de marzo de 2017, primero prueba los paquetes NuGet actualizados. En mi caso, resolvieron el problema (funciona bien en nuestros sistemas de producción).

Respuesta original:

En mi caso, me desperté el 28 de marzo de 2017 para descubrir que la autenticación de Facebook de nuestra aplicación había dejado de funcionar de repente. No habíamos cambiado nada en el código de la aplicación.

Resulta que Facebook hizo una "actualización forzosa" de su API gráfica de la versión 2.2 a la 2.3 el 27 de marzo de 2017. Una de las diferencias en estas versiones de la API parece ser que el punto final de Facebook /oauth/access_token no responde más con un cuerpo de contenido codificado en forma, pero con JSON en su lugar.

Ahora, en el middleware de Owin, encontramos que el método protected override FacebookAuthenticationHandler.AuthenticateCoreAsync() , que analiza el cuerpo de la respuesta como un formulario y, posteriormente, utiliza el access_token del formulario analizado. Huelga decir que el formulario analizado está vacío, por lo que access_token también está vacío, lo que provoca un error access_denied más adelante en la cadena.

Para solucionar esto rápidamente, creamos una clase de contenedor para la respuesta de Facebook Oauth

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

Luego, en OwinStart, agregamos un controlador de canal de retorno personalizado ...

app.UseFacebookAuthentication(new FacebookAuthenticationOptions { AppId = "hidden", AppSecret = "hidden", BackchannelHttpHandler = new FacebookBackChannelHandler() });

... donde el controlador se define como:

public class FacebookBackChannelHandler : HttpClientHandler { protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { var result = await base.SendAsync(request, cancellationToken); if (!request.RequestUri.AbsolutePath.Contains("access_token")) return result; // For the access token we need to now deal with the fact that the response is now in JSON format, not form values. Owin looks for form values. 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; } }

Básicamente, el manejador simplemente crea un nuevo HttpResponseMessage que contiene la información codificada en forma equivalente de la respuesta JSON de Facebook. Tenga en cuenta que este código utiliza el popular paquete Json.Net.

Con este controlador personalizado, los problemas parecen estar resueltos (aunque todavía tenemos que implementar :)).

¡Espero que salve a alguien más que se despierta hoy con problemas similares!

Además, si alguien tiene una solución más limpia para esto, ¡me encantaría saberlo!