I'm having a problem with users that I create in code. They work for the first few login attempts but then after a while stop logging in and return null from the findasync method. if I do a findbyname it returns the user however this doesn't check the password so I can't use it. these users also don't have a password hash but the users that I create using the register methods do.
if (!db.Users.Any())
{
var userStore = new UserStore<ApplicationUser>(db);
var userManager = new ApplicationUserManager(userStore);
var user = new ApplicationUser
{
UserName = "username",
FirstName = "first",
LastName = "last",
EmailAddress = "example@example.com",
DateCreated = DateTime.Now,
DateModified = DateTime.Now,
ContactNumber = "0208555555",
LastActivityDate = DateTime.Now,
LastPasswordChangedDate = DateTime.Now
};
user.LockoutEnabled = false;
userManager.Create(user, "abc123");
userManager.AddToRole(user.Id, "Admin");
}
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
var user2 = await UserManager.FindByNameAsync(model.UserName);
PasswordVerificationResult result = PasswordVerificationResult.Failed;
result = UserManager.PasswordHasher.VerifyHashedPassword(user2.PasswordHash, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
AuditLog.LogUserAction(UserManager.FindByName(model.UserName).Id, "Login", "User successfully logged in.");
user.LastActivityDate = DateTime.Now;
await db.SaveChangesAsync();
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
public class ApplicationUser : IdentityUser
{
[Required]
[Display(Name = "First name")]
[MaxLength(20)]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last name")]
[MaxLength(50)]
public string LastName { get; set; }
[Required]
[Display(Name = "Email")]
[EmailAddress(ErrorMessage = "Invalid email address")]
public string EmailAddress { get; set; }
[Required]
[Display(Name = "Contact number")]
public string ContactNumber { get; set; }
[Required]
[Display(Name = "Service Provider")]
public int SK_ServiceProviderID { get; set; }
public virtual ServiceProvider ServiceProvider { get; set; }
[Required]
[DisplayName("Date Created")]
public DateTime DateCreated { get; set; }
[Required]
[DisplayName("Date Modified")]
public DateTime DateModified { get; set; }
[Required]
public DateTime LastPasswordChangedDate { get; set; }
[Required]
public DateTime LastActivityDate { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
turns out that it was failing because I was not setting a security stamp field when creating the users by code and this can not be null when using the following:
var resetToken = await UserManager.GeneratePasswordResetTokenAsync(model.UserId);
IdentityResult passwordChangeResult = await UserManager.ResetPasswordAsync(model.UserId, resetToken, model.Password);
This answer to another question helped me figure it out.