public async Task ValidadeUserPasswordForHistoryAsync_Invalid_False()
        {
            // Arrange
            var          cxn             = new SqlConnectionWrapperMock();
            var          repository      = new SqlUserRepository(cxn.Object, cxn.Object);
            const int    userId          = 99;
            var          userSalt        = new Guid();
            const string newPassword     = "******";
            var          passwordHystory = new List <SqlUserRepository.HashedPassword>
            {
                new SqlUserRepository.HashedPassword {
                    Password = HashingUtilities.GenerateSaltedHash(newPassword, userSalt), UserSALT = userSalt
                }
            };

            cxn.SetupQueryAsync(
                "GetLastUserPasswords",
                new Dictionary <string, object>
            {
                { "@userId", userId }
            },
                passwordHystory);

            // Act
            var result = await repository.ValidateUserPasswordForHistoryAsync(userId, newPassword);

            // Assert
            cxn.Verify();
            Assert.AreEqual(false, result);
        }
        public async Task UpdateUserPasswordAsync(string login, string password)
        {
            var userSalt    = Guid.NewGuid();
            var newPassword = HashingUtilities.GenerateSaltedHash(password, userSalt);

            var parameters = new DynamicParameters();

            parameters.Add("@Login", login);
            parameters.Add("@UserSALT", userSalt);
            parameters.Add("@Password", newPassword);
            await _connectionWrapper.ExecuteAsync("UpdateUserOnPasswordResetAsync", parameters, commandType : CommandType.StoredProcedure);
        }
Beispiel #3
0
        public async Task ResetPassword(AuthenticationUser user, string oldPassword, string newPassword)
        {
            if (string.IsNullOrEmpty(newPassword))
            {
                throw new BadRequestException("Password reset failed, new password cannot be empty", ErrorCodes.EmptyPassword);
            }

            if (oldPassword != null && oldPassword == newPassword)
            {
                throw new BadRequestException("Password reset failed, new password cannot be equal to the old one", ErrorCodes.SamePassword);
            }

            if (newPassword.ToLower() == user.Login?.ToLower())
            {
                throw new BadRequestException("Password reset failed, new password cannot be equal to login name", ErrorCodes.PasswordSameAsLogin);
            }

            if (newPassword.ToLower() == user.DisplayName?.ToLower())
            {
                throw new BadRequestException("Password reset failed, new password cannot be equal to display name", ErrorCodes.PasswordSameAsDisplayName);
            }

            string errorMsg;

            if (!PasswordValidationHelper.ValidatePassword(newPassword, true, out errorMsg))
            {
                throw new BadRequestException("Password reset failed, new password is invalid", ErrorCodes.TooSimplePassword);
            }

            if (await IsChangePasswordCooldownInEffect(user))
            {
                throw new ConflictException("Password reset failed, password reset cooldown in effect", ErrorCodes.ChangePasswordCooldownInEffect);
            }

            if (!await _userRepository.ValidateUserPasswordForHistoryAsync(user.Id, newPassword))
            {
                throw new BadRequestException("The new password matches a previously used password.", ErrorCodes.PasswordAlreadyUsedPreviously);
            }

            var newGuid = Guid.NewGuid();

            user.UserSalt = newGuid;
            user.Password = HashingUtilities.GenerateSaltedHash(newPassword, user.UserSalt);

            await _userRepository.UpdateUserOnPasswordResetAsync(user);
        }
        public async Task <bool> ValidateUserPasswordForHistoryAsync(int userId, string newPassword)
        {
            var prm = new DynamicParameters();

            prm.Add("@userId", userId);
            var passwordHistory = await _connectionWrapper.QueryAsync <HashedPassword>("GetLastUserPasswords", prm, commandType : CommandType.StoredProcedure);

            foreach (var password in passwordHistory)
            {
                var newHashedPassword = HashingUtilities.GenerateSaltedHash(newPassword, password.UserSALT);
                if (string.Equals(newHashedPassword, password.Password))
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #5
0
        private AuthenticationStatus AuthenticateDatabaseUser(AuthenticationUser user, string password, int passwordExpirationInDays = 0)
        {
            var hashedPassword = HashingUtilities.GenerateSaltedHash(password, user.UserSalt);

            if (!string.Equals(user.Password, hashedPassword))
            {
                return(AuthenticationStatus.InvalidCredentials);
            }

            if (!user.IsEnabled)
            {
                return(AuthenticationStatus.Locked);
            }

            if (HasExpiredPassword(user, passwordExpirationInDays))
            {
                return(AuthenticationStatus.PasswordExpired);
            }

            return(AuthenticationStatus.Success);
        }
Beispiel #6
0
        public async Task <IHttpActionResult> PostPasswordResetAsync([FromBody] ResetPasswordContent content)
        {
            // the deserializer creates a zero filled guid when none provided
            if (content.Token == Guid.Empty || content.Token.GetHashCode() == 0)
            {
                throw new BadRequestException("Password reset failed, token not provided", ErrorCodes.PasswordResetEmptyToken);
            }

            var tokens = (await _userRepository.GetPasswordRecoveryTokensAsync(content.Token)).ToList();

            if (!tokens.Any())
            {
                // user did not request password reset
                throw new ConflictException("Password reset failed, recovery token not found.", ErrorCodes.PasswordResetTokenNotFound);
            }

            if (tokens.First().RecoveryToken != content.Token)
            {
                // provided token doesn't match last requested
                throw new ConflictException("Password reset failed, a more recent recovery token exists.", ErrorCodes.PasswordResetTokenNotLatest);
            }

            var tokenLifespan = await _applicationSettingsRepository.GetValue(PasswordResetTokenExpirationInHoursKey, DefaultPasswordResetTokenExpirationInHours);

            if (tokens.First().CreationTime.AddHours(tokenLifespan) < DateTime.Now)
            {
                // token expired
                throw new ConflictException("Password reset failed, recovery token expired.", ErrorCodes.PasswordResetTokenExpired);
            }

            var userLogin = tokens.First().Login;
            var user      = await _userRepository.GetUserByLoginAsync(userLogin);

            if (user == null)
            {
                // user does not exist
                throw new ConflictException("Password reset failed, the user does not exist.", ErrorCodes.PasswordResetUserNotFound);
            }

            if (!user.IsEnabled)
            {
                // user is disabled
                throw new ConflictException("Password reset failed, the login for this user is disabled.", ErrorCodes.PasswordResetUserDisabled);
            }

            string decodedNewPassword;

            try
            {
                decodedNewPassword = SystemEncryptions.Decode(content.Password);
            }
            catch (Exception)
            {
                throw new BadRequestException("Password reset failed, the provided password was not encoded correctly", ErrorCodes.PasswordDecodingError);
            }

            if (decodedNewPassword != null && user.Password == HashingUtilities.GenerateSaltedHash(decodedNewPassword, user.UserSalt))
            {
                throw new BadRequestException("Password reset failed, new password cannot be equal to the old one", ErrorCodes.SamePassword);
            }

            // reset password
            await _authenticationRepository.ResetPassword(user, null, decodedNewPassword);

            // drop user session
            var uri     = new Uri(WebApiConfig.AccessControl);
            var http    = _httpClientProvider.Create(uri);
            var request = new HttpRequestMessage {
                RequestUri = new Uri(uri, $"sessions/{user.Id}"), Method = HttpMethod.Delete
            };
            await http.SendAsync(request);

            return(Ok());
        }