I have my Initialiser setup and everything seems to run correctly and all the details are saved to the database but when I try to log in it via the webapp it fails everytime. When I run the debugger in the login controller it returns {Failed} after this is hit:
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
Initialiser:
public class DbInitialiser : IDbInitialiser
{
private readonly ApplicationDbContext _db;
private readonly UserManager<IdentityUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public DbInitialiser(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager, ApplicationDbContext db)
{
_db = db;
_userManager = userManager;
_roleManager = roleManager;
}
public void Initialise()
{
try
{
if (_db.Database.GetPendingMigrations().Count() > 0)
{
_db.Database.Migrate();
}
}
catch (Exception ex)
{
}
if (_db.Roles.Any(r => r.Name == "Admin")) return;
_roleManager.CreateAsync(new IdentityRole("Admin")).GetAwaiter().GetResult();//makes sure this executes before proceceding with anything else
_roleManager.CreateAsync(new IdentityRole("Manager")).GetAwaiter().GetResult();
_userManager.CreateAsync(new Employee
{
UserName = "Admin",
Email = "[email protected]",
EmailConfirmed = true,
TwoFactorEnabled = false,
PhoneNumberConfirmed = true
//can set other properties, this is for the initial setup
}, "Abc123!Abc123!").GetAwaiter().GetResult();
IdentityUser user = _db.Users.Where(u => u.Email == "[email protected]").FirstOrDefault();
_userManager.AddToRoleAsync(user, "Admin").GetAwaiter().GetResult();
}
(My Employee class extends IdentityUser)
I have checked all my password requirements as mentioned in other similar posts so I know it isnt to do with that and when I check in SSMS all the data for the user is there in aspnetusers so I am not sure why it wont let me login to the admin user that is seeded
When I run the debugger in the login controller it returns {Failed}
In the source code of SignInManager<TUser>.PasswordSignInAsync
method, we can find it would check the user based on the provided userName
.
public virtual async Task<SignInResult> PasswordSignInAsync(string userName, string password,
bool isPersistent, bool lockoutOnFailure)
{
var user = await UserManager.FindByNameAsync(userName);
if (user == null)
{
return SignInResult.Failed;
}
return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure);
}
In your code, you set UserName
with "Admin
" that is not same as Email
with "[email protected]
". If user login with email account, the code snippet var user = await UserManager.FindByNameAsync(userName);
would return null, which cause the issue.
To fix it, you can try to set UserName
with same value of Email
([email protected]). Or modify the login code logic to find user by the Email, then sign in that user with password, like below.
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var user = await _userManager.FindByEmailAsync(Input.Email);
//var istrue = await _userManager.CheckPasswordAsync(user, Input.Password);
var result = await _signInManager.PasswordSignInAsync(user, Input.Password, Input.RememberMe, lockoutOnFailure: true);
//var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);