Example #1
0
        /// <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)
                });
            }
        }
Example #2
0
        /// <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
            });
        }