Search code examples
identityserver4asp.net-core-3.1asp.net-core-identity

Claim change in Identity Server's ProfileService is not reflected in Authentication Cookie


Using ASP.NET Core 3.1 and Identity Server 4 I am starting the login process from a SPA.

After I login I have the following claims on IS4 app authentication cookie:

sub                              1
AspNet.Identity.SecurityStamp    RRHNY65RQMUHTXXSIZKT2YORA3QQ2WAC
role                             Admin
preferred_username               [email protected]
name                             [email protected]
email                            [email protected]
email_verified                   true
amr                              pwd
idp                              local
auth_time                        1598736198

Why does the name claim gets the email as its value?

I then implemented the ProfileService to replace the name claim by the actual user name.

When I check the claims on the spa the replacement was done ...

But on IS4 application the Authentication Cookie still gets the email as name claim.

Why?


Solution

  • It seems the problem was how ASP.NET Core 3.1 defines the Claims.

    I then implemented UserClaimsPrincipalFactory to update the name claim:

    public class UserClaimsPrincipalFactory : UserClaimsPrincipalFactory<User> {
    
      public UserClaimsPrincipalFactory(UserManager<User> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor) { } 
    
      public async override Task<ClaimsPrincipal> CreateAsync(User user) {
    
        ClaimsPrincipal principal = await base.CreateAsync(user);
        ClaimsIdentity identity = (ClaimsIdentity)principal.Identity;
    
        Claim claim = identity.FindFirst("name");
      
        if (claim != null)
          identity.RemoveClaim(claim);
    
        identity.AddClaim(new Claim("name", user.Name));
    
        return principal;
    
      }
    
    }
    

    And now the Authentication Cookie and the Token have the same claims.

    Using IdentityServer4's ProfileService only changes the claims on the token:

      public class ProfileService : IProfileService {
        
        private readonly IUserClaimsPrincipalFactory<User> _claimsFactory;
        private readonly UserManager<User> _userManager;
    
        public ProfileService(UserManager<User> userManager, IUserClaimsPrincipalFactory<User> claimsFactory) {
          _userManager = userManager;
          _claimsFactory = claimsFactory;
        }
    
        public async Task GetProfileDataAsync(ProfileDataRequestContext context) {
          // Not doing any change here
          User user = await _userManager.GetUserAsync(context.Subject);
          ClaimsPrincipal principal = await _claimsFactory.CreateAsync(user); 
          context.IssuedClaims = principal.Claims.ToList();
        }
    
        public async Task IsActiveAsync(IsActiveContext context) {
          User user = await _userManager.GetUserAsync(context.Subject);
          context.IsActive = (user != null) && user.Enabled;
        }
        
      }
    

    I suppose ProfileService is more useful when not using Asp.Net Core Identity?