I’m using ASP.NET Core Identity in a Blazor project. I’d like to encrypt the user’s personal data, however, I don’t want to encrypt the UserName
. My plan is to use the UserName
as an account id rather than the user’s name. The user’s name will instead be held externally to the IdentityUser
class and encrypted separately using a different encryption mechanism. This account id, which will be held in UserName
, needs to be memorable, but not contain user identifiable data, so won’t need to be encrypted, it will just be like any normal login id. My hope is that, by not encrypting this account id, it will be possible for the user to recover their account under certain scenarios.
I’ve been unable to override the ProtectedPersonalData
attribute on UserName
.
I’ve added a LookupProtector
class that realises ILookupProtector
and LookupProtectorKeyRing
that realises ILookupProtectorKeyRing
.
I’ve added a class called ApplicationUser
that inherits from IdentityUser
and given it a UserName
property without the ProtectedPersonalData
attribute …
public class ApplicationUser : IdentityUser
{
/// <summary>
/// Gets or sets the user name for this user.
/// </summary>
public override string UserName { get; set; } = null!;
}
I’ve modified ApplicationDbContext
to use ApplicationUser
as a generic type …
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
I’ve modified the call to AddDefaultIdentity
to refer to ApplicationUser
instead of IdentityUser
and added a call to AddPersonalDataProtection
with generic types for LookupProtector
and LookupProtectorKeyRing
…
builder.Services.AddDefaultIdentity<ApplicationUser>(options =>
{
options.SignIn.RequireConfirmedAccount = true;
options.User.RequireUniqueEmail = true;
options.Stores.ProtectPersonalData = true;
}).AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddPersonalDataProtection<LookupProtector, LookupProtectorKeyRing>();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<ApplicationUser>>();
I’ve replaced all other references to IdentityUser
in my code to ApplicationUser
, for example, the instances of UserManager
and SignInManager
use ApplicationUser
as their generic type instead of IdentityUser
…
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
I’ve tried scaffolding the User class in case that does something different to what I’ve done manually. I needed to click ‘+’ then type in the name of the ApplicationDbContext
by hand and also check an unwanted file ‘Account/Lockout’ to get it to proceed, but even then it failed with a build error, even though my code builds fine with a normal build. The build error was, “There was an error running the selected code generator: Failed to compile the project in memory”
Scaffold settings
I’ve also dropped the existing database, rolled back all migrations (including the original Identity migration) and then added a single new migration for all models created to-date using these commands …
dotnet ef database drop
dotnet ef migrations remove (multiple calls)
dotnet ef migrations add CreateTables
dotnet ef database update
However, now when I register a user I see that the method LookupProtector.Protect
is called with data that seems to be from the UserName
or NormalizedUserName
.
Am I missing something here? Please, let me know.
I could try to work around this by adding a UserId
property to ApplicationUser
and attempt to leave the UserName
mostly ignored, but I’d like to find a solution that feels more ‘correct’ if I can.
Rick P. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.