¿Cómo uso ASP.NET Identity 2.0 para permitir que un usuario se haga pasar por otro usuario?

Estoy migrando una aplicación ASP.NET MVC 5.1 de MembershipProvider a ASP.NET Identity v2.0. Una de las características que tengo en la aplicación es la suplantación del usuario: los administradores pueden iniciar sesión como cualquier otro usuario registrado en el sitio sin conocer las contraseñas.

Usé este código para implementar la suplantación del usuario para MembershipProvider y esto no funciona con la biblioteca de Identity.

¿Cómo implemento la suplantación de usuario (no la suplantación de IIS) en ASP.NET Identity?

Encontré una solución a este problema.

Básicamente, agrego un reclamo con el nombre de usuario del administrador, si este reclamo existe, sé que está ocurriendo la suplantación. Cuando el administrador desea detener la suplantación, el sistema recupera el nombre de usuario original de las reclamaciones, elimina las antiguas suplantaciones de identidad y crea una nueva cookie para el administrador:

[AuthenticateAdmin] // <- make sure this endpoint is only available to admins public async Task ImpersonateUserAsync(string userName) { var context = HttpContext.Current; var originalUsername = context.User.Identity.Name; var impersonatedUser = await userManager.FindByNameAsync(userName); var impersonatedIdentity = await userManager.CreateIdentityAsync(impersonatedUser, DefaultAuthenticationTypes.ApplicationCookie); impersonatedIdentity.AddClaim(new Claim("UserImpersonation", "true")); impersonatedIdentity.AddClaim(new Claim("OriginalUsername", originalUsername)); var authenticationManager = context.GetOwinContext().Authentication; authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, impersonatedIdentity); } 

Más información está en mi blog: la suplantación del usuario con ASP.Net Identity 2 .

Suplantación de usuario en Asp.Net Core

Hasta julio de 2017: este tema es bastante popular, por lo que he investigado la suplantación de usuarios en Core y los principios son muy similares con API actualizada. Aquí es cómo suplantar:

  [Authorize(Roles = "Admin"] // <-- Make sure only admins can access this public async Task ImpersonateUser(String userId) { var currentUserId = User.GetUserId(); var impersonatedUser = await _userManager.FindByIdAsync(userId); var userPrincipal = await _signInManager.CreateUserPrincipalAsync(impersonatedUser); userPrincipal.Identities.First().AddClaim(new Claim("OriginalUserId", currentUserId)); userPrincipal.Identities.First().AddClaim(new Claim("IsImpersonating", "true")); // sign out the current user await _signInManager.SignOutAsync(); // If you use asp.net core 1.0 await HttpContext.Authentication.SignInAsync(cookieOptions.ApplicationCookieAuthenticationScheme, userPrincipal); // If you use asp.net core 2.0 (the line above is deprecated) await HttpContext.SignInAsync(cookieOptions.ApplicationCookieAuthenticationScheme, userPrincipal); return RedirectToAction("Index", "Home"); } 

Esta es la forma de detener la suplantación:

  [Authorize(Roles = "Admin"] // <-- Make sure only admins can access this public async Task StopImpersonation() { if (!User.IsImpersonating()) { throw new Exception("You are not impersonating now. Can't stop impersonation"); } var originalUserId = User.FindFirst("OriginalUserId").Value; var originalUser = await _userManager.FindByIdAsync(originalUserId); await _signInManager.SignOutAsync(); await _signInManager.SignInAsync(originalUser, isPersistent: true); return RedirectToAction("Index", "Home"); } 

Explicación completa en mi blog: http://tech.trailmax.info/2017/07/user-impersonation-in-asp-net-core/ Ejemplo de código completo en GitHub: https://github.com/trailmax/AspNetCoreImpersonation

Solo para quién está usando Asp Net Core Identity, este es el código para resolver el problema inicial (Un administrador que desea ingresar como usuario, sin saber la contraseña). La siguiente solución no es una “suplantación” real con token como en la respuesta elegida:

  [Authorize("Administrator")] public async Task ImpersonateUserAsync(string email) { var impersonatedUser = await _userManager.FindByNameAsync(email); //Usually username is the email await _signInManager.SignOutAsync(); //signout admin await _signInManager.SignInAsync(impersonatedUser,false); //Impersonate User return RedirectToAction("Index","Home"); }