Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.Net Core 3 Identity - Custom Claims not present in JWT from browser

Asp.Net Core 3.0
I am using the ASP.NET Core web application with Angular and Authentication (Individual User Accounts) template (from Visual Studio 2019).
My intention is to add some Custom Claims in the generated JWT and use them in browser.
In order to do that, I have extended the UserClaimsPrincipalFactory

public class MyCustomClaimsInjector : UserClaimsPrincipalFactory<ApplicationUser>
{
    public MyCustomClaimsFactory(UserManager<ApplicationUser> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor)
    {
    }

    protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
    {
        var id = await base.GenerateClaimsAsync(user);
        id.AddClaim(new Claim("my_claim1", "AdditionalClaim1"));
        id.AddClaim(new Claim("my_claim2", "AdditionalClaim2"));
        return id;
    }
}

As well, I have registered the extension in the Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddDefaultIdentity<ApplicationUser>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddClaimsPrincipalFactory<MyCustomClaimsFactory>();


        services.AddIdentityServer()
            .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

        services.AddAuthentication()
            .AddIdentityServerJwt();
        services.AddControllersWithViews();
        services.AddRazorPages();
        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });
    }

During Sign In phase, started from the SPA client, the debugger passes through MyCustomClaimsFactory and adds the claims to the ClaimsIdentity in the GenerateClaimsAsync method.

But, I find strange why the JWT received in browser does not contain the Claims added by the MyCustomClaimsFactory.

Is my expectation to see the Custom Claim in the JWT in browser OK ?

Can anyone suggest the direction to dig in... Why the claims isn't present in the JWT ?

Decoded JWT is: enter image description here

The SPA app: enter image description here

like image 316
mihai Avatar asked Jan 01 '23 14:01

mihai


1 Answers

Will share my results. Hope that will help anyone else.

I have implemented IProfileService and piped the .AddProfileService<ProfileService>()implementation in ConfigureServices.

public class ProfileService : IProfileService
{
    protected UserManager<ApplicationUser> _userManager;

    public ProfileService(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {         
        var user = await _userManager.GetUserAsync(context.Subject);

        var claims = new List<Claim>
        {
            new Claim("my_FirstName", "user_FirstName"),
            new Claim("my_LastName", "user_LastName")
        };

        context.IssuedClaims.AddRange(claims);
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {            
        var user = await _userManager.GetUserAsync(context.Subject);

        context.IsActive = (user != null);
    }
}

the Startup.cs file

services.AddIdentityServer()
        .AddApiAuthorization<ApplicationUser, ApplicationDbContext>()
        .AddProfileService<ProfileService>();

With that, now the JWT contains my custom claims.
I am not sure why the override for UserClaimsPrincipalFactory was not able to solve that.
Will try to study deeper those areas.

like image 188
mihai Avatar answered Jan 05 '23 05:01

mihai