MVC 5 Owin Facebook Auth resultados en la excepción de referencia nula

Estoy intentando configurar la autenticación OWIN de Facebook integrada en un nuevo proyecto de MVC 5 en Visual Studio 2013. He configurado aplicaciones y claves de acuerdo con 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

Sin embargo, obtengo una NullReferenceException lanzada desde esta llamada en AccountController:

[AllowAnonymous] public async Task ExternalLoginCallback(string returnUrl) { var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); 

Ya he comprobado la respuesta en Fiddler y recibo lo que parece ser una respuesta exitosa de Facebook, pero sigo teniendo este error. La respuesta es así:

 {"id":"xxx","name":"xxx","first_name":"xxx","last_name":"xxx","link": "https:\/\/www.facebook.com\/profile.php?id=xxx","location":{"id":"xxx","name":"xxx"}, "gender":"xxx","timezone":1,"locale":"en_GB","verified":true,"updated_time":"2013-10-23T10:42:23+0000"} 

Lo consigo al depurar en http y https. Supongo que esto es un error en el framework, pero hasta ahora me ha quedado un espacio en blanco al diagnosticar esto a través del reflector.

Probablemente esto sea un error en el código de extensión de identidad OWIN. No puedo reproducir el problema ya que mi carga de Facebook siempre devuelve un campo de nombre de usuario en json, que falta en la respuesta de fb. No estoy muy seguro de por qué no está allí.

El código en el método de extensión owin de identidad no tiene una verificación nula para el reclamo de nombre de identidad que es igual que el campo de nombre de usuario. Hemos presentado una falla internamente.

Para solucionar este problema, podría intentar reemplazar su método ExternalLoginCallback con el siguiente código:

  [AllowAnonymous] public async Task ExternalLoginCallback(string returnUrl) { var result = await AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie); if (result == null || result.Identity == null) { return RedirectToAction("Login"); } var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier); if (idClaim == null) { return RedirectToAction("Login"); } var login = new UserLoginInfo(idClaim.Issuer, idClaim.Value); var name = result.Identity.Name == null ? "" : result.Identity.Name.Replace(" ", ""); // Sign in the user with this external login provider if the user already has a login var user = await UserManager.FindAsync(login); if (user != null) { await SignInAsync(user, isPersistent: false); return RedirectToLocal(returnUrl); } else { // If the user does not have an account, then prompt the user to create an account ViewBag.ReturnUrl = returnUrl; ViewBag.LoginProvider = login.LoginProvider; return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = name }); } } 

El código configurará el nombre de usuario predeterminado como vacío cuando no haya ningún nombre de usuario de facebook / google.

Hongye Sun hizo todo el trabajo pesado en su respuesta anterior.

Aquí hay un código que puede agregarse a su clase de controlador y ser llamado en lugar del problemático AuthenticationManager.GetExternalLoginInfoAsync ().

 private async Task AuthenticationManager_GetExternalLoginInfoAsync_Workaround() { ExternalLoginInfo loginInfo = null; var result = await AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie); if (result != null && result.Identity != null) { var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier); if (idClaim != null) { loginInfo = new ExternalLoginInfo() { DefaultUserName = result.Identity.Name == null ? "" : result.Identity.Name.Replace(" ", ""), Login = new UserLoginInfo(idClaim.Issuer, idClaim.Value) }; } } return loginInfo; } 

Yo tuve el mismo problema. app.CreatePerOwinContext(ApplicationSignInManager.Create); mi problema acaba de agregar la app.CreatePerOwinContext(ApplicationSignInManager.Create); a la Startup.Auth.cs. No tenía eso en mi Startup.Auth.cs tan

var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);

siempre me arrojó una referencia de objeto no configurada a una instancia de un error de objeto. Lo averiguo analizando la plantilla predeterminada VS 2013 para MVC 5. Por lo tanto, si necesita más información sobre la estructura del código o un ejemplo, eche un vistazo a la plantilla MVC5 de VS 2013.

Si el seguimiento de su stack contiene DotNetOpenAuth.AspNet, entonces es el mismo error que aparentemente existió durante dos años en DotNetOpenAuth / DotNetOpenId.

NullReferenceException en DotNetOpenAuth

https://github.com/DotNetOpenAuth/DotNetOpenAuth/issues/317#issuecomment-29580565

El propietario de esas bibliotecas indica que MS las ha abandonado, aunque se ve desde su defecto, ya que probablemente se hayan transferido al código MS.

Si es así, ¿significa eso que OSS quedó enterrado en un código cerrado?

Me encantaría ver tu rastro de stack.

Me enfrenté al mismo problema, cuando revisé las bibliotecas, estaba usando Microsoft ASP.NET Identity Owin 1.0.0 Lo actualicé a Microsoft ASP.NET Identity Owin 2.0.1 usando el comando PM> Install-Package Microsoft.AspNet.Identity.Owin -Version 2.0.1 Esto solucionó el problema.

Me encontré con esta publicación hace unos días, pero lamentablemente ninguna de las soluciones anteriores funcionó para mí. así que aquí es cómo logré solucionarlo y recibir el correo electrónico de Facebook.

  • Actualización siguiente NuGet Pacakges
    • Microsoft.Owin a la versión 3.1.0-rc1
    • Microsoft.Owin.Security a la versión 3.1.0-rc1
    • Microsoft.Owin.Security.Cookies a la versión 3.1.0-rc1
    • Microsoft.Owin.Security.OAuth a la versión 3.1.0-rc1
    • Microsoft.Owin.Security.Facebook a la versión 3.1.0-rc1

A continuación, agregue el siguiente código a la clase de 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); 

Esta es la clase de definición para FacebookBackChannelHandler() :

 using System; using System.Net.Http; public class FacebookBackChannelHandler : HttpClientHandler { protected override async System.Threading.Tasks.Task 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); } } 

Comencé a obtener esto en la plantilla más reciente de VS 2013.3 y me di cuenta de que la autenticación no funcionaba bien con FormsAuthentication que transferí innecesariamente desde uno de mis otros proyectos. Esto es lo que hice para solucionarlo:

añadido ...

añadido ...

Tuve exactamente el mismo problema al seguir el mismo tutorial. Lo resolví haciendo los dos pasos siguientes: 1> Menú de Visual Studio-> Herramientas-> Administrador de paquetes de biblioteca-> Administrar paquetes de NuGet para la solución …, luego instalar el paquete: Microsoft.Owin.Host.SystemWeb 2> En el mismo ventana, haga clic en Actualizar (barra izquierda) y luego actualice todos los paquetes.

Espero que esta respuesta ayude a otras personas que tienen el mismo problema.

Estaba obteniendo lo mismo.

Noté que mis proveedores se configuraron antes de que se llamara a UseExternalSignInCookie , así que simplemente me aseguré de UseExternalSignInCookie antes de que mis proveedores estén configurados y todo funcionó:

 // This has to go first app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); // This must come later app.UseGoogleAuthentication( "[ClientId]", "[ClientSecret]"); 

Pensé en incluir algunas notas para las plantillas de Visual Studio 2015 / el último código de placa de caldera para WebAPI 2. Estaba obteniendo este problema con la autenticación de Google pero me parece que es similar a Facebook y a los otros inicios de sesión sociales. Tenía el último Owin y mis otros paquetes nuget estaban actualizados. Resulta que con las últimas plantillas listas para usar de api 2, solo necesitaba solicitar específicamente que el “correo electrónico” se incluyera en google. Sin esta línea, la llamada api / Cuenta / Registrar sería un error.

Y, por supuesto, asegúrese de que su aplicación esté registrada en google y que su sitio pueda llamarla. (Muchos buenos ejemplos que muestran esos pasos.) https://console.developers.google.com/apis

Aquí está mi ajuste en el archivo App_Start \ Startup.Auth.cs:

 var googleOptions = new GoogleOAuth2AuthenticationOptions() { ClientId = "xxx", ClientSecret = "xxx" }; googleOptions.Scope.Add("email"); //!! Add this !! app.UseGoogleAuthentication(googleOptions); 

Hasta que agregue la línea .Add (“correo electrónico”), la llamada api / Account / RegisterExternal WebAPI 2 (AccountController.cs) devolverá nulo desde esta sección de RegisterExternal:

 var info = await Authentication.GetExternalLoginInfoAsync(); if (info == null) //This would be true, and it would error. { return InternalServerError(); } 

Como este es uno de los pocos artículos que aparecen para este error, pensé en etiquetar mis notas en mi solución para la posteridad. (¡especialmente el proceso de prueba del cartero!)

Para que todo funcione en las pruebas: 1) Llame a la URL api / Account / ExternalLogins de la siguiente manera:

 http://localhost:59137/api/Account/ExternalLogins?returnUrl=%2F&generateState=true 

Deberías obtener una respuesta como esta:

   Google 1phegLF241xeSfd8gZAsCXiBAp3l5bMygg2VSeRXAHk1  /api/Account/ExternalLogin?provider=Google&response_type=token&client_id=self&redirect_uri=http%3A%2F%2Flocalhost%3A59137%2F&state=1phegLF241xeSfd8gZAsCXiBAp3l5bMygg2VSeRXAHk1    

2) Luego obtenga la Url de la respuesta y llámela. Debería obtener el indicador / página de inicio de sesión de google. (O supongo que el de Facebook o Twitter, si eso es lo que configuraste).

3) Inicia sesión, y serás redireccionado a tu página de redirección. Tendrá una URL como algo como esto:

http: // localhost: 59137 / # = señal_acceso d5asC1arCUXaLEMgBS8PT_uwZcTJqC1UZbXblNZ3hMOh3TSKtEXYeKtyKBTv3WmLcaLGGomSvpRSFMfXPxpPvNRgjUVWAiqxtKfv3qWHNqfIMeu5j0eZrJDRAMTrYFgflSbEopAe909a31I4mQnJuvaiITHYPrLmqkm6J88HAVx8F981_q_tflu4A72k3KaB-m2wd0-p1jdQnNMlixM2Wfloh_niUTBIOYUPc1SkKWcZxuI6dzN2Z0PmWHDwzJI8nM8vOuzybJIsxLOyTY1VfzSQ5Qzcll3HhifLPkyZxvXDQ5LHqW1v0_AztsUWkEhW_AJzmw2IaOcTtHCmkmWm1K444okNtOsYfs6HFui0NeY y token_type = portador y expires_in = 1.209.600 Y = estado 3FSOd3_n_sEL4QtiELWPG5B2_H3wRjVb75uDjQS16gk1

toma el token (en negrita arriba) y úsalo como el token del portador.

Ejemplo de cartero de la API GET / Account / UserInfo

4) Ahora que no está registrado (pero tiene un token de portador), puede llamar a la apéndice POST / Cuenta / Registro externo

enter image description here

5) La respuesta será correcta, y si busca en sus tablas AspnetUser, verá que tiene un nuevo registro AspnetUsers y un nuevo registro AspNetUserLogins para google como proveedor.

¡Espero que esto ayude a cualquiera que intente hacer que esto funcione!

No había activado la API de Google+ y regresé con access_denied cuando miré el violín. Al habilitar la API de Google+, se solucionó el problema.