简体   繁体   中英

ASP.NET Zero and external authentication

We migrate an old web application written in Node.js to ASP.NET Zero. We have to keep all the users and their passwords so they are still able to login. Passwords are hashed using bcrypt.

The plan is following: when user logs in for the first time after the migration we authorize him/her against brypt password and if the password is valid, we hash it using _userManager.PasswordHasher.HashPassword(user, plainPassword) and save it as his/her password. Next time this user wants to login, the standard ASP.NET Zero functions is called to achieve this.

The first part - bcrypt works quite fine but I cannot figure out how to use the standard mechanism to authenticate the user. This is what I have so far:

private readonly IRepository<User, long> _userRepository;
private readonly SignInManager<User> _signInManager;
private readonly UserManager _userManager;

public AltAuthSource(IRepository<User, long> userRepository, UserManager userManager, SignInManager<User> signInManager)
{
    _userRepository = userRepository;
    _userManager = userManager;
    _signInManager = signInManager;
}

public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
{
    var user = _userRepository.GetAll().FirstOrDefault(x => x.UserName.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase) || x.EmailAddress.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase));

    if (user == null)
    {
        return Task.FromResult(false);
    }
    else
    {
        if (string.IsNullOrWhiteSpace(user.Password))
        {
            var passwordOk = BCrypt.Net.BCrypt.Verify(plainPassword, user.PasswordOrig);

            if (passwordOk)
            {
                _userManager.ResetAccessFailedCountAsync(user);

                var newHash = _userManager.PasswordHasher.HashPassword(user, plainPassword);
                user.Password = newHash;

                return Task.FromResult(true);
            }
            else
            {
                _userManager.AccessFailedAsync(user);
                return Task.FromResult(false);
            }
        }
        else
        {
            var passwordOk = _signInManager.PasswordSignInAsync(user, plainPassword, false, false);

            if (passwordOk.Result.Succeeded)
            {
                _userManager.ResetAccessFailedCountAsync(user);
                return Task.FromResult(true);
            }
            else
            {
                _userManager.AccessFailedAsync(user);
                return Task.FromResult(false);
            }
        }
    }
}

If anyone has already solved this, can you point me to the right direction, please?

After some more digging into the Abp source I found out that if the user is not athenticated by external source, Abp still tries to authenticate against its database. So this most likely solves my problem:

public class AltAuthSource: DefaultExternalAuthenticationSource<Tenant, User>, ITransientDependency
{
    private readonly IRepository<User, long> _userRepository;
    private readonly UserManager _userManager;

    public override string Name => "AltSource";

    public AltAuthSource(IRepository<User, long> userRepository, UserManager userManager)
    {
        _userRepository = userRepository;
        _userManager = userManager;
    }

    public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
    {
        var user = _userRepository.GetAll().FirstOrDefault(x => x.UserName.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase) || x.EmailAddress.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase));

        if (user == null || !string.IsNullOrWhiteSpace(user.Password))
        {
            return Task.FromResult(false);
        }
        else
        {
            var passwordOk = BCrypt.Net.BCrypt.Verify(plainPassword, user.PasswordOrig);

            if (passwordOk)
            {
                _userManager.ResetAccessFailedCountAsync(user);

                var newHash = _userManager.PasswordHasher.HashPassword(user, plainPassword);
                user.Password = newHash;

                return Task.FromResult(true);
            }
            else
            {
                _userManager.AccessFailedAsync(user);
                return Task.FromResult(false);
            }
        }
    }
}

Or am I overlooking something?

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