Search code examples
asp.net-coreasp.net-identity

Identity 3 - store claims in database but not cookie


In.net core Identity 3 - is it possible to NOT store user claims or role claims in the Identity cookie by default but have them in the database only?

In other words if you want to access the claims you would have to load them explicitly.

Haven't been able to figure out how to configure this using the built in functionality of Identity and the default schema.


Solution

  • I was able to still use the built in AspNetRoleClaims table but not including these in the cookie by overriding the UserClaimsPrincipalFactory class. Again the reason for this is that I have many role claims and the cookie was becoming too large.

    I created my own class, AppClaimsPrincipalFactory that inherits from UserClaimsPrincipalFactory and overrides the CreateAsync method:

    public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
    {
        public AppClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)
        {
        }
        public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }
            var userId = await UserManager.GetUserIdAsync(user);
            var userName = await UserManager.GetUserNameAsync(user);
            var id = new ClaimsIdentity(Options.Cookies.ApplicationCookieAuthenticationScheme,
                Options.ClaimsIdentity.UserNameClaimType,
                Options.ClaimsIdentity.RoleClaimType);
            id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId));
            id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName));
            if (UserManager.SupportsUserSecurityStamp)
            {
                id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType,
                    await UserManager.GetSecurityStampAsync(user)));
            }
    
            // code removed that adds the role claims 
    
            if (UserManager.SupportsUserClaim)
            {
                id.AddClaims(await UserManager.GetClaimsAsync(user));
            }
            return new ClaimsPrincipal(id);
        }
    }
    

    In Startup.cs ConfigureServices, I then register this with the container like so:

    services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();
    
            // override UserClaimsPrincipalFactory (to remove role claims from cookie )
            services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, AppClaimsPrincipalFactory>();