Cómo crear un usuario de identidad basado en principios de reclamaciones [duplicado]

Nov 24 2020

Estoy usando asp.net mvc con autenticación de cuentas de trabajo / escuela. Actualmente estoy tratando de implementar la identidad en el proceso del usuario.

Aquí está mi ApplicationUserclase:

public class ApplicationUser: IdentityUser
{
    public ICollection<Semester> Semesters { get; set; }
}

Hasta ahora, la identidad funciona bien, solo hay un problema. Cuando inicio sesión en la aplicación con mi cuenta de la escuela, puedo llamar al ClaimsPrincipalscomo Useren los controladores. Para obtener la corriente ApplicationUser, puede usar el UserManager( await _userManager.GetUserAsync(User), Usersiendo el ClaimsPrincipals) Pero como no he almacenado mi cuenta de la escuela en la base de datos, el resultado será nulo. Si creo una nueva ApplicationUsercomo la siguiente

var newUser = new ApplicationUser()
{
    UserName = User.Identity.Name,
    Email = User.Identity.Name
};
await _userManager.CreateAsync(newUser);
await _userManager.AddClaimsAsync(newUser, User.Claims);

Esto creará y guardará con éxito el nuevo usuario en la base de datos con las reclamaciones. Pero luego cuando trato de obtener el nuevo creado ApplicationUsercon await _userManager.GetUserAsync(User)el resultado seguirá siendo nula. Si accedo a mi DbContexty obtengo todo ApplicationUsers, el recién creado ApplicationUserestá ahí. Entonces, ¿cómo puedo crear un ApplicationUserbasado en el ClaimsPrincipalsque obtengo del inicio de sesión de mi cuenta escolar?

Respuestas

Ogglas Dec 07 2020 at 19:49

Créditos para @poke por esto.

UserManager.GetUserAsyncutiliza internamente UserManager.GetUserIdpara recuperar la identificación de usuario del usuario que luego se utiliza para consultar el objeto desde la tienda de usuarios (es decir, su base de datos).

GetUserId básicamente se ve así:

public string GetUserId(ClaimsPrincipal principal)
{
    return principal.FindFirstValue(Options.ClaimsIdentity.UserIdClaimType);
}

Entonces esto devuelve el valor de reclamo de Options.ClaimsIdentity.UserIdClaimType. Optionses el IdentityOptionsobjeto con el que configura la identidad. Por defecto, el valor de UserIdClaimTypees ClaimTypes.NameIdentifier, es decir "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier".

Entonces, cuando intenta usar UserManager.GetUserAsync(HttpContext.User), donde el principal de usuario tiene un UserIDreclamo, el administrador de usuarios simplemente está buscando un reclamo diferente.

Puede solucionar esto cambiando a ClaimTypes.NameIdentifier:

new ClaimsIdentity(new[]
{
    new Claim(ClaimTypes.Name, user.UserName),
    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
})

O configura la identidad correctamente para que utilice su UserIDtipo de reclamo:

// in Startup.ConfigureServices
services.AddIdentity(options => {
    options.ClaimIdentity.UserIdClaimType = "UserID";
});

Fuente:

https://stackoverflow.com/a/51122850/3850405

MattE. Dec 04 2020 at 05:55

Las reclamaciones de un proveedor externo serán específicas de ese proveedor. No está iniciando sesión en la tienda de identidad local en su aplicación, solo afirma saber quién es el usuario. Por lo tanto, debe registrar al usuario en su tienda (SignInManager) antes de poder usarlo para la autorización. Si no le importa proteger los recursos y solo desea conocer al usuario, puede mapear directamente a su tienda interna

Las afirmaciones en el encabezado deben ser interceptadas por el 'middleware' de ASPNET utilizando un proveedor de autenticación que luego establecerá el objeto User en HttpContext. Una vez que tenga el usuario, deberá asignar su tienda de usuarios local a los de la cuenta de la escuela y luego obtener los reclamos como una llamada separada del resultado. Por lo general, el correo electrónico es el asunto de la reclamación y se puede utilizar para el mapeo:

    var userName = User.Identity.Name;
    var user = _userManager.FindByNameAsync(userName);
    var claims = _userManager.GetClaimsAsync(user);