I am experimenting with Aspnet Core 2.2 and have replaced the standard IdentityUser
with my MyIdentityUser
. When I try to log on I get "Invalid login attempt."
What is it I have missed to implement to allow me to log in?
The ConfigureServices
method sets up Identity with my MyIdentiyUser
and MyIUserStore
like so:
services.AddDefaultIdentity<MyIdentityUser>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddUserStore<MyUserStore>();
By implementing all IUserStore
and IUserPasswordStore
methods as sparingly as possbile (I started with every method throwing NotImplementedException
and then implementing the ones that were called) I got to this:
public class MyUserStore : IUserStore<MyIdentityUser>, IUserPasswordStore<MyIdentityUser>
{
public void Dispose() { }
public Task<MyIdentityUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
var ret = new MyIdentityUser
{
Id = "1",
UserName = normalizedUserName
};
return Task.FromResult(ret);
}
public Task<string> GetUserIdAsync(MyIdentityUser user, CancellationToken cancellationToken)
{
return Task.FromResult(user.UserName);
}
public Task<string> GetPasswordHashAsync(MyIdentityUser user, CancellationToken cancellationToken)
{
return Task.FromResult("asdf");
}
... the rest of the methods throws exception.
}
For the sake of being complete here is my MyIdentityUser
public class MyIdentityUser
{
public string Id {get;set;}
public string UserName {get;set}
}
and start of _LoginPartial.cshtml
@using Microsoft.AspNetCore.Identity
@inject SignInManager<MyIdentityUser> SignInManager
@inject UserManager<MyIdentityUser> UserManager
You were returning an empty string as hash
public Task<string> GetPasswordHashAsync(MyIdentityUser user, CancellationToken cancellationToken)
{
return Task.FromResult(string.Empty);
}
But even an empty password, do not results in an empty hash string. On top of that, there are different algorithms used (which can be configured in Startup.cs, when adding Identity).
You will have to return a real, calculated hash from a specific password if you want it succeed, otherwise it will recognized the entered password returns a different hash then the "stored" one and will cause a failure in login.
Just because you are faking/implementing the user store do not mean the hash validations won't be performed.
public Task<string> GetPasswordHashAsync(MyIdentityUser user, CancellationToken cancellationToken)
{
var hash = new PasswordHasher<MyIdentityUser>().HashPassword(user, "asdf");
return Task.FromResult(hash)
}
Will do, though beware that if you change the password hash algorithm it may fail, since you are new
ing it, which means it uses the default options for password hashing.