1
votes

I'm trying to add some basic authentication to my asp.net core website.
I have my users stored in a sqlite database and i'm trying to verify the password the user enters but for some reason it always fails even though the entered password is correct.

Any advise here?

This is my login action:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel ivm)
{
   if (ModelState.IsValid)
   {
      var user = _userRepo.Get(ivm.Email);
      if (user == null)
      {
         ModelState.AddModelError("UserError", "User not found");
         return View("Index", ivm);
      }
      PasswordHasher<User> hasher = new PasswordHasher<User>();
      var result = hasher.VerifyHashedPassword(user, user.Password, ivm.Password);
      if (result != PasswordVerificationResult.Failed)
      {
         string role = "";
         if (user.Role == Models.Enums.Role.Admin)
            role = "Admin";
         else
            role = "User";
         var claims = new[] { new Claim(ClaimTypes.Name, user.Id.ToString()), new Claim(ClaimTypes.Role, role) };
         var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
         await AuthenticationHttpContextExtensions.SignInAsync(HttpContext, CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));
         return RedirectToAction("Index", "Home");
      }
      else
      {
         ModelState.AddModelError("PasswordError", "Wrong password");
         return View("Index", ivm);
      }
   }
   else
   {
      ModelState.AddModelError("ModelError", "ModelError");
      return View("Index", ivm);
   }
}

User:

[Table("Users")]
public class User
{
    public string Email { get; set; }
    public string Password { get; set; }
    public Role Role { get; set; }
    public Guid Id { get; set; }
}

Current init just an admin user:

            var user = new User
            {
                Email = "email.com",
                Role = Models.Enums.Role.Admin,
                Id = Guid.NewGuid()
            };
            PasswordHasher<User> phw = new PasswordHasher<User>();
            string hashed = phw.HashPassword(user, "superpassword");
            user.Password = hashed;
            db.Users.Add(user);
            db.SaveChanges();
1
What does your User class look like, specifically the Password property? Additionally, how is a new User added? What function is performing the hash during registration?mcbowes
@mcbowes see updatePio

1 Answers

1
votes

In my ASP.NET Core project I use UserManager which handles password checking pretty well

bool correctPassword = await _userManager.CheckPasswordAsync(user, password);

UserManager also handles user creation without having to deal with password hasher.

One of the overloads:

public virtual Task<IdentityResult> CreateAsync(TUser user, string password);

Update 1:

based on the code you provided, you assign password hash to Password member of User class

instead, you should use PasswordHash property e.g.

hostAdminUser = new ApplicationUser()
{
    UserName = SetupConsts.Users.Host.UserName,
    Email = SetupConsts.Users.Host.Email,
    EmailConfirmed = true,
    PasswordHash = new PasswordHasher<ApplicationUser>().HashPassword(hostAdminUser, SetupConsts.Users.Passwords.Default)
};

await _userManager.CreateAsync(hostAdminUser);

so, here's the relevant bit: PasswordHash = new PasswordHasher<ApplicationUser>


Update 2:

In order to use UserManager in ASP.NET Core you need to inject it into your controller

public class AuthController : Controller
{
    private UserManager<ApplicationUser> _userManager;

    public AuthController(
        UserManager<ApplicationUser> userManager
        )
    {
        _userManager = userManager;
    }

you are then supposed to use _userManager instance.

In Startup.cs find the method called ConfigureServices, and put the following line required for Dependency Injection

services.AddTransient<UserManager<ApplicationUser>>();