in src/Unosquare.PassCore.PasswordProvider/PasswordChangeProvider.cs [38:126]
public ApiErrorItem? PerformPasswordChange(string username, string currentPassword, string newPassword)
{
try
{
var fixedUsername = FixUsernameWithDomain(username);
using var principalContext = AcquirePrincipalContext();
var userPrincipal = UserPrincipal.FindByIdentity(principalContext, _idType, fixedUsername);
// Check if the user principal exists
if (userPrincipal == null)
{
_logger.LogWarning($"The User principal ({fixedUsername}) doesn't exist");
return new ApiErrorItem(ApiErrorCode.UserNotFound);
}
var minPwdLength = AcquireDomainPasswordLength();
if (newPassword.Length < minPwdLength)
{
_logger.LogError("Failed due to password complex policies: New password length is shorter than AD minimum password length");
return new ApiErrorItem(ApiErrorCode.ComplexPassword);
}
// Check if the newPassword is Pwned
if (PwnedPasswordsSearch.PwnedSearch.IsPwnedPassword(newPassword))
{
_logger.LogError("Failed due to pwned password: New password is publicly known and can be used in dictionary attacks");
return new ApiErrorItem(ApiErrorCode.PwnedPassword);
}
_logger.LogInformation($"PerformPasswordChange for user {fixedUsername}");
var item = ValidateGroups(userPrincipal);
if (item != null)
return item;
// Check if password change is allowed
if (userPrincipal.UserCannotChangePassword)
{
_logger.LogWarning("The User principal cannot change the password");
return new ApiErrorItem(ApiErrorCode.ChangeNotPermitted);
}
// Check if password expired or must be changed
if (_options.UpdateLastPassword && userPrincipal.LastPasswordSet == null)
{
SetLastPassword(userPrincipal);
}
// Use always UPN for password check.
if (!ValidateUserCredentials(userPrincipal.UserPrincipalName, currentPassword, principalContext))
{
_logger.LogWarning("The User principal password is not valid");
return new ApiErrorItem(ApiErrorCode.InvalidCredentials);
}
// Change the password via 2 different methods. Try SetPassword if ChangePassword fails.
ChangePassword(currentPassword, newPassword, userPrincipal);
userPrincipal.Save();
_logger.LogDebug("The User principal password updated with setPassword");
}
catch (PasswordException passwordEx)
{
var item = new ApiErrorItem(ApiErrorCode.ComplexPassword, passwordEx.Message);
_logger.LogWarning(item.Message, passwordEx);
return item;
}
catch (Exception ex)
{
var item = ex is ApiErrorException apiError
? apiError.ToApiErrorItem()
: new ApiErrorItem(ApiErrorCode.Generic, ex.InnerException?.Message ?? ex.Message);
_logger.LogWarning(item.Message, ex);
return item;
}
return null;
}