1

J'ai un scénario avec une application page unique implémentée avec Typescript qui utilise oidc-client pour obtenir id_token et access_token à partir d'une application AspNet Core qui utilise IdentityServer4.Comment AspNet Identity génère des revendications utilisateur

Sur le serveur d'identité Je suis également en utilisant l'identité avec EntityFramework, afin que je puisse récupérer l'utilisateur et leur profil pour générer des réclamations, etc.

Je suis face à une situation étrange où je suis par exemple la mise à jour du FirstName pour un utilisateur, il est mis à jour correctement dans la base de données mais lors de la génération des revendications au niveau utilisateur (given_name, family_name, name et email) le nom donné n'est pas mis à jour avec le nouveau nom, donc le id_token émis ne contient pas les informations mises à jour dans les revendications.

J'ai quelque chose comme ceci:

public class AspNetIdentityProfileService : IProfileService 
{ 
    private readonly UserManager<User> _userManager; 
    private readonly IUserRepository _userRepository; 

    public AspNetIdentityProfileService(UserManager<User> userManager, IUserRepository userRepository) 
    { 
    _userManager = userManager; 
    _userRepository = userRepository; 
    } 

    // some code where I generate a List<Claim> calling below method 

    private async Task<IEnumerable<Claim>> GetUserLevelClaimsAsync(User user) 
    { 
    //user contains the updated info because it comes from DB. 
    List<Claim> userClaims = new List<Claim>(); 
    var standardClaims = await _userManager.GetClaimsAsync(user); //has old values 
    userClaims.AddRange(standardClaims); 
    userClaims.Add(new Claim(JwtClaimTypes.Role, user.Role.ToString().ToLowerInvariant())); 
    return userClaims; 
    } 
} 

Pourquoi le await _userManager.GetClaimsAsync(user); sans tenir compte des informations mises à jour pour l'utilisateur? D'où provient l'ancienne information? J'ai redémarré l'application en supprimant les cookies du navigateur au cas où ils seraient stockés dans le cookie que le serveur d'identité émet à des fins de connexion unique, mais je ne sais toujours pas où les anciennes informations sont mises en cache.

MISE À JOUR 1: Ceci est le modèle utilisateur.

public class User : IdentityUser 
{ 
    //Extend properties 
    public DateTime CreatedOn { get; set; } 
    public DateTime ModifiedOn { get; set; } 
    public Guid? PrimaryBusinessId { get; set; } 
    public Business PrimaryBusiness { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string FullName 
    { 
     get 
     { 
      return string.Join(" ", FirstName, LastName); 
     } 
    } 

    public DateTime? LastLoggedInOn { get; set; } 

    public UserRole Role { get; set; } 

    public List<UserBusiness> UserBusinesses { get; set; } 
} 

MISE À JOUR 2: Il y a une solution évidente, qui est d'ajouter manuellement les demandes des propriétés de l'utilisateur à la place se fondant sur UserManager de l'identité. Mais la question demeure, pourquoi userManager ne récupère pas les valeurs mises à jour dans DB? et où trouve-t-il les anciennes valeurs récupérées?

private IEnumerable<Claim> GetUserLevelClaims(User user) 
    { 
     List<Claim> userClaims = new List<Claim>(); 
     //var standardClaims = await _userManager.GetClaimsAsync(user); //does not retrieve updated fields 
     userClaims.Add(new Claim(JwtClaimTypes.Name, user.FullName)); 
     userClaims.Add(new Claim(JwtClaimTypes.FamilyName, user.LastName)); 
     userClaims.Add(new Claim(JwtClaimTypes.GivenName, user.FirstName)); 
     userClaims.Add(new Claim(JwtClaimTypes.Email, user.Email)); 
     userClaims.Add(new Claim(JwtClaimTypes.Role, user.Role.ToString().ToLowerInvariant())); 
     return userClaims; 
    } 
+0

Pouvez-vous coller votre modèle de données utilisateur de l'application. – Lutando

+0

@Lutando modèle utilisateur collé sur la mise à jour 1 Prénom et nom ne semblent pas faire partie de IdentityUser, j'ai donc ajouté mes propres propriétés. Pensez-vous que l'identité est incapable d'accéder à la valeur de ces propriétés? Les revendications émises pour l'utilisateur ont l'ancien nom et le nom de famille, pas sûr de l'endroit où ces valeurs seraient stockées. – iberodev

+0

Également ajouté Mise à jour 2 avec solution de contournement – iberodev

Répondre

2

Vous devez indiquer à IProfileService d'où les revendications.

Fondamentalement, userManager de AspNetCore.Identity obtiendra seulement les revendications associées pour cet utilisateur. C'est, IdentityUser.Claims. Les "anciennes valeurs" existent toujours dans la table AspNetUserClaims. Si vous mettez à jour l'entité associée pour cet utilisateur pour n'importe quelle revendication dans la table, alors IProfileService émettra ces revendications mises à jour puisque vous comptez sur userManager pour récupérer vos revendications. Fondamentalement, pour savoir quelles revendications appartiennent à un utilisateur, vous pouvez voir qu'il y a la «table racine» appelée AspNetUsers. Cette table a une table des revendications appelée appelée AspNetUserClaims. Cette table ne fait que cartographier les utilisateurs et leurs revendications 1-M.En résumé, l'édition d'une valeur de sinistre dans cette table est ce que vous devez faire.

N'hésitez pas à ajouter plus de revendications à la dans IProfileService dans GetProfileDataAsync. Il est assez fréquent d'ajouter des revendications en fonction de l'entité de la table elle-même. comme vous l'avez démontré dans votre mise à jour # 2

1

@Lutando m'a indiqué dans la bonne direction avec ses commentaires.

Pour répondre à ma propre question, le gestionnaire des utilisateurs saisit les revendications non pas à partir de la table User, mais à partir d'une autre table d'identité appelée UserClaims. Je ne savais pas que cette table était utilisée mais maintenant c'est logique. Comme Lutando suggère également, la solution de contournement est parfaitement valide et je n'ai pas besoin de compter sur le gestionnaire des utilisateurs de l'identité pour générer des revendications. Je n'ai même pas besoin d'utiliser cette table UserClaims parce que j'ai le nom et le nom dans ma table utilisateur comme indiqué dans la mise à jour 1.