/// <summary> /// Authenticates against the data store and returns a UserIdentity given /// a user name, and password. /// </summary> /// <param name="name">The unique user name.</param> /// <param name="password">The matching password.</param> /// <param name="ipAddress">The internet address where the user is connecting from.</param> /// <param name="duration">The amount of time that the issued token will be valid.</param> /// <param name="result">A ExecutionResults instance to add applicable /// warning and error messages to.</param> /// <returns> /// A valid user instance. If the user did not exist or the /// credentials are incorrect then the IsAuthenticated flag /// will be false. If the credentials were correct the /// IsAuthenticated flag will be true. /// </returns> public override UserIdentity AuthenticateUser( string name, string password, UserSessionDurationType duration, string ipAddress, ExecutionResults result) { return(AuthenticateUser(name: name, password: password, duration: duration, ipAddress: ipAddress, checkHistory: true, allowUpdateHash: true, result: result)); }
/// <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 virtual UserIdentity RegisterUser(User user, UserSessionDurationType duration, String ipAddress, ExecutionResults result) { var password = user.PasswordHash; //grab before it gets hashed. if (!RegisterBase(user, result)) { return(new UserIdentity()); } return(AuthenticateUser(name: user.Name, password: password, duration: duration, ipAddress: ipAddress, checkHistory: false, allowUpdateHash: false, result: result)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <summary> /// Authenticates against the data store and returns a UserIdentity given /// a user name, and password. /// </summary> /// <param name="name">The unique user name.</param> /// <param name="password">The matching password.</param> /// <param name="ipAddress">The internet address where the user is connecting from.</param> /// <param name="duration">The amount of time that the issued token will be valid.</param> /// <param name="result">A ExecutionResults instance to add applicable /// warning and error messages to.</param> /// <returns> /// A valid user instance. If the user did not exist or the /// credentials are incorrect then the IsAuthenticated flag /// will be false. If the credentials were correct the /// IsAuthenticated flag will be true. /// </returns> public static UserIdentity AuthenticateUser(string name, string password, UserSessionDurationType duration, string ipAddress, ExecutionResults result) { return(Provider.AuthenticateUser(name, password, duration, ipAddress, result)); }
/// <summary> /// Authenticates a user with the requested rule options. This internal method is called /// by the other public versions of the method. Override in a derived class if you want /// to change the rule interpretations or add new rules. /// </summary> /// <param name="name"></param> /// <param name="password"></param> /// <param name="duration"></param> /// <param name="ipAddress"></param> /// <param name="checkHistory"></param> /// <param name="allowUpdateHash"></param> /// <param name="result"></param> /// <returns></returns> protected virtual UserIdentity AuthenticateUser(string name, string password, UserSessionDurationType duration, string ipAddress, bool checkHistory, bool allowUpdateHash, ExecutionResults result) { if (checkHistory) { var recentFailures = GetRecentFailedUserNameAuthenticationCount(name); if (recentFailures > AllowedFailuresPerPeriod) return FailAuthenticateUser(name, ipAddress, result); } var user = GetUserByName(name); if (user == null) return FailAuthenticateUser(name, ipAddress, result); var salt = GetUserSalt(user.UserID); if (salt == null) return FailAuthenticateUser(name, ipAddress, result); //this should get a named hashProvider used to originally hash the password... // fallback to 'default' provider in legacy case when we didn't store the name. var hasher = !string.IsNullOrEmpty(salt.HashName) ? HashManager.Providers[salt.HashName] : HashManager.DefaultProvider; var passwordHash = hasher.Hash(salt.PasswordSalt, password, salt.HashGroup + BaseHashIterations); if (user.PasswordHash != passwordHash) return FailAuthenticateUser(name, ipAddress, result); var session = new UserSession { CreatedDate = DateTime.UtcNow, ExpirationDate = DateTime.UtcNow.AddMinutes(duration == UserSessionDurationType.PublicComputer ? PublicSessionDuration : ExtendedSessionDuration), UserID = user.UserID, RenewalToken = Guid.NewGuid() }; var history = new AuthenticationHistory { CreatedDate = session.CreatedDate, IPAddress = ipAddress, IsAuthenticated = true, UserName = name, SessionID = session.SessionID, UserSession = session }; using (var scope = new System.Transactions.TransactionScope()) { if (allowUpdateHash && (hasher.IsObsolete || user.PasswordHashUpdatedDate < DateTime.UtcNow.AddMonths(-1))) { //update hashes on regular basis, keeps the iterations in latest range for current users, and with a 'current' hash provider. 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.PasswordHashUpdatedDate = DateTime.UtcNow; //starts as a lightweight transaction SaveUser(user); //enlists in a full distributed transaction if users and salts have different connection strings SaveUserSalt(salt); } //either continues distributed transaction if applicable, // or creates a new lightweight transaction for these two commands SaveUserSession(session); InsertUserHistory(history); scope.Complete(); } return new UserIdentity(history, Name); }
/// <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 virtual UserIdentity RegisterUser(User user, UserSessionDurationType duration, String ipAddress, ExecutionResults result) { var password = user.PasswordHash; //grab before it gets hashed. if (!RegisterBase(user, result)) return new UserIdentity(); return AuthenticateUser(name: user.Name, password: password, duration: duration, ipAddress: ipAddress, checkHistory: false, allowUpdateHash: false, result: result); }
/// <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); }
/// <summary> /// Authenticates against the data store and returns a UserIdentity given /// a user name, and password. /// </summary> /// <param name="name">The unique user name.</param> /// <param name="password">The matching password.</param> /// <param name="ipAddress">The internet address where the user is connecting from.</param> /// <param name="duration">The amount of time that the issued token will be valid.</param> /// <param name="result">A ExecutionResults instance to add applicable /// warning and error messages to.</param> /// <returns> /// A valid user instance. If the user did not exist or the /// credentials are incorrect then the IsAuthenticated flag /// will be false. If the credentials were correct the /// IsAuthenticated flag will be true. /// </returns> public virtual UserIdentity AuthenticateUser( string name, string password, UserSessionDurationType duration, string ipAddress, ExecutionResults result) { return AuthenticateUser(name: name, password: password, duration: duration, ipAddress: ipAddress, checkHistory: true, allowUpdateHash: true, result: result); }
/// <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 static UserIdentity AuthenticateUser(string token, UserSessionDurationType duration, String ipAddress, ExecutionResults result) { return(Provider.AuthenticateUser(token, duration, ipAddress, result)); }
/// <summary> /// Authenticates against the data store and returns a UserIdentity given /// a user name, and password. /// </summary> /// <param name="name">The unique user name.</param> /// <param name="password">The matching password.</param> /// <param name="ipAddress">The internet address where the user is connecting from.</param> /// <param name="duration">The amount of time that the issued token will be valid.</param> /// <param name="result">A ExecutionResults instance to add applicable /// warning and error messages to.</param> /// <returns> /// A valid user instance. If the user did not exist or the /// credentials are incorrect then the IsAuthenticated flag /// will be false. If the credentials were correct the /// IsAuthenticated flag will be true. /// </returns> public abstract UserIdentity AuthenticateUser(string name, string password, UserSessionDurationType duration, string ipAddress, ExecutionResults result);
/// <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 static UserIdentity RegisterUser(User user, UserSessionDurationType duration, String ipAddress, ExecutionResults result) { return Provider.RegisterUser(user, duration, ipAddress, result); }
/// <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 static UserIdentity AuthenticateUser(string token, UserSessionDurationType duration, String ipAddress, ExecutionResults result) { return Provider.AuthenticateUser(token, duration, ipAddress, result); }
/// <summary> /// Authenticates against the data store and returns a UserIdentity given /// a user name, and password. /// </summary> /// <param name="name">The unique user name.</param> /// <param name="password">The matching password.</param> /// <param name="ipAddress">The internet address where the user is connecting from.</param> /// <param name="duration">The amount of time that the issued token will be valid.</param> /// <param name="result">A ExecutionResults instance to add applicable /// warning and error messages to.</param> /// <returns> /// A valid user instance. If the user did not exist or the /// credentials are incorrect then the IsAuthenticated flag /// will be false. If the credentials were correct the /// IsAuthenticated flag will be true. /// </returns> public static UserIdentity AuthenticateUser(string name, string password, UserSessionDurationType duration, string ipAddress, ExecutionResults result) { return Provider.AuthenticateUser(name, password, duration, ipAddress, result); }
/// <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 abstract UserIdentity RegisterUser(User user, UserSessionDurationType duration, String ipAddress, ExecutionResults result);
/// <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 abstract UserIdentity AuthenticateUser(string token, UserSessionDurationType duration, String ipAddress, ExecutionResults result);
/// <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 static UserIdentity RegisterUser(User user, UserSessionDurationType duration, String ipAddress, ExecutionResults result) { return(Provider.RegisterUser(user, duration, ipAddress, result)); }
private cs.UserIdentity AuthenticateUser(string name, string password, UserSessionDurationType duration, string ipAddress, bool checkHistory, bool allowUpdateHash, ExecutionResults result) { if (checkHistory) { var recentFailures = GetRecentFailedUserNameAuthenticationCount(name); if (recentFailures > AllowedFailuresPerPeriod) { return(FailAuthenticateUser(name, ipAddress, result)); } } User user = GetUserByName(name); if (user == null) { return(FailAuthenticateUser(name, ipAddress, result)); } UserSalt salt = GetUserSalt(user.UserID); if (salt == null) { return(FailAuthenticateUser(name, ipAddress, result)); } //this should get a named hashProvider used to originally hash the password... // fallback to 'default' provider in legacy case when we didn't store the name. HashProvider hasher = !string.IsNullOrEmpty(salt.HashName) ? HashManager.Providers[salt.HashName] : HashManager.DefaultProvider; var passwordHash = hasher.Hash(salt.PasswordSalt, password, salt.HashGroup + BaseHashIterations); if (user.PasswordHash != passwordHash) { return(FailAuthenticateUser(name, ipAddress, result)); } var session = new UserSession { CreatedDate = DateTime.UtcNow, ExpirationDate = DateTime.UtcNow.AddMinutes(duration == UserSessionDurationType.PublicComputer ? PublicSessionDuration : ExtendedSessionDuration), UserID = user.UserID, RenewalToken = Guid.NewGuid() }; var history = new AuthenticationHistory { IPAddress = ipAddress, IsAuthenticated = true, UserName = name, UserSession = session }; using (var scope = new System.Transactions.TransactionScope()) { if (allowUpdateHash && (hasher.IsObsolete || user.PasswordHashUpdatedDate < DateTime.UtcNow.AddMonths(-1))) { //update hashes on regular basis, keeps the iterations in latest range for current users, and with a 'current' hash provider. 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.PasswordHashUpdatedDate = DateTime.UtcNow; //starts as a lightweight transaction SaveUser(user); //enlists in a full distributed transaction if users and salts have different connection strings SaveUserSalt(salt); } //either continues distributed transaction if applicable, // or creates a new lightweight transaction for these two commands SaveUserSession(session); InsertUserHistory(history); } return(new cs.UserIdentity(history, this.Name)); }