예제 #1
0
        public void UserManagerTest05_Create_Update_Validate_And_DeleteUser()
        {
            // create a new user and save to DB
            var user = userManager.CreateUser(TESTUSERID, PasswordHashing.EncodePassword("testHash".ToSecureString(), null));

            user.isActive          = true;                                                                                                                              // ensure we activate account so we can retrieve it later
            user.isPasswordExpired = false;                                                                                                                             // and don't want to be flagged as needing pw change
            Assert.Throws <SavedFailedException>(() => userManager.SaveUser(user));
            user.currentSite = DataRepository.GetDataRepository.ReferenceData["SiteLocation"].FirstOrDefault(x => ((SiteLocation)x).name == "Norfolk") as SiteLocation; // avoid FK constraint failure
            Assert.DoesNotThrow(() => userManager.SaveUser(user));

            // see if we can validate user with wrong passphrase
            Assert.IsFalse(userManager.ValidateUser(TESTUSERID, null, out user), "1" + nameof(userManager.ValidateUser));
            Assert.IsNull(user);
            Assert.IsFalse(userManager.ValidateUser(TESTUSERID, "BADHash".ToSecureString(), out user), "2" + nameof(userManager.ValidateUser));
            Assert.IsNull(user);

            // and again but with correct passphrase
            Assert.IsTrue(userManager.ValidateUser(TESTUSERID, "testHash".ToSecureString(), out user), "3" + nameof(userManager.ValidateUser));
            Assert.NotNull(user);

            userManager.RemoveUser(user);
            // verify actually removed
            Assert.IsFalse(userManager.ValidateUser(TESTUSERID, "testHash".ToSecureString(), out user), "4" + nameof(userManager.ValidateUser));
            Assert.IsNull(user);
        }
예제 #2
0
        public void TestGenerateAndCompareHashMatch()
        {
            byte[] saltAndHash = Convert.FromBase64String(PasswordHashing.EncodePassword(KnownPassword.ToSecureString(), null));
            byte[] salt        = PasswordHashing.ExtractStoredSalt(saltAndHash);

            Assert.That(salt, Is.Not.Null);
            Assert.That(PasswordHashing.HashesMatch(Convert.FromBase64String(PasswordHashing.EncodePassword(KnownPassword.ToSecureString(), salt)), saltAndHash));
        }
예제 #3
0
        public void TestHashDoesntMatch()
        {
            byte[] storedHash = Convert.FromBase64String(KnownHashAndSalt);
            byte[] salt       = PasswordHashing.GenerateSalt();
            byte[] curHash    = Convert.FromBase64String(PasswordHashing.EncodePassword(KnownPassword.ToSecureString(), salt));

            Assert.That(PasswordHashing.HashesMatch(storedHash, curHash), Is.False);
        }
예제 #4
0
        public void TestHashMatches()
        {
            byte[] storedHash = Convert.FromBase64String(KnownHashAndSalt);
            byte[] salt       = PasswordHashing.ExtractStoredSalt(storedHash);
            byte[] curHash    = Convert.FromBase64String(PasswordHashing.EncodePassword(KnownPassword.ToSecureString(), salt));

            Assert.That(PasswordHashing.HashesMatch(storedHash, curHash), Is.True);
        }
예제 #5
0
        public void TestEncode()
        {
            byte[] storedHash = Convert.FromBase64String(KnownHashAndSalt);
            byte[] salt       = PasswordHashing.ExtractStoredSalt(storedHash);
            byte[] curHash    = Convert.FromBase64String(PasswordHashing.EncodePassword(KnownPassword.ToSecureString(), salt));

            Assert.That(storedHash, Is.EqualTo(curHash), "Hashed Passphrase 'HACK' should be the same");
        }
예제 #6
0
 /// <summary>
 /// Allows [re]setting stored password hash
 /// </summary>
 /// <param name="passphrase">the password/phrase to hash</param>
 /// <param name="mustChange">defaults true, user must change on next log in; use false if user is setting/changing their own passphrase</param>
 public static void SetPasswordHash(this UserDetail user, SecureString passphrase, bool mustChange = true)
 {
     user.isPasswordExpired = mustChange;
     user.hashedPassphrase  = PasswordHashing.EncodePassword(passphrase, null);
 }
예제 #7
0
        /// <summary>
        /// Retrieve user information after validating provided userId and passphrase.
        /// If valid then returns true and updates user with UserDetails
        /// Otherwise returns false and sets user to null
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="passphrase"></param>
        /// <param name="user">creates new instance and returns validated user information</param>
        /// <returns>true if user input valid and user object container user information; false on any error validating</returns>
        public bool ValidateUser(string userId, SecureString passphrase, out UserDetail user)
        {
            logger.Trace(nameof(ValidateUser));
            // ensure we initialize user to null unless a valid userId and passphrase is provided
            user = null;

            // if not a valid value for DB key then fail early
            if (string.IsNullOrWhiteSpace(userId))
            {
                return(false);
            }

            try
            {
                // retrieve corresponding user information from DB
                // Note: userId [UserDetail DB table key] is stored in lower case (using CultureInvariant form)
                var possibleUser = GetUserDetailsFor(userId);
                // invalid userId or error loading from DB - failed to validate; Note early exit allows determination of usernames
                if (possibleUser == null)
                {
                    logger.Warn($"Failed to obtain possible user details for {userId}.");
                    return(false);
                }

                // get attempted password, exit early if obviously invalid passphrase (blank)
                // if (string.IsNullOrWhiteSpace(passphrase.ToString())) return false; -- passphrase is now a SecureString, don't defeat point and convert to string
                if ((passphrase == null) || (passphrase.Length < 1))
                {
                    logger.Warn($"Passphrase provided for {userId} is invalid.");
                    return(false);
                }

                // split apart stored hash so we can hash attempted password & compare
                bool isValid;
                try
                {
                    byte[] storedHash = Convert.FromBase64String(possibleUser.hashedPassphrase);
                    byte[] salt       = PasswordHashing.ExtractStoredSalt(storedHash);
                    // get hashed version of attempted password
                    byte[] curHash = Convert.FromBase64String(PasswordHashing.EncodePassword(passphrase, salt));

                    // determine if hashed passphrases are a match
                    isValid = PasswordHashing.HashesMatch(storedHash, curHash);
                }
                catch (System.FormatException e) // invalid Base64 string
                {
                    logger.Warn("Error validating credentials, likely stored passphrase corrupted / not base64 encoded!", e);
                    isValid = false;
                }
                // validated supplied password, now confirm user account not currently disabled
                isValid = isValid && possibleUser.isActive;

                // only return any information if user credentials successfully validated
                if (isValid)
                {
                    logger.Info("Valid user.");
                    user = possibleUser;
                }
                else
                {
                    logger.Warn($"Failed to validate credentials for user {userId}.");
                }

                return(isValid);
            }
            catch (Exception e)
            {
                logger.Error(e, $"Error occured when validating user - {e.Message}");
                throw;
            }
        }