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?
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?