Search code examples
c#asp.net-identityidentityserver4.net-core-3.0

User.Identity.Name is null after local login


I configure IdentityServer4 to use AspNet Identity (.net core 3.0) in order to allow users to authenticate using login/password.

My third application is an WebApi in .net core 3.0.

After logging, authentication and authorization succeeded but I can't retrieve UserId through User.Identity.Name which is null/empty.

However, I can see the claims information which contain a sub claim containing the userId.

Here is the packages I use for my IdentityServer4 web app

<PackageReference Include=&quot;IdentityServer4&quot; Version=&quot;3.0.1&quot; />

Solution

  • I'm facing to the same issue and I found two solutions.

    • [Solution 1] - WebApi - Updating NameClaimType of IdentityServerAuthentication configuration

    In your startup file of your WebApi, update the NameClaimType property

    services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
            .AddIdentityServerAuthentication(options =>
             {
                   options.CacheDuration = xxxxx;
                   options.Authority = xxxxx;
                   options.ApiName = xxxx;
                   options.ApiSecret = xxxxx;
                   options.RequireHttpsMetadata = xxxxxx;
                   options.NameClaimType = JwtClaimTypes.Subject;
             });
    
    • [Solution 2] - IdentityServer4 App - Creating new profil to customize your claims

    Create a new profil for IdentityServer4 server in order to customize claims inside the token.

    public class AspNetIdentityProfileService : IProfileService
    {
        private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
        private readonly UserManager<ApplicationUser> _userManager;
    
        public AspNetIdentityProfileService(UserManager<ApplicationUser> userManager, IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory)
        {
            _userManager = userManager;
            _claimsFactory = claimsFactory;
        }
    
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var sub = context.Subject.GetSubjectId();
            var user = await _userManager.FindByIdAsync(sub);
            var principal = await _claimsFactory.CreateAsync(user);
    
            var claims = principal.Claims.ToList();
    
            claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
    
            claims.Add(new Claim("name", user.UserName));
            context.IssuedClaims = claims;
        }
    
        public async Task IsActiveAsync(IsActiveContext context)
        {
            var sub = context.Subject.GetSubjectId();
            var user = await _userManager.FindByIdAsync(sub);
    
            context.IsActive = user != null;
        }
    }
    

    In your startup file

    services.AddTransient<IProfileService, AspNetIdentityProfileService>();