Like many people, when running my .net Core 3.1 Applciation, I need to keep track of some custom properties when a user is logged in. Previously, I may have put this into a custom Session Object, but moving to Azure and .net Core, wanting to utilise the scaling up ability, whilst penny pinching (not running a Redis Server etc), this wasn't an option.
Turns out, this is simplier than it seems.
To achieve this, we need:
A custom ApplicationDBContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
Which has a custom Application User:
public class ApplicationUser : IdentityUser<int>
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
A custom Application Role:
public class ApplicationRole : IdentityRole<int>
{
}
A factory to specify the claims:
public class MyUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, ApplicationRole>
{
public MyUserClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager, IOptions<IdentityOptions> optionsAccessor)
: base(userManager, roleManager, optionsAccessor)
{
}
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
var identity = await base.GenerateClaimsAsync(user);
identity.AddClaim(new Claim("FirstName", user.FirstName ?? ""));
identity.AddClaim(new Claim("LastName", user.LastName ?? ""));
return identity;
}
}
Then in our Startup.cs, we need to use DI to inject the following:
services
.AddIdentity<ApplicationUser, ApplicationRole>()
.AddRoleManager<RoleManager<ApplicationRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddClaimsPrincipalFactory<MyUserClaimsPrincipalFactory>();
Then, anywhere we use User, we are able to:
var FirstName = User.FindFirst("FirstName").Value;