Search code examples
sql-serverdatabaseentity-frameworkasp.net-coreasp.net-identity

.Net Core Identity seed data: unable to login using credentials seeded


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


Solution

  • 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);