2022-09-10 00:33:17 +03:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
2022-09-10 07:12:03 +03:00
|
|
|
using System.Threading;
|
2022-09-10 00:33:17 +03:00
|
|
|
using System.Threading.Tasks;
|
|
|
|
using BlueWest.Cryptography;
|
2022-09-17 22:13:35 +03:00
|
|
|
using BlueWest.Data.Application;
|
2022-09-10 00:33:17 +03:00
|
|
|
using Microsoft.AspNetCore.Identity;
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
|
|
|
namespace BlueWest.WebApi.Context.Users;
|
|
|
|
|
2022-09-11 01:22:04 +03:00
|
|
|
/// <summary>
|
|
|
|
/// User Manager Object
|
|
|
|
/// </summary>
|
|
|
|
internal class ApplicationUserManager : UserManager<ApplicationUser>, IUserManager
|
2022-09-10 00:33:17 +03:00
|
|
|
{
|
|
|
|
private readonly IHasher _hasher;
|
2022-09-10 07:12:03 +03:00
|
|
|
private readonly UserRepository _usersRepo;
|
2022-09-17 22:13:35 +03:00
|
|
|
public ApplicationUserManager(
|
|
|
|
UserRepository store,
|
|
|
|
IOptions<IdentityOptions> optionsAccessor,
|
|
|
|
IHasher passwordHasher,
|
|
|
|
IEnumerable<IUserValidator<ApplicationUser>> userValidators,
|
|
|
|
IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators,
|
|
|
|
ILookupNormalizer keyNormalizer,
|
|
|
|
IdentityErrorDescriber errors,
|
|
|
|
IServiceProvider services,
|
|
|
|
ILogger<UserManager<ApplicationUser>> logger) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
|
2022-09-10 00:33:17 +03:00
|
|
|
{
|
|
|
|
_hasher = passwordHasher;
|
|
|
|
_usersRepo = store;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override async Task<bool> CheckPasswordAsync(ApplicationUser user, string password)
|
|
|
|
{
|
|
|
|
ThrowIfDisposed();
|
|
|
|
var passwordStore = GetPasswordStore();
|
|
|
|
|
|
|
|
var result = await VerifyPasswordAsync(passwordStore, user, password);
|
|
|
|
if (result == PasswordVerificationResult.SuccessRehashNeeded)
|
|
|
|
{
|
|
|
|
//Remove the IPasswordStore parameter so we can call the protected, not private, method
|
|
|
|
await UpdatePasswordHash(user, password, validatePassword: false);
|
|
|
|
await UpdateUserAsync(user);
|
|
|
|
}
|
|
|
|
|
|
|
|
var success = result != PasswordVerificationResult.Failed;
|
|
|
|
if (!success)
|
|
|
|
{
|
|
|
|
var userId = user != null ? GetUserIdAsync(user).Result : "(null)";
|
|
|
|
Logger.LogWarning(0, "Invalid password for user {userId}.", userId);
|
|
|
|
}
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2022-09-17 22:13:35 +03:00
|
|
|
|
2022-09-10 00:33:17 +03:00
|
|
|
protected override async Task<PasswordVerificationResult> VerifyPasswordAsync(IUserPasswordStore<ApplicationUser> store, ApplicationUser user, string password)
|
|
|
|
{
|
|
|
|
string existingHash;
|
|
|
|
|
|
|
|
if (user != null)
|
|
|
|
existingHash = await store.GetPasswordHashAsync(user, CancellationToken);
|
|
|
|
else
|
|
|
|
existingHash = "not a real hash";
|
|
|
|
|
|
|
|
if (existingHash == null)
|
|
|
|
{
|
|
|
|
return PasswordVerificationResult.Failed;
|
|
|
|
}
|
|
|
|
return PasswordHasher.VerifyHashedPassword(user, existingHash, password);
|
|
|
|
}
|
|
|
|
|
2022-09-10 07:12:03 +03:00
|
|
|
|
2022-09-10 00:33:17 +03:00
|
|
|
|
|
|
|
public override async Task<IdentityResult> ChangePasswordAsync(ApplicationUser user, string currentPassword, string newPassword)
|
|
|
|
{
|
|
|
|
ThrowIfDisposed();
|
|
|
|
var passwordStore = GetPasswordStore();
|
|
|
|
if (user == null)
|
|
|
|
{
|
|
|
|
throw new ArgumentNullException(nameof(user));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (await VerifyPasswordAsync(passwordStore, user, currentPassword) != PasswordVerificationResult.Failed)
|
|
|
|
{
|
|
|
|
var result = await UpdatePasswordHash(user, newPassword, validatePassword: false);
|
|
|
|
if (!result.Succeeded)
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return await UpdateUserAsync(user);
|
|
|
|
}
|
|
|
|
Logger.LogWarning(2, "Change password failed for user {userId}.", await GetUserIdAsync(user));
|
|
|
|
return IdentityResult.Failed(ErrorDescriber.PasswordMismatch());
|
|
|
|
}
|
2022-09-17 22:13:35 +03:00
|
|
|
|
|
|
|
public override Task<IdentityResult> SetAuthenticationTokenAsync(ApplicationUser user, string loginProvider, string tokenName, string tokenValue)
|
|
|
|
{
|
|
|
|
return base.SetAuthenticationTokenAsync(user, loginProvider, tokenName, tokenValue);
|
|
|
|
}
|
2022-09-10 00:33:17 +03:00
|
|
|
|
|
|
|
private IUserPasswordStore<ApplicationUser> GetPasswordStore()
|
|
|
|
{
|
|
|
|
if (Store is IUserPasswordStore<ApplicationUser> passwordStore)
|
|
|
|
{
|
|
|
|
return passwordStore;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|