Como criar identidade de usuário com base em declarações prinicpals [duplicado]

Nov 24 2020

Estou usando o asp.net mvc com autenticação de contas de trabalho / escola. Atualmente estou tentando implementar a identidade no processo do usuário.

Aqui está minha ApplicationUseraula:

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

Até agora, a identidade funciona bem, só há um problema. Quando eu entro no aplicativo com minha conta escolar, posso chamar o ClaimsPrincipalsas Usernos Controladores. Para obter a atual, ApplicationUservocê pode usar o UserManager( await _userManager.GetUserAsync(User), Usersendo o ClaimsPrincipals). Mas, como não armazenei minha conta escolar no banco de dados, o resultado será nulo. Se eu criar um novo ApplicationUsercomo o seguinte

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

Isso criará e salvará com êxito o novo usuário no banco de dados com as declarações. Mas então quando tento obter o novo criado ApplicationUsercom await _userManager.GetUserAsync(User)o resultado ainda será nulo. Se eu acessar o meu DbContexte obter todos ApplicationUsers, o recém-criado ApplicationUserestará lá. Então, como posso criar um ApplicationUserbaseado no ClaimsPrincipalsque recebo da minha conta de login da escola?

Respostas

Ogglas Dec 07 2020 at 19:49

Créditos para @poke por isso.

UserManager.GetUserAsyncusa internamente UserManager.GetUserIdpara recuperar o id do usuário do usuário, que é então usado para consultar o objeto do armazenamento de usuários (ou seja, seu banco de dados).

GetUserId basicamente se parece com isto:

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

Portanto, isso retorna o valor de reivindicação de Options.ClaimsIdentity.UserIdClaimType. Optionsé o IdentityOptionsobjeto com o qual você configura a identidade. Por padrão, o valor de UserIdClaimTypeé ClaimTypes.NameIdentifier, ou seja "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier".

Portanto, quando você tenta usar o UserManager.GetUserAsync(HttpContext.User), onde o principal do usuário tem uma UserIDdeclaração, o gerente de usuários está simplesmente procurando uma declaração diferente.

Você pode corrigir isso alternando para ClaimTypes.NameIdentifier:

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

Ou você configura o Identity corretamente para que ele use o seu UserIDtipo de declaração:

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

Fonte:

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

MattE. Dec 04 2020 at 05:55

As reivindicações de um provedor externo serão específicas a esse provedor. Ele não está se conectando ao armazenamento de identidade local em seu aplicativo, está apenas declarando saber quem é o usuário. Portanto, você precisa registrar o usuário em sua loja (SignInManager) antes de usá-lo para autorização. Se você não se preocupa em proteger os recursos e apenas deseja conhecer o usuário, pode mapear diretamente para sua loja interna

As declarações no cabeçalho precisam ser interceptadas pelo 'middleware' ASPNET usando um provedor de autenticação que definirá o objeto Usuário no HttpContext. Assim que tiver o usuário, você precisará mapear sua loja de usuários local para aqueles da conta da escola e, em seguida, obter as declarações como uma chamada separada do resultado. Normalmente, o e-mail é o assunto da declaração e pode ser usado para mapeamento:

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