示例#1
0
        /// <summary>
        /// Invalidates a session token so it can no longer be used.
        /// </summary>
        /// <param name="token"></param>
        /// <param name="ipAddress"></param>
        /// <param name="result"></param>
        public virtual void InvalidateSession(string token, String ipAddress, ExecutionResults result)
        {
            const string errorMsg = "Authentication token invalid.";

            Guid renewalToken;

            if (!Guid.TryParse(token, out renewalToken))
            {
                result.AppendError(errorMsg);
                return;
            }

            var session = GetUserSession(renewalToken);

            if (session == null)
            {
                return; //sure is invalidated, doesn't exist.
            }
            if (session.ExpirationDate < DateTime.UtcNow)
            {
                return; //already invalidated.
            }
            session.ExpirationDate = DateTime.UtcNow;
            SaveUserSession(session);
        }
示例#2
0
        /// <summary>
        /// Authenticates against the data store and returns a UserIdentity given
        /// a token returned from a previous authentication.
        /// </summary>
        /// <param name="token">The unique token.</param>
        /// <param name="duration">The amount of time that the renewed token will be valid.</param>
        /// <param name="ipAddress">The internet address where the user is connecting from.</param>
        /// <param name="result">A ExecutionResults instance to add applicable
        /// warning and error messages to.</param>
        /// <returns>
        /// A valid user identity instance.  If the token is incorrect or expired
        /// then the IsAuthenticated flag will be false.  Otherwise the identity
        /// will be authenticated.
        /// </returns>
        public virtual UserIdentity AuthenticateUser(string token, UserSessionDurationType duration, String ipAddress, ExecutionResults result)
        {
            const string errorMsg = "Authentication token invalid.";
            Guid         renewalToken;

            if (!Guid.TryParse(token, out renewalToken))
            {
                result.AppendError(errorMsg);
                return(new UserIdentity());
            }
            var session = GetUserSession(renewalToken);

            if (session == null)
            {
                result.AppendError(errorMsg);
                return(new UserIdentity());
            }
            if (session.ExpirationDate < DateTime.UtcNow)
            {
                result.AppendError(errorMsg);
                return(new UserIdentity());
            }

            var history = GetSessionAuthenticationHistory(session);

            if (history == null)
            {
                result.AppendError(errorMsg);
                return(new UserIdentity());
            }
            if (history.IPAddress != ipAddress && !DisableIpAddressSessionLock)
            {                               //coming from a new IPAddress, token was stolen or user is coming from a new dynamic IP address (new internet connection?)
                result.AppendError(errorMsg);
                return(new UserIdentity()); //force new login with password (essentially approves this new IP address)
                //WARN: This is a weak valid check.  An imposter can fake the source IP, and a legitimate user could hop IP Addresses during a single session (mobile device)
            }

            if ((DateTime.UtcNow - session.RenewedDate).Duration() > TimeSpan.FromMinutes(1))
            {   //reduce the number of writes.  Only need to know within a minute how many active users there are.  There may be many json requests for a single page in a minute.
                session.RenewedDate    = DateTime.UtcNow;
                session.ExpirationDate = DateTime.UtcNow.AddMinutes(duration == UserSessionDurationType.PublicComputer ? PublicSessionDuration : ExtendedSessionDuration);
                SaveUserSession(session);
            }
            history.UserSession = session;
            return(new UserIdentity(history, Name));
        }
示例#3
0
 /// <summary>
 /// Validates that a password meets minimum requirements.
 /// </summary>
 /// <param name="password"></param>
 /// <param name="results"></param>
 /// <returns></returns>
 public virtual bool ValidatePassword(string password, ExecutionResults results)
 {
     if (!PasswordRegex.IsMatch(password))
     {
         results.AppendError(PasswordErrorMessage);
         return(false);
     }
     return(true);
 }
示例#4
0
 /// <summary>
 /// Validates that the specified name meets minimum requirements.
 /// </summary>
 /// <param name="name">The desired name/alias.</param>
 /// <param name="result">Any error messages about the desired name.</param>
 /// <returns></returns>
 public virtual bool ValidateName(string name, ExecutionResults result)
 {
     if (!NameRegex.IsMatch(name) && !EmailRegex.IsMatch(name))
     {
         //if this message is changed, do the same anywhere else it is used
         result.AppendError(
             "The name contains invalid characters.  The name must be an email address OR contain only letters, numbers, dashes, underscores, and spaces, are allowed.");
         return(false);
     }
     return(true);
 }
示例#5
0
 private cs.UserIdentity FailAuthenticateUser(string name, string ipAddress, ExecutionResults result)
 {
     result.AppendError(LoginCredentialsFailureMessage);
     InsertUserHistory(new AuthenticationHistory()
     {
         UserName        = name,
         IPAddress       = ipAddress,
         IsAuthenticated = false
     });
     return(new cs.UserIdentity());
 }
 /// <summary>
 /// Returns a failed authentication attempt, an anonymous user identity.
 /// </summary>
 /// <param name="name">The user name.</param>
 /// <param name="ipAddress">The IP address the user was coming from.</param>
 /// <param name="result">A container for error messages.</param>
 /// <returns></returns>
 protected UserIdentity FailAuthenticateUser(string name, string ipAddress, ExecutionResults result)
 {
     result.AppendError(LoginCredentialsFailureMessage);
     InsertUserHistory(new AuthenticationHistory
     {
         CreatedDate     = DateTime.UtcNow,
         UserName        = name,
         IPAddress       = ipAddress,
         IsAuthenticated = false
     });
     return(new UserIdentity());
 }
示例#7
0
        /// <summary>
        /// Authenticates against the data store and returns a UserIdentity given
        /// a token returned from a previous authentication.
        /// </summary>
        /// <param name="token">The unique token.</param>
        /// <param name="duration">The amount of time that the renewed token will be valid.</param>
        /// <param name="ipAddress">The internet address where the user is connecting from.</param>
        /// <param name="result">A ExecutionResults instance to add applicable
        /// warning and error messages to.</param>
        /// <returns>
        /// A valid user identity instance.  If the token is incorrect or expired
        /// then the IsAuthenticated flag will be false.  Otherwise the identity
        /// will be authenticated.
        /// </returns>
        public override UserIdentity AuthenticateUser(string token, UserSessionDurationType duration, String ipAddress, ExecutionResults result)
        {
            String errorMsg = "Authentication token invalid.";
            Guid   renewalToken;

            if (!Guid.TryParse(token, out renewalToken))
            {
                result.AppendError(errorMsg);
                return(new cs.UserIdentity());
            }
            UserSession session = GetUserSession(renewalToken);

            if (session == null)
            {
                result.AppendError(errorMsg);
                return(new cs.UserIdentity());
            }
            AuthenticationHistory history = GetSessionAuthenticationHistory(session);

            if (history == null)
            {
                result.AppendError(errorMsg);
                return(new cs.UserIdentity());
            }
            else if (history.IPAddress != ipAddress)
            {                                  //coming from a new IPAddress, token was stolen or user is coming from a new dynamic IP address (new internet connection?)
                result.AppendError(errorMsg);
                return(new cs.UserIdentity()); //force new login with password (essentially approves this new IP address)
                //WARN: is this a valid check?  Can an imposter just fake the source IP?  Could a legitimate user hop IP Addresses during a single session?
            }

            session.RenewedDate    = DateTime.UtcNow;
            session.ExpirationDate = DateTime.UtcNow.AddMinutes(duration == UserSessionDurationType.PublicComputer ? PublicSessionDuration : ExtendedSessionDuration);
            SaveUserSession(session);
            history.UserSession = session;
            return(new UserIdentity(history, this.Name));
        }
示例#8
0
        public virtual ActionResult ForgotPassword(ForgotPasswordViewModel model)
        {
            if (this.ModelState.IsValid)
            {
                var result    = new ExecutionResults();
                var resetCode = UserManager.GenerateUserResetCode(model.UserName);
                if (!String.IsNullOrWhiteSpace(resetCode)) //user found
                {
                    //TODO: generate email body with reset code.
                }
                else
                {
                    //TODO: generate alternate body telling how to sign up.
                }
#warning TODO: send the reset code via email (or signup instructions if account does not exist) and then show a view with email confirmation.
                //TODO: send the email (whether user found or not!)
                //TODO: return an ActionResult if successful

                result.AppendError("The forgot password functionality is not yet implemented.");

                //failed business layer rules
                if (this.IsJsonRequest())
                {
                    return(Json(new { success = false, message = result.ToHtmlString() }));
                }
                else
                {
                    for (int e = 0; e < result.Messages.Count; e++)
                    {
                        this.ModelState.AddModelError(e.ToString(CultureInfo.InvariantCulture), result.Messages[e].Message);
                    }
                    return(this.View(model));
                }
            }
            if (this.IsJsonRequest())
            {
                return(Json(new { success = false, errors = this.ModelState.ToJson() }));
            }
            else
            {
                return(this.View(model)); //modelstate already populated
            }
        }
示例#9
0
        /// <summary>
        /// Registers a new user.  The PasswordHash property should be the actual password.
        /// </summary>
        /// <param name="user">A user with a raw password which is turned into a password hash as part of registration.</param>
        /// <param name="duration">The amount of time that the initial session will be valid.</param>
        /// <param name="ipAddress">The internet address where the user is connecting from.</param>
        /// <param name="result">A ExecutionResults instance to add applicable
        /// warning and error messages to.</param>
        /// <returns>A boolean indicating success (true) or failure (false).</returns>
        public override UserIdentity RegisterUser(User user, UserSessionDurationType duration, String ipAddress, ExecutionResults result)
        {
            string password = user.PasswordHash;

            if (!ValidateName(user.Name, result) || !ValidatePassword(password, result))
            {
                return(new cs.UserIdentity());
            }

            var existing = GetUserByName(user.Name);

            if (existing != null)
            {   //seed user table with deleted users with names you don't want users to have
                result.AppendError("The name you specified cannot be used.");
                return(new cs.UserIdentity());
            }
            if (user.UserID.Equals(Guid.Empty))
            {
                user.UserID = Guid.NewGuid();
            }

            HashProvider hasher = HashManager.SelectProvider();
            var          salt   = new UserSalt
            {
                PasswordSalt = hasher.GetSalt(),
                UserID       = user.UserID,
                HashGroup    = new Random(DateTime.Now.Second).Next(HashGroupMinimum, HashGroupMaximum),
                HashName     = hasher.Name
            };

            user.PasswordHash = hasher.Hash(salt.PasswordSalt, password,
                                            salt.HashGroup + BaseHashIterations);
            using (var scope = new System.Transactions.TransactionScope())
            {
                //starts as a lightweight transaction
                SaveUser(user);
                //enlists in a full distributed transaction if users and salts have different connection strings
                SaveUserSalt(salt);
            }
            return(AuthenticateUser(name: user.Name, password: password, duration: duration,
                                    ipAddress: ipAddress, checkHistory: false, allowUpdateHash: false, result: result));
        }
示例#10
0
        /// <summary>
        /// Base logic to register a full user, or a guest user.  Creates the appropriate records and the proper validation.
        /// </summary>
        /// <param name="user">A user with a raw password which is turned into a password hash as part of registration.</param>
        /// <param name="result">A ExecutionResults instance to add applicable
        /// warning and error messages to.</param>
        /// <returns>A boolean indicating success (true) or failure (false).</returns>
        protected virtual bool RegisterBase(User user, ExecutionResults result)
        {
            var password = user.PasswordHash;

            if (!ValidateName(user.Name, result) || !ValidatePassword(password, result))
            {
                return(false);
            }

            var existing = GetUserByName(user.Name);

            if (existing != null)
            {   //seed user table with deleted users with names you don't want users to have
                result.AppendError("The name you specified cannot be used.");
                return(false);
            }
            if (user.UserID.Equals(Guid.Empty))
            {
                user.UserID = Guid.NewGuid();
            }

            var hasher = HashManager.SelectProvider();
            var salt   = new UserSalt
            {
                PasswordSalt = hasher.GetSalt(),
                UserID       = user.UserID,
                HashGroup    = new Random(DateTime.Now.Second).Next(HashGroupMinimum, HashGroupMaximum),
                HashName     = hasher.Name
            };

            user.PasswordHash = hasher.Hash(salt.PasswordSalt, password,
                                            salt.HashGroup + BaseHashIterations);
            using (var scope = new System.Transactions.TransactionScope())
            {
                //starts as a lightweight transaction
                SaveUser(user);
                //enlists in a full distributed transaction if users and salts have different connection strings
                SaveUserSalt(salt);
                scope.Complete();
            }
            return(true);
        }
 public virtual ActionResult Register(RegisterViewModel model, string returnUrl)
 {
     if (ModelState.IsValid)
     {
         var results  = new ExecutionResults();
         var user     = model.ToUser();
         var identity = UserManager.RegisterUser(user, UserSessionDurationType.Extended, Request.UserHostAddress, results);
         if (results.Success)
         {   //successful registration
             SecurityContextManager.CurrentUser = new UserPrincipal(identity);
             return(RedirectToLocal(returnUrl));
         }
         //failed business layer
         results.AppendError("Failed to complete registration.");
         for (var e = 0; e < results.Messages.Count; e++)
         {
             ModelState.AddModelError(e.ToString(CultureInfo.InvariantCulture), results.Messages[e].Message);
         }
     }
     //failed data annotation validations
     model.Load();
     return(View(model));
 }
示例#12
0
        /// <summary>
        /// Base logic to register a full user, or a guest user.  Creates the appropriate records and the proper validation.
        /// </summary>
        /// <param name="user">A user with a raw password which is turned into a password hash as part of registration.</param>
        /// <param name="result">A ExecutionResults instance to add applicable
        /// warning and error messages to.</param>
        /// <returns>A boolean indicating success (true) or failure (false).</returns>
        protected virtual bool RegisterBase(User user, ExecutionResults result)
        {
            var password = user.PasswordHash;
            if (!ValidateName(user.Name, result) || !ValidatePassword(password, result))
                return false;

            var existing = GetUserByName(user.Name);
            if (existing != null)
            {   //seed user table with deleted users with names you don't want users to have
                result.AppendError("The name you specified cannot be used.");
                return false;
            }
            if (user.UserID.Equals(Guid.Empty))
                user.UserID = Guid.NewGuid();

            var hasher = HashManager.SelectProvider();
            var salt = new UserSalt
            {
                PasswordSalt = hasher.GetSalt(),
                UserID = user.UserID,
                HashGroup = new Random(DateTime.Now.Second).Next(HashGroupMinimum, HashGroupMaximum),
                HashName = hasher.Name
            };
            user.PasswordHash = hasher.Hash(salt.PasswordSalt, password,
                                                   salt.HashGroup + BaseHashIterations);
            using (var scope = new System.Transactions.TransactionScope())
            {
                //starts as a lightweight transaction
                SaveUser(user);
                //enlists in a full distributed transaction if users and salts have different connection strings
                SaveUserSalt(salt);
                scope.Complete();
            }
            return true;
        }
示例#13
0
 /// <summary>
 /// Returns a failed authentication attempt, an anonymous user identity.
 /// </summary>
 /// <param name="name">The user name.</param>
 /// <param name="ipAddress">The IP address the user was coming from.</param>
 /// <param name="result">A container for error messages.</param>
 /// <returns></returns>
 protected UserIdentity FailAuthenticateUser(string name, string ipAddress, ExecutionResults result)
 {
     result.AppendError(LoginCredentialsFailureMessage);
     InsertUserHistory(new AuthenticationHistory
         {
             CreatedDate = DateTime.UtcNow,
             UserName = name,
             IPAddress = ipAddress,
             IsAuthenticated = false
         });
     return new UserIdentity();
 }
示例#14
0
 /// <summary>
 /// Validates that a password meets minimum requirements.
 /// </summary>
 /// <param name="password"></param>
 /// <param name="results"></param>
 /// <returns></returns>
 public virtual bool ValidatePassword(string password, ExecutionResults results)
 {
     if (!PasswordRegex.IsMatch(password))
     {
         results.AppendError(PasswordErrorMessage);
         return false;
     }
     return true;
 }
示例#15
0
 /// <summary>
 /// Validates that the specified name meets minimum requirements.
 /// </summary>
 /// <param name="name">The desired name/alias.</param>
 /// <param name="result">Any error messages about the desired name.</param>
 /// <returns></returns>
 public virtual bool ValidateName(string name, ExecutionResults result)
 {
     if (!NameRegex.IsMatch(name) && !EmailRegex.IsMatch(name))
     {
         //if this message is changed, do the same anywhere else it is used
         result.AppendError(
             "The name contains invalid characters.  The name must be an email address OR contain only letters, numbers, dashes, underscores, and spaces, are allowed.");
         return false;
     }
     return true;
 }
示例#16
0
 /// <summary>
 /// updates a user's name and/or password.
 /// </summary>
 /// <param name="item">The user details to be saved.  If Password is empty is it not changed.  If specified it should be the new raw password (not a hash).</param>
 /// <param name="currentPassword">The current raw password for the user used to authenticate that the change can be made, or the current resetcode last sent to this user.</param>
 /// <param name="ipAddress">The internet address where the user is connecting from.</param>
 /// <param name="result">A ExecutionResults instance to add applicable
 /// warning and error messages to.</param>
 /// <returns>A boolean indicating success (true) or failure (false).</returns>
 public virtual bool UpdateUser(User item, String currentPassword, String ipAddress, ExecutionResults result)
 {
     if (item.UserID.Equals(Guid.Empty))
         throw new ArgumentException("The user identity must be specified.");
     var user = GetUserByID(item.UserID);
     var salt = GetUserSalt(item.UserID);
     if (user == null || salt == null)
     {
         result.AppendError("The specified user identity does not exist.");
         return false;
     }
     if (salt.ResetCode == currentPassword)
     {
         if (salt.ResetCodeExpiration < DateTime.UtcNow)
         {
             result.AppendError(
                 user.IsGuest
                 ? "Your account verification code has expired.  Request a password reset to complete your registration."
                 : "Your password reset code has expired.  Request a new one to be sent to you, and then use it immediately.");
             return false;
         }
         salt.ResetCode = null;
         salt.ResetCodeExpiration = DateTime.UtcNow;
     }
     else
     {
         var rememberMe = !SecurityContextManager.IsAnonymous &&
                           SecurityContextManager.CurrentUser.Identity.Ticket.UserSession.ExpirationDate >
                           DateTime.UtcNow.AddMinutes(PublicSessionDuration);
         if (!AuthenticateUser(name: item.Name, password: currentPassword, ipAddress: ipAddress,
                               duration: rememberMe ? UserSessionDurationType.Extended : UserSessionDurationType.PublicComputer,
                               allowUpdateHash: false, checkHistory: false, result: result).IsAuthenticated)
         {
             result.AppendError("Cannot change password due to authentication error with current password.");
             return false;
         }
     }
     if (user.Name != item.Name)
     {   //user is changing their sign in name.  Make sure the new name is available.
         var nameExisting = GetUserByName(item.Name);
         if (nameExisting != null)
         {
             result.AppendError("The name you specified cannot be used.");
             return false;
         }
         user.Name = item.Name;
     }
     if (!String.IsNullOrEmpty(item.PasswordHash))
     {
         var password = item.PasswordHash;
         //update hashes on regular basis, keeps the iterations in latest range for current users, and with a 'current' hash provider.
         HashProvider hasher = HashManager.SelectProvider();
         salt.PasswordSalt = hasher.GetSalt();
         salt.HashGroup = new Random(DateTime.Now.Second).Next(HashGroupMinimum, HashGroupMaximum);
         salt.HashName = hasher.Name;
         user.PasswordHash = hasher.Hash(salt.PasswordSalt, password, salt.HashGroup + BaseHashIterations);
         user.PasswordUpdatedDate = DateTime.UtcNow;
     }
     using (var scope = new System.Transactions.TransactionScope())
     {
         //starts as a lightweight transaction
         SaveUser(user);
         //enlists in a full distributed transaction if users and salts have different connection strings
         SaveUserSalt(salt);
         scope.Complete();
     }
     return true;
 }
示例#17
0
        /// <summary>
        /// Authenticates against the data store and returns a UserIdentity given
        /// a token returned from a previous authentication.
        /// </summary>
        /// <param name="token">The unique token.</param>
        /// <param name="duration">The amount of time that the renewed token will be valid.</param>
        /// <param name="ipAddress">The internet address where the user is connecting from.</param>
        /// <param name="result">A ExecutionResults instance to add applicable
        /// warning and error messages to.</param>
        /// <returns>
        /// A valid user identity instance.  If the token is incorrect or expired
        /// then the IsAuthenticated flag will be false.  Otherwise the identity
        /// will be authenticated.
        /// </returns>
        public virtual UserIdentity AuthenticateUser(string token, UserSessionDurationType duration, String ipAddress, ExecutionResults result)
        {
            const string errorMsg = "Authentication token invalid.";
            Guid renewalToken;
            if (!Guid.TryParse(token, out renewalToken))
            {
                result.AppendError(errorMsg);
                return new UserIdentity();
            }
            var session = GetUserSession(renewalToken);
            if (session == null)
            {
                result.AppendError(errorMsg);
                return new UserIdentity();
            }
            var history = GetSessionAuthenticationHistory(session);
            if (history == null)
            {
                result.AppendError(errorMsg);
                return new UserIdentity();
            }
            if (history.IPAddress != ipAddress)
            {	//coming from a new IPAddress, token was stolen or user is coming from a new dynamic IP address (new internet connection?)
                result.AppendError(errorMsg);
                return new UserIdentity(); //force new login with password (essentially approves this new IP address)
                //WARN: is this a valid check?  Can an imposter just fake the source IP?  Could a legitimate user hop IP Addresses during a single session?
            }

            if ((DateTime.UtcNow - session.RenewedDate).Duration() > TimeSpan.FromMinutes(1))
            {   //reduce the number of writes.  Only need to know within a minute how many active users there are.  There may be many json requests for a single page in a minute.
                session.RenewedDate = DateTime.UtcNow;
                session.ExpirationDate = DateTime.UtcNow.AddMinutes(duration == UserSessionDurationType.PublicComputer ? PublicSessionDuration : ExtendedSessionDuration);
                SaveUserSession(session);
            }
            history.UserSession = session;
            return new UserIdentity(history, Name);
        }
示例#18
0
        /// <summary>
        /// updates a user's name and/or password.
        /// </summary>
        /// <param name="item">The user details to be saved.  If Password is empty is it not changed.  If specified it should be the new raw password (not a hash).</param>
        /// <param name="currentPassword">The current raw password for the user used to authenticate that the change can be made, or the current resetcode last sent to this user.</param>
        /// <param name="ipAddress">The internet address where the user is connecting from.</param>
        /// <param name="result">A ExecutionResults instance to add applicable
        /// warning and error messages to.</param>
        /// <returns>A boolean indicating success (true) or failure (false).</returns>
        public override bool UpdateUser(User item, String currentPassword, String ipAddress, ExecutionResults result)
        {
            if (item.UserID.Equals(Guid.Empty))
            {
                throw new ArgumentException("The user identity must be specified.");
            }
            var user = GetUserByID(item.UserID);
            var salt = GetUserSalt(item.UserID);

            if (user == null || salt == null)
            {
                result.AppendError("The specified user identity does not exist.");
                return(false);
            }
            if (salt.ResetCode == currentPassword)
            {
                if (salt.ResetCodeExpiration < DateTime.UtcNow)
                {
                    result.AppendError(
                        "Your password reset code has expired.  Request a new one to be sent to you, and then use it immediately.");
                    return(false);
                }
                salt.ResetCode           = null;
                salt.ResetCodeExpiration = DateTime.UtcNow;
            }
            else
            {
                var rememberMe = !cs.SecurityContextManager.IsAnonymous &&
                                 cs.SecurityContextManager.CurrentUser.Identity.Ticket.UserSession.ExpirationDate >
                                 DateTime.UtcNow.AddMinutes(PublicSessionDuration);
                if (!AuthenticateUser(name: item.Name, password: currentPassword, ipAddress: ipAddress,
                                      duration: rememberMe ? UserSessionDurationType.Extended : UserSessionDurationType.PublicComputer,
                                      allowUpdateHash: false, checkHistory: false, result: result).IsAuthenticated)
                {
                    result.AppendError("Cannot change password due to authentication error with current password.");
                    return(false);
                }
            }
            if (user.Name != item.Name)
            {   //user is changing their sign in name.  Make sure the new name is available.
                var nameExisting = GetUserByName(item.Name);
                if (nameExisting != null)
                {
                    result.AppendError("The name you specified cannot be used.");
                    return(false);
                }
                user.Name = item.Name;
            }
            if (!String.IsNullOrEmpty(item.PasswordHash))
            {
                var password = item.PasswordHash;
                //update hashes on regular basis, keeps the iterations in latest range for current users, and with a 'current' hash provider.
                HashProvider hasher = HashManager.SelectProvider();
                salt.PasswordSalt        = hasher.GetSalt();
                salt.HashGroup           = new Random(DateTime.Now.Second).Next(HashGroupMinimum, HashGroupMaximum);
                salt.HashName            = hasher.Name;
                user.PasswordHash        = hasher.Hash(salt.PasswordSalt, password, salt.HashGroup + BaseHashIterations);
                user.PasswordUpdatedDate = DateTime.UtcNow;
            }
            using (var scope = new System.Transactions.TransactionScope())
            {
                //starts as a lightweight transaction
                SaveUser(user);
                //enlists in a full distributed transaction if users and salts have different connection strings
                SaveUserSalt(salt);
            }
            return(true);
        }
示例#19
0
 /// <summary>
 /// Sends a password reset notification to the specified user.
 /// </summary>
 /// <param name="userName">The user to notify.</param>
 /// <param name="result">
 /// A placeholder for errors in the system, such as email not available now.
 /// Do not notify caller if the user does not exist, for security reasons.</param>
 /// <remarks>
 ///
 /// </remarks>
 public virtual bool NotifyPasswordReset(String userName, ExecutionResults result)
 {   //Either configure the Azure implementation, or create your own.
     result.AppendError("The forgot password functionality is not yet implemented.");
     return(false);
 }
 /// <summary>
 /// Sends a password reset notification to the specified user.
 /// </summary>
 /// <param name="userName">The user to notify.</param>
 /// <param name="result">
 /// A placeholder for errors in the system, such as email not available now.
 /// Do not notify caller if the user does not exist, for security reasons.</param>
 /// <remarks>
 /// 
 /// </remarks>
 public virtual bool NotifyPasswordReset(String userName, ExecutionResults result)
 {
     //Either configure the Azure implementation, or create your own.
     result.AppendError("The forgot password functionality is not yet implemented.");
     return false;
 }