Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Password History for ASP.net Core 2.0

One of my requirements is to check the last 5 password history entries over the past year to make sure clients are not reusing passwords.

I've already created a Password entity and Passwords collection on my User entity.

I need to create a custom user manager that inherits from UserManager<TUser> and overrides methods that add/update the password to populate the history. I will also have to create a custom password validator that inherits PasswordValidator<TUser> and override the ValidateAsync method.

How does one go about registering these custom implementations in .Net Core 2.0? Do you have to replace the services.AddIdentity helper with all of the individual dependency injection calls? Or is there a way to override only the UserManager and PasswordValidator pieces?

like image 770
Sam Avatar asked Sep 14 '25 23:09

Sam


2 Answers

You can just replace the services that get registered by default with the AddIdentity() call by simply registering your services on top of them. The dependency injection container will keep all registrations around, but when services request an instance, it will only use the latest registration for a type. So you just need to make sure that you register your services in exactly the same way, the original services were registered. So in doubt, check the implementation to see what services get registered how.

In your case, you probably want to do something like this:

services.AddIdentity<MyUser, MyRole>();
services.AddScoped<UserManager<MyUser>, CustomUserManager>();
services.AddScoped<IPasswordValidator<MyUser>, CustomPasswordValidator>();
like image 115
poke Avatar answered Sep 17 '25 15:09

poke


Another idea that works in your case and can work in multiple other cases is to search for a method that will let you add different functionalities along with identity.

For example:

  services.AddIdentity<User, IdentityRole>()
                .AddUserManager<UserManager>()
                .AddDefaultTokenProviders();

for specifying a different UserManager implementation.

In your case you can use AddPasswordValidator method:

services.AddIdentity<User, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonLetterOrDigit = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
})
.AddDefaultTokenProviders()
.AddPasswordValidator<SameCharacterPasswordValidator<User>>();

and Identity framework will do all the DI work for you:

 public virtual IdentityBuilder AddPasswordValidator<TUser>() where TUser : class
 {
    return this.AddScoped(typeof (IPasswordValidator<>).MakeGenericType(this.UserType), typeof (TUser));
 }
like image 39
Razvan Dumitru Avatar answered Sep 17 '25 14:09

Razvan Dumitru