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?
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>();
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));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With