Reputation: 175
I implemented the authentication with ASP.NET Core Identity 2.0 in an existing App. As I use my own database schema and classes, I use my own User class and I had to create a custom UserStore. The problem is when I created the users, I hashed their password not with the same method which is use in Identity and the login failed when this function is called :
var result = await _signInManager.PasswordSignInAsync(model.Login, model.Password, model.RememberMe, lockoutOnFailure: false);
I have seen on different post that you need to override the CheckPasswordAsync() function to add your own way to check if the passwords are similar. However, I tried to implement it but it is no a success...
CustomUserManager:
public class CustomUserManager<TUser> : UserManager<TUser> where TUser : class
{
public CustomUserManager(IUserStore<TUser> store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TUser> passwordHasher, IEnumerable<IUserValidator<TUser>> userValidators,
IEnumerable<IPasswordValidator<TUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<TUser>> logger) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
}
public override Task<bool> CheckPasswordAsync(TUser user, string password)
{
return base.CheckPasswordAsync(user, password);
}
}
AccountController constructor :
public AccountController(
CustomUserManager<User> userManager,
SignInManager<User> signInManager,
ILogger<AccountController> logger)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
}
I even tried to Add the scope in the services configuration:
services.AddIdentity<User, ProfileUser>().AddDefaultTokenProviders();
services.AddTransient<IUserStore<User>, UserIdentity>();
services.AddTransient<IRoleStore<ProfileUser>, ProfileIdentity>();
services.AddScoped< UserManager<User>, CustomUserManager>();
But it doesn't work. When I launch the App and try to access to the login page, I get an error:
InvalidOperationException: Unable to resolve service for type 'CustomUserManager`1[Maquetteur.Entities.User]' while attempting to activate 'Maquetteur.Web.AccountController'.
With the default UserManager I can access to the login Page but the login function fails. With the custom UserManager I cannot access to the login page.
Do you have an idea what I'm doing wrong ? Or maybe there is an other way to implement our own way to check if passwords are similar when the user logs in ?
Upvotes: 2
Views: 1855
Reputation: 93063
You were heading in the right direction when you added this line:
services.AddScoped<UserManager<User>, CustomUserManager>();
This line essentially says: If I ask for a UserManager<User>
, please give me a CustomUserManager
instead. However, that's not exactly what you intended here. Instead, you wanted to say: If I ask for a CustomUserManager
, please just give me a CustomUserManager
.
It's actually quite easy to fix - You can just register it when you add the Identity services. e.g.:
services
.AddIdentity<User, ProfileUser>()
.AddUserManager<CustomUserManager<User>>()
.AddDefaultTokenProviders();
Note: There are also additional extensions for registering your custom IUserStore
and IRoleStore
implementations.
Upvotes: 4