/// <summary> /// Change a users password /// </summary> /// <param name="request"></param> /// <returns></returns> public ChangePasswordResponse ChangePassword(ChangePasswordRequest request) { try { // //Validate the parameters // if (request == null || String.IsNullOrWhiteSpace(request.UserName)) { return(new ChangePasswordResponse() { IsSuccessful = false, Message = "An invalid password change request was made." }); } // //Validate the new passwords are equal // if (!request.NewPassword.Equals(request.NewPasswordConfirm)) { return(new ChangePasswordResponse() { IsSuccessful = false, Message = "The passwords you entered must match." }); } // //Validate the new passwords meets complexity requirements // if (request.CheckPasswordComplexity) { var passwordComplexityRequest = new CheckPasswordComplexityRequest() { Password = request.NewPassword, UserName = request.UserName }; var passwordComplexityResponse = CheckPasswordComplexity(passwordComplexityRequest); if (!passwordComplexityResponse.IsSuccessful) { return(new ChangePasswordResponse() { IsSuccessful = false, Message = passwordComplexityResponse.Message }); } } // //Determine if this is for an AD user or a security user record //Get the SecurityUser Record if we have it // SecurityUser securityUser = null; ADUser adUser = null; if (request.SecurityUserId != null) { securityUser = _repository.GetAll <SecurityUser>() .FirstOrDefault(p => p.SecurityUserId == request.SecurityUserId); } // //Get the AD user if AD authentication is enabled, and we dont have a security user //or we dont have a security user active directory guid // if (DomainApplicationService.Instance.FormsAuthenticationADEnabled && (securityUser == null || securityUser.ActiveDirectoryGuid == null)) { adUser = new ADUser(request.UserName); if (adUser == null || !adUser.ValidUser) { adUser = null; } } else if (DomainApplicationService.Instance.FormsAuthenticationADEnabled && securityUser.ActiveDirectoryGuid != null) { adUser = new ADUser(securityUser.ActiveDirectoryGuid.Value); if (adUser == null || !adUser.ValidUser) { adUser = null; } } // //Ensure we found a user account to reset a password for // if (securityUser == null && adUser == null) { return(new ChangePasswordResponse() { IsSuccessful = false, Message = "A valid user could not be found to reset the password for." }); } // //Ensure the user account is active and not locked and its password can be reset // // if (request.CheckIfUserPasswordCanBeChanged) { var canUserPasswordBeChangedRequest = new CanUserPasswordBeChangedRequest() { SecurityUser = securityUser, ADUser = adUser, AuthenticationMethod = request.AuthenticationMethod }; var canUserPasswordBeChangedResponse = CanUserPasswordBeChanged(canUserPasswordBeChangedRequest); if (!canUserPasswordBeChangedResponse.IsSuccessful) { return(new ChangePasswordResponse() { IsSuccessful = false, Message = String.Format( "{0} Please contact support to have the password changed.", canUserPasswordBeChangedResponse.Message) }); } } DateTime?newPasswordExpirationDate = null; var passwordChanged = false; // //If AD user, connect to AD and reset the users password //Ensure the user is allowed to reset their password // if (adUser != null && (securityUser == null || request.AuthenticationMethod == AuthenticationMethods.ActiveDirectory.ToString())) { adUser.ChangePassword(request.NewPassword); newPasswordExpirationDate = adUser.PasswordExpiryDate; passwordChanged = true; } // //If Security User, then reset the users password there //Generate a new passwordhash, salt, and update the password last changed date as well as password expiration date //Store the users current password in the password history table if its a SecurityUser record. // else if (securityUser != null && (request.AuthenticationMethod == null || request.AuthenticationMethod == AuthenticationMethods.SecurityUser.ToString())) { // //Ensure the users current password matches what they typed into the screen // if (request.CheckCurrentPassword) { if (securityUser.PasswordHash != SHA256Hash.HashValue(request.CurrentPassword, securityUser.PasswordSalt)) { return(new ChangePasswordResponse() { IsSuccessful = false, Message = "An invalid current password was entered." }); } } // //Enforce password history, where a password cannot be one of the previously used passwords. // if (request.EnforcePasswordHistory) { // //Ensure the new password is not the current password // if (securityUser.PasswordHash == SHA256Hash.HashValue(request.NewPassword, securityUser.PasswordSalt)) { return(new ChangePasswordResponse() { IsSuccessful = false, Message = "The new password cannot be the same as the current password." }); } // //Validate that the new password is not in the password history //as a previously used password // var passwordHistoryRecordsToCheck = ApplicationService.Instance.PasswordHistoryRecordsToCheckOnPasswordChange; if (passwordHistoryRecordsToCheck > 0) { var passwordHistory = _repository.GetAll <SecurityUserPasswordHistory>() .Where(p => p.SecurityUserId == securityUser.SecurityUserId) .OrderBy(p => p.CreateDate) .Take(passwordHistoryRecordsToCheck) .ToList(); foreach (var p in passwordHistory) { if (p.PasswordHash == SHA256Hash.HashValue(request.NewPassword, p.PasswordSalt)) { return(new ChangePasswordResponse() { IsSuccessful = false, Message = "The new password cannot be one of the previously used passwords." }); } } } } // //Create the password history entry for the users current password // var securityUserPasswordHistory = new SecurityUserPasswordHistory() { SecurityUserId = securityUser.SecurityUserId, PasswordHash = securityUser.PasswordHash, PasswordSalt = securityUser.PasswordSalt }; _repository.Add(securityUserPasswordHistory); // //Update the security user record // securityUser.PasswordLastChangedDate = DateTime.Now; securityUser.PasswordSalt = SHA256Hash.CreateSalt(6); securityUser.PasswordHash = SHA256Hash.HashValue(request.NewPassword, securityUser.PasswordSalt); if (securityUser.PasswordNeverExpires) { securityUser.PasswordExpirationDate = null; } else { var passwordExpirationDateResponse = CalculatePasswordExpirationDate(new CalculatePasswordExpirationDateRequest()); securityUser.PasswordExpirationDate = passwordExpirationDateResponse.PasswordExpirationDate; } newPasswordExpirationDate = securityUser.PasswordExpirationDate; passwordChanged = true; } // //If for some reason the password couldnt be changed // if (!passwordChanged) { return(new ChangePasswordResponse() { IsSuccessful = false, Message = "The password could not be changed. Please report this error. No AD User or SecurityUser record could be obtained to change the password for." }); } _repository.Commit(); // //Repopulate the current users session values if needed // if (DomainSessionService.Instance != null && DomainSessionService.Instance.CurrentUser != null && request.UserName.Equals(DomainSessionService.Instance.CurrentUser.UserName)) { DomainSessionService.Instance.CurrentUser.PasswordExpirationDate = newPasswordExpirationDate; DomainSessionService.Instance.CurrentUser.PasswordLastChangedDate = DateTime.Now; } // //Send the user an email to confirm that their password has been reset // if (request.SendPasswordSuccessfullyChangedEmail) { var sendPasswordChangedEmailRequest = new SendPasswordChangedEmailRequest() { SecurityUser = securityUser, ADUser = adUser }; var sendPasswordChangedEmailResponse = SendPasswordChangedEmail(sendPasswordChangedEmailRequest); } // //Password change was successful if we got to here // return(new ChangePasswordResponse() { IsSuccessful = true, Message = null, PasswordExpirationDate = newPasswordExpirationDate }); } catch (Exception e) { LogService.Instance.Log.Error("An unhandled exception occurred changing the password. ", e); return(new ChangePasswordResponse() { IsSuccessful = false, Message = String.Format("An unhandled exception occurred changing the password. {0}", e.Message) }); } }
/// <summary> /// Determine if a user can change their password or not. /// </summary> /// <param name="request">The request object containing the ADUser or SecurityUser to check, </param> /// <returns>Response object where IsSuccessful is True if the password can be changed, false if it doesnt.</returns> public CanUserPasswordBeChangedResponse CanUserPasswordBeChanged(CanUserPasswordBeChangedRequest request) { // //If there are no users found, we cannot reset the password // if (request.ADUser == null && request.SecurityUser == null) { return(new CanUserPasswordBeChangedResponse() { IsSuccessful = false, Message = "Neither the SecurityUser or ADUser record was specified to determine if the password could be changed for it." }); } // //We have only one user now, validate it can have a password reset // //Ensure AD allows it to be reset if (request.ADUser != null && (request.SecurityUser == null || request.AuthenticationMethod == AuthenticationMethods.ActiveDirectory.ToString())) { if (request.ADUser.UserCannotChangePassword || request.ADUser.AccountDisabled || request.ADUser.AccountLockedOut || !ApplicationService.Instance.PasswordChangeAllowedForADUser) { return(new CanUserPasswordBeChangedResponse() { IsSuccessful = false, Message = String.Format("Username {0} cannot have it's password reset.", request.ADUser.UserName) }); } } //And ensure SecurityUser allows it to be reset if (request.SecurityUser != null) { if (request.SecurityUser.AccountLocked || !request.SecurityUser.Active || request.SecurityUser.UserCannotChangePassword || (request.SecurityUser.AccountExpirationDate != null && request.SecurityUser.AccountExpirationDate <= DateTime.Now) || request.SecurityUser.UserName.Equals("Anonymous")) { var errorDetails = ""; if (!request.SecurityUser.Active) { errorDetails = "The user is not active."; } else if (request.SecurityUser.UserCannotChangePassword) { errorDetails = "The user cannot change their password."; } else if (request.SecurityUser.AccountExpirationDate != null && request.SecurityUser.AccountExpirationDate <= DateTime.Now) { errorDetails = "The user's account is expired."; } else if (request.SecurityUser.UserName.Equals("Anonymous")) { errorDetails = "Passwords may not be set for the anonymous user."; } return(new CanUserPasswordBeChangedResponse() { IsSuccessful = false, Message = String.Format("Username {0} cannot have it's password changed. {1}", request.SecurityUser.UserName, errorDetails) }); } } // //If we get here then the users password can be changed // return(new CanUserPasswordBeChangedResponse() { IsSuccessful = true, Message = null }); }
/// <summary> /// Process the request for a forgotten password from the main forgot password screen. This will lookup the /// user and if found email them a link to reset their password. /// </summary> /// <param name="model"></param> public SendInstructionsToResetPasswordResponse SendInstructionsToResetPassword(SendInstructionsToResetPasswordRequest request) { // //Validate the parameters // if (request == null || String.IsNullOrWhiteSpace(request.UserNameOrEmail)) { return(new SendInstructionsToResetPasswordResponse() { IsSuccessful = false, Message = "An invalid user name or email address was specified." }); } SecurityUser securityUser = null; ADUser adUser = null; // //See if we can reset this users active directory account. We only need to do this //if active directory auth is enabled, if AD users are allowed to reset their password, //and we are not storing the users in the SecurityUser table. // if (ApplicationService.Instance.FormsAuthenticationADEnabled && ApplicationService.Instance.ForgotPasswordResetAllowedForADUser && adUser == null && securityUser == null ) { // //Try to find by username first // adUser = new ADUser(request.UserNameOrEmail); // //If not found, try to find by email address // if (!adUser.ValidUser) { var searchFilter = adUser.GetUserSearchFilterByEmailAddress(request.UserNameOrEmail); adUser.PopulateUserInformation(searchFilter); } //Ensure we clear the record if we dont have a valid AD user if (!adUser.ValidUser) { adUser = null; } // //Get the security user record if we have security user records for AD users // else { if (ApplicationService.Instance.FormsAuthenticationCreateSecurityUserRecordOnADAuth) { securityUser = _repository.GetAll <SecurityUser>() .FirstOrDefault(p => p.ActiveDirectoryGuid == adUser.ObjectGuid); } } } // //Then try to find the user by their SecurityUser table record // if (ApplicationService.Instance.FormsAuthenticationSecurityUserTableEnabled && adUser == null && securityUser == null) { // //First try lookup only by userid //Check the security user table first // var securityUsers = _repository.GetAll <SecurityUser>().Where(p => p.UserName.Equals(request.UserNameOrEmail)); //If no match found, try lookup by email address if (!securityUsers.Any()) { securityUsers = _repository.GetAll <SecurityUser>() .Where(p => p.EmailAddress.Equals(request.UserNameOrEmail)); } // //If there is more than one result, we cannot reset the password // if (securityUsers.Count() > 1) { return(new SendInstructionsToResetPasswordResponse() { IsSuccessful = false, Message = "Multiple records were found with the supplied username or email, your password cannot be reset. Please contact support to have your password reset." }); } securityUser = securityUsers.FirstOrDefault(); } // //Now ensure we can continue with the password reset // // var canUserPasswordBeChangedRequest = new CanUserPasswordBeChangedRequest() { SecurityUser = securityUser, ADUser = adUser }; var canUserPasswordBeChangedResponse = _passwordService.CanUserPasswordBeChanged(canUserPasswordBeChangedRequest); if (!canUserPasswordBeChangedResponse.IsSuccessful) { return(new SendInstructionsToResetPasswordResponse() { IsSuccessful = false, Message = "That username or email address cannot have it's password reset. Please contact support to have your password reset." }); } // //Ensure the user has an email address // if ((securityUser == null || String.IsNullOrWhiteSpace(securityUser.EmailAddress)) && (adUser == null || String.IsNullOrWhiteSpace(adUser.EmailAddress))) { return(new SendInstructionsToResetPasswordResponse() { IsSuccessful = false, Message = "That username or email address cannot have it's password reset as it has no email on file. Please contact support to have your password reset." }); } // //Create the password reset entry // var passwordResetRequest = CreateSecurityPasswordResetRequestEntry(request, securityUser, adUser); // //Send the password reset email // var sendForgotPasswordEmailRequest = new SendForgotPasswordEmailRequest() { SecurityUser = securityUser, ADUser = adUser, SecurityPasswordResetRequest = passwordResetRequest }; var sendForgotPasswordEmailResponse = SendForgotPasswordEmail(sendForgotPasswordEmailRequest); if (!sendForgotPasswordEmailResponse.IsSuccessful) { return(new SendInstructionsToResetPasswordResponse() { IsSuccessful = false, Message = sendForgotPasswordEmailResponse.Message }); } // //Request was successful // return(new SendInstructionsToResetPasswordResponse() { IsSuccessful = true, Message = null }); }