/// <summary> /// Change user password /// </summary> public bool ChangePassword(string userName, string currentPassword, string newPassword, out string errorReason) { var identity = LdapIdentity.ParseUser(userName); errorReason = null; try { LdapProfile userProfile; using (var connection = new LdapConnection(_configuration.Domain)) { connection.Credential = new NetworkCredential(identity.Name, currentPassword); connection.Bind(); var domain = LdapIdentity.FqdnToDn(_configuration.Domain); var isProfileLoaded = LoadProfile(connection, domain, identity, out var profile); if (!isProfileLoaded) { errorReason = Resources.AD.UnableToChangePassword; return(false); } userProfile = profile; } _logger.Debug($"Changing password for user '{identity.Name}' in {userProfile.BaseDn.DnToFqdn()}"); using (var ctx = new PrincipalContext(ContextType.Domain, userProfile.BaseDn.DnToFqdn(), null, ContextOptions.Negotiate, identity.Name, currentPassword)) { using (var user = UserPrincipal.FindByIdentity(ctx, IdentityType.DistinguishedName, userProfile.DistinguishedName)) { user.ChangePassword(currentPassword, newPassword); user.Save(); } } _logger.Debug($"Password changed for user '{identity.Name}'"); return(true); } catch (PasswordException pex) { _logger.Warning($"Changing password for user '{identity.Name}' failed: {pex.Message}, {pex.HResult}"); errorReason = Resources.AD.PasswordDoesNotMeetRequirements; } catch (Exception ex) { _logger.Warning($"Changing password for user {identity.Name} failed: {ex.Message}"); errorReason = Resources.AD.UnableToChangePassword; } return(false); }
/// <summary> /// Verify User Name, Password, User Status and Policy against Active Directory /// </summary> public ActiveDirectoryCredentialValidationResult VerifyCredential(string userName, string password) { if (string.IsNullOrEmpty(userName)) { throw new ArgumentNullException(nameof(userName)); } if (string.IsNullOrEmpty(password)) { _logger.Error($"Empty password provided for user '{userName}'"); return(ActiveDirectoryCredentialValidationResult.UnknowError("Invalid credentials")); } var user = LdapIdentity.ParseUser(userName); try { _logger.Debug($"Verifying user '{user.Name}' credential and status at {_configuration.Domain}"); using (var connection = new LdapConnection(_configuration.Domain)) { connection.Credential = new NetworkCredential(user.Name, password); connection.Bind(); _logger.Information($"User '{user.Name}' credential and status verified successfully at {_configuration.Domain}"); var domain = LdapIdentity.FqdnToDn(_configuration.Domain); var isProfileLoaded = LoadProfile(connection, domain, user, out var profile); if (!isProfileLoaded) { return(ActiveDirectoryCredentialValidationResult.UnknowError("Unable to load profile")); } var checkGroupMembership = !string.IsNullOrEmpty(_configuration.ActiveDirectory2FaGroup); if (checkGroupMembership) { var isMemberOf = IsMemberOf(connection, profile.BaseDn, user, _configuration.ActiveDirectory2FaGroup); if (!isMemberOf) { _logger.Information($"User '{user.Name}' is NOT member of {_configuration.ActiveDirectory2FaGroup} group"); _logger.Information($"Bypass second factor for user '{user.Name}'"); return(ActiveDirectoryCredentialValidationResult.ByPass()); } _logger.Information($"User '{user.Name}' is member of {_configuration.ActiveDirectory2FaGroup} group"); } var result = ActiveDirectoryCredentialValidationResult.Ok(); result.DisplayName = profile.DisplayName; result.Email = profile.Email; if (_configuration.UseActiveDirectoryUserPhone) { result.Phone = profile.Phone; } if (_configuration.UseActiveDirectoryMobileUserPhone) { result.Phone = profile.Mobile; } return(result); } } catch (LdapException lex) { var result = ActiveDirectoryCredentialValidationResult.KnownError(lex.ServerErrorMessage); _logger.Warning($"Verification user '{user.Name}' at {_configuration.Domain} failed: {result.Reason}"); return(result); } catch (Exception ex) { _logger.Error(ex, $"Verification user '{user.Name}' at {_configuration.Domain} failed."); return(ActiveDirectoryCredentialValidationResult.UnknowError()); } }