how google apis c# asp.net-mvc-5 google-oauth oauth-provider

c# - apis - oauth2 google how to



Problema intermitente de ASP.NET oAuth con Google, AuthenticationManager.GetExternalIdentityAsync regresa nulo (7)

Estoy tratando de solucionar un problema intermitente cuando utilizo Google como un proveedor de inicio de sesión externo.

Al intentar iniciar sesión, el usuario se redirige a la página de inicio de sesión en lugar de autenticarse.

El problema ocurre en esta línea (línea 55 del enlace a continuación), GetExternalIdentityAsync devuelve null.

var externalIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);

El código completo es:

[Authorize] public abstract class GoogleAccountController<TUser> : Controller where TUser : Microsoft.AspNet.Identity.IUser { public IAuthenticationManager AuthenticationManager { get { return HttpContext.GetOwinContext().Authentication; } } public abstract UserManager<TUser> UserManager { get; set; } [AllowAnonymous] [HttpGet] [Route("login")] public ActionResult Login(string returnUrl) { ViewData.Model = new LoginModel() { Message = TempData["message"] as string, Providers = HttpContext.GetOwinContext().Authentication.GetExternalAuthenticationTypes(), ReturnUrl = returnUrl }; return View(); } [AllowAnonymous] [HttpPost] [ValidateAntiForgeryToken] [Route("login")] public ActionResult Login(string provider, string returnUrl) { return new ChallengeResult(provider, Url.Action("Callback", "Account", new { ReturnUrl = returnUrl })); } [AllowAnonymous] [Route("authenticate")] public async Task<ActionResult> Callback(string returnUrl) { var externalIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie); if (externalIdentity == null) { return RedirectToAction("Login", new { ReturnUrl = returnUrl }); } var emailAddress = externalIdentity.FindFirstValue(ClaimTypes.Email); var user = await UserManager.FindByNameAsync(emailAddress); if (user != null) { await SignInAsync(user, false); return RedirectToLocal(returnUrl); } else { TempData.Add("message", string.Format("The account {0} is not approved.", emailAddress)); return RedirectToAction("Login", new { ReturnUrl = returnUrl }); } } [HttpPost] [ValidateAntiForgeryToken] [Route("logout")] public ActionResult Logout(string returnUrl) { AuthenticationManager.SignOut(); return RedirectToLocal(returnUrl); } private async Task SignInAsync(TUser user, bool isPersistent) { AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie); var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); var authenticationProperties = new AuthenticationProperties() { IsPersistent = isPersistent }; AuthenticationManager.SignIn(authenticationProperties, identity); } private ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } protected override void Dispose(bool disposing) { if (disposing && UserManager != null) { UserManager.Dispose(); UserManager = null; } base.Dispose(disposing); } }

Que también está aquí

Este es un problema muy intermitente, y la redistribución de la aplicación a menudo hará que funcione temporalmente.

Al mirar en Fiddler, puedo ver que se realiza una llamada para iniciar sesión en google justo antes del método de autentificación en el que no puede encontrar la cookie.

La aplicación usa el siguiente código para inicializar el inicio de sesión de google

app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/login") }); app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); app.UseGoogleAuthentication();

Establecí el modo de autenticación en non en el archivo web.config y eliminé el módulo de autenticación de formularios.

<system.web> <authentication mode="None" /> </system.web> <system.webServer> <validation validateIntegratedModeConfiguration="false" /> <modules runAllManagedModulesForAllRequests="true"> <remove name="FormsAuthenticationModule" /> </modules> </system.webServer>

Los sitios están alojados en Azure, algunos se ejecutan en 1 instancia, otros 2. Tienen dominios personalizados, aunque aún fallan tanto en el dominio personalizado como en el dominio azurewebsites, y en http / https.

¿Alguien puede ayudar con por qué esto podría estar pasando?

Actualizar

La versión 3.0 de Microsoft.Owin.Security.Google fue lanzada anoche. Voy a cambiar y ver si esto soluciona el problema.

https://www.nuget.org/packages/Microsoft.Owin.Security.Google


¡Tengo este problema ayer y estaba COMPLETAMENTE GOLPEADO! Y, como describes, lo entendí así sin ninguna razón.

Me las arreglé para arreglarlo (después de horas de comparar 2 proyectos, 1 proyecto de prueba que no funcionaba sin problemas cada vez y otro que era un proyecto más serio) y tenían exactamente el mismo código, pero diferentes versiones dll)

El problema estaba en los archivos DLL: los paquetes a los que se hace referencia desde Nuget. Asegúrese de tener los últimos paquetes y también consulte la sección de tiempo de ejecución en su web.config .

Después de actualizar todos los paquetes relacionados con Owin y Microsoft.Owin y agregué:

<assemblyBinding> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> </assemblyBinding>

... funcionó de nuevo! Podrían variar en función de sus paquetes usados, pero así fue como funcionó para mí.


Asegúrese de que las cookies de terceros estén habilitadas. Descubrí que si no inició sesión en Google cuando intenta ''Registrar'' a un usuario con su aplicación, lo redirecciona a la página de inicio de sesión mientras busca esta cookie que no está allí, pero que aún logra hacer qué necesita con el proveedor externo. La próxima vez que intente ''Registrarse'', porque ya se ha convertido en parte del proceso, ya no necesita buscar la cookie externa y, por lo tanto, lo logra por segunda vez.


Creo que no deberías estar usando app.UseGoogleAuthentication(); ya que es una llamada que intentará usar OpenID 2.0, que ha quedado en desuso .
Lo que debería estar usando en su lugar es OAuth 2.0 para iniciar sesión (OpenID Connect) .
Asi que:

  1. registre su aplicación en Google Developers Console
  2. le permite acceder a la API de Google+ (aunque no tiene intención de utilizar Google+ directamente, ahora se usa como medio de autenticación)
  3. habilitar la autenticación de Google de ASP.NET Identity de esta manera

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() { ClientId = "YOUR_CLIENT_ID", ClientSecret = "YOUR_CLIENT_SECRET", });


Hay un error en la implementación de Owin de Microsoft para System.Web. El que se está utilizando al ejecutar aplicaciones Owin en IIS. Que es lo que probablemente el 99% de nosotros hagamos, si estamos usando el nuevo manejo de autenticación basado en Owin con ASP.NET MVC5.

El error hace que las cookies establecidas por Owin desaparezcan misteriosamente en algunas ocasiones.

Pon este nuget antes de https://github.com/KentorIT/owin-cookie-saver antes de app.UseGoogleAuthentication(...)


Olvidé habilitar "Google + API" en la consola del desarrollador de Google. El inicio de sesión de Google parece estar bien, pero GetExternalLoginInfoAsync devuelve null.

Puede seguir este enlace https://.com/a/27631109/657926


Tengo el mismo problema. Estoy usando Visual Studio 2013 y el sitio web está en Azure. El inicio de sesión social que había estado funcionando sin problemas dejó de funcionar y LinkLoginCallback recibía null en loginInfo. Volví a publicar el proyecto sin cambio de código o reconstrucción y luego login. Recibí datos correctos y todo funciona bien. No tiene sentido, pero ahí tienes.


Tom Estoy usando google-oauth en mi aplicación asp.net usando REST API. funciona bien y no tengo problemas de conexión.

Los siguientes pasos estoy realizando:

1.He creado un proyecto en la consola de Google developer en el que he creado la configuración "ID de cliente para la aplicación web" que contendrá los siguientes parámetros.

a) Client ID => Será generado automáticamente por Google b) Dirección de correo electrónico => Google lo generará automáticamente c) Client secret => Se generará automáticamente por google d) Redirigir URIs => Necesita especificar url de página web que se usará para manejar el proceso de autenticación. En esta página podemos autenticar y podemos obtener información básica del usuario.

my url: "http://localhost:1822/WebForm1.aspx/code"

Mi uso:

  1. Creé un proyecto de muestra que contendrá "Página web1.aspx" y "Página web2.aspx".

He configurado la página de inicio "Webpage2.aspx" y estoy formando una URL de autenticación abierta en la "página web2.aspx" y redirigiendo a la página de inicio de sesión de google.

Después de iniciar sesión, se redireccionará a "Página web1.aspx" junto con el código de acceso. Al pasar este código de acceso a la URL " https://accounts.google.com/o/oauth2/token ", obtengo el token de acceso junto con el tipo de token y el tiempo de caducidad del token. Después de pasar este acceso a la URL " https://www.googleapis.com/oauth2/v2/userinfo ", obtengo información básica del usuario como "correo electrónico, nombre, género, foto, etc. ..."

Código de ejemplo

public class GoogleAuthorizationData { public string access_token { get; set; } public int expires_in { get; set; } public string token_type { get; set; } } public class GoogleUserInfo { public string name { get; set; } public string family_name { get; set; } public string gender { get; set; } public string email { get; set; } public string given_name { get; set; } public string picture { get; set; } public string link { get; set; } public string id { get; set; } } Webpage1.aspx ============ protected void Page_Load(object sender, EventArgs e) { string code = Request.QueryString["code"].ToString(); string scope = Request.QueryString["scope"].ToString(); string url = "https://accounts.google.com/o/oauth2/token"; string postString = "code=" + code + "&client_id=" + ConfigurationManager.AppSettings["GoogleClientID"].ToString() + "&client_secret=" + ConfigurationManager.AppSettings["GoogleSecretKey"].ToString() + "&redirect_uri=" + ConfigurationManager.AppSettings["ResponseUrl"].ToString() + "&grant_type=authorization_code"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.ToString()); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; UTF8Encoding utfenc = new UTF8Encoding(); byte[] bytes = utfenc.GetBytes(postString); Stream os = null; try { request.ContentLength = bytes.Length; os = request.GetRequestStream(); os.Write(bytes, 0, bytes.Length); } catch { } try { HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse(); Stream responseStream = webResponse.GetResponseStream(); StreamReader responseStreamReader = new StreamReader(responseStream); var result = responseStreamReader.ReadToEnd();// var json = new JavaScriptSerializer(); GoogleAuthorizationData authData = json.Deserialize<GoogleAuthorizationData>(result); HttpWebRequest request1 = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/oauth2/v2/userinfo"); request1.Method = "GET"; request1.ContentLength = 0; request1.Headers.Add("Authorization", string.Format("{0} {1}", authData.token_type, authData.access_token)); HttpWebResponse webResponse1 = (HttpWebResponse)request1.GetResponse(); Stream responseStream1 = webResponse1.GetResponseStream(); StreamReader responseStreamReader1 = new StreamReader(responseStream1); GoogleUserInfo userinfo = json.Deserialize<GoogleUserInfo>(responseStreamReader1.ReadToEnd()); Response.Write(userinfo.email); } catch (Exception eX) { throw eX; } }