简体   繁体   中英

Asp.Net Core Identity, updating existing plain text passwords

We have customized Asp.Net Core to use our table of students rather than the AspNetUser table. Everything works fine for new students. But we need to update the existing students' passwords. I would like to do something like this (in AccountController Login method) when a student logins or this could be done on a one-time basis…

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        // Require the user to have a confirmed email before they can log on.
        var user = await _userManager.FindByEmailAsync(model.Email);
        if (user != null)
        {
            if (user.PasswordHash == null)
            {
                user.EmailConfirmed = true;
                user.UserName = model.Email;
                user.NormalizedEmail = model.Email.ToUpper();
                user.NormalizedUserName = user.NormalizedEmail;
                //user.PasswordHash = ?;
                //user.SecurityStamp = ?;
                //update user in database.
            }
            //continue on with login process
        }
    }
}

The below code (from the Register method) creates a new user and adds him to the database. This is not what we want.

var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
    // …

You'll find the UserManager has anything you need to set the password for a user. While you could use the internal password hasher directly, going through the user manager makes sure that the user entity is updated properly in respect to the password. So you can just rely on the user manager to “do the right thing”.

If a user does not have a password, you can use AddPasswordAsync to set it:

var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null && !(await _userManager.HasPasswordAsync(user)))
{
    // retrieve plaintext password
    var originalPassword = GetPlainTextPassword(user);

    var result = await _userManager.AddPasswordAsync(user, originalPassword);

    if (!result.Succeeded)
    {
        // handle error
    }
}

Otherwise, you could also make use of the password reset flow and generate a token you then immediately use to reset the user's password (without actually involving the user). So you would basically chain GeneratePasswordResetTokenAsync and ResetPasswordAsync . Of course, this should only be done for maintenance reasons:

var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)
{
    // retrieve plaintext password
    var originalPassword = GetPlainTextPassword(user);

    // retrieve token
    var resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);

    // reset password
    var result = await _userManager.ResetPasswordAsync(user, resetToken, originalPassword);

    if (!result.Succeeded)
    {
        // handle error
    }
}

Regardless of this, I would still suggest you to actively require users to reset their passwords themselves. Just remove the plain text passwords from the database, and keep the empty password. That way, users will have to reset their password first (you should add a note to explain that they will have to do that before their first login), and nobody will ever be able to see their new password in plain text. – The old passwords are exposed in the database and likely (hopefully?!) a large number of backups, and even if you believe your system is secure, it likely isn't perfect. And there are still people involved that have access to the database and could directly or indirectly expose those passwords to others (with or without good intentions). You shouldn't trust your system enough that nothing will go wrong. And users shouldn't have to trust you with keeping their passwords safe. You should tell them to make a new password and get rid of their old ones—better sooner than later.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM