public async Task <AuthenticationUser> AuthenticateUserAsync(string login, string password, bool ignoreInvalidLoginAttempts) { if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password)) { throw new AuthenticationException("Username and password cannot be empty", ErrorCodes.EmptyCredentials); } var user = await _userRepository.GetUserByLoginAsync(login); if (user == null) { await _log.LogInformation(WebApiConfig.LogSourceSessions, I18NHelper.FormatInvariant("Could not get user with login '{0}'", login)); throw new AuthenticationException("Invalid username or password", ErrorCodes.InvalidCredentials); } var instanceSettings = await _settingsRepository.GetInstanceSettingsAsync(); if (instanceSettings.IsSamlEnabled.GetValueOrDefault()) { // Fallback is allowed by default (value is null) if (!user.IsFallbackAllowed.GetValueOrDefault(true)) { throw new AuthenticationException("User must be authenticated via Federated Authentication mechanism", ErrorCodes.FallbackIsDisabled); } } AuthenticationStatus authenticationStatus; switch (user.Source) { case UserGroupSource.Database: authenticationStatus = AuthenticateDatabaseUser(user, password, instanceSettings.PasswordExpirationInDays); break; case UserGroupSource.Windows: if (!instanceSettings.IsLdapIntegrationEnabled) { throw new AuthenticationException(string.Format("To authenticate user with login: {0}, ldap integration must be enabled", login), ErrorCodes.LdapIsDisabled); } authenticationStatus = await _ldapRepository.AuthenticateLdapUserAsync(login, password, instanceSettings.UseDefaultConnection); break; default: throw new AuthenticationException(string.Format("Authentication provider could not be found for login: {0}", login)); } await ProcessAuthenticationStatus(authenticationStatus, user, instanceSettings, ignoreInvalidLoginAttempts); user.LicenseType = await _userRepository.GetEffectiveUserLicenseAsync(user.Id); return(user); }
public async Task <IHttpActionResult> PostRequestPasswordResetAsync([FromBody] string login) { try { var matchingSetting = await _applicationSettingsRepository.GetValue(IsPasswordRecoveryEnabledKey, false); if (!matchingSetting) { await _log.LogInformation(WebApiConfig.LogSourceUsersPasswordReset, "Password recovery is disabled"); return(Conflict()); } var instanceSettings = await _settingsRepository.GetInstanceSettingsAsync(); if (instanceSettings?.EmailSettingsDeserialized?.HostName == null) { await _log.LogInformation(WebApiConfig.LogSourceUsersPasswordReset, "Invalid instance email settings"); return(Conflict()); } var user = await _userRepository.GetUserByLoginAsync(login); if (user == null) { await _log.LogInformation(WebApiConfig.LogSourceUsersPasswordReset, "The user doesn't exist"); return(Conflict()); } bool passwordResetAllowed = await _userRepository.CanUserResetPasswordAsync(login); if (!passwordResetAllowed) { await _log.LogInformation(WebApiConfig.LogSourceUsersPasswordReset, "The user isn't allowed to reset the password"); return(Conflict()); } bool passwordRequestLimitExceeded = await _userRepository.HasUserExceededPasswordRequestLimitAsync(login); if (passwordRequestLimitExceeded) { await _log.LogInformation(WebApiConfig.LogSourceUsersPasswordReset, "Exceeded requests limit"); return(Conflict()); } bool passwordResetCooldownInEffect = await _authenticationRepository.IsChangePasswordCooldownInEffect(user); if (passwordResetCooldownInEffect) { await _log.LogInformation(WebApiConfig.LogSourceUsersPasswordReset, "Cooldown is in effect"); return(Conflict()); } var recoveryToken = SystemEncryptions.CreateCryptographicallySecureGuid(); var recoveryUrl = new Uri(Request.RequestUri, ServiceConstants.ForgotPasswordResetUrl + "/" + recoveryToken).AbsoluteUri; // decrypt the password to be set in mailBee instanceSettings.EmailSettingsDeserialized.DecryptPassword(); _emailHelper.Initialize(instanceSettings.EmailSettingsDeserialized); _emailHelper.SendEmail(user.Email, "Reset Password", $@" <html> <div>Hello {user.DisplayName}.</div> <br> <div>We have received a request to reset your password.</div> <br> <div>To confirm this password reset, visit the following link:</div> <a href='{recoveryUrl}'>Reset password</a> <br><br> <div>If you did not make this request, you can ignore this email, and no changes will be made.</div> <br> <div>If you have any questions, please contact your administrator. </div> </html>"); await _userRepository.UpdatePasswordRecoveryTokensAsync(login, recoveryToken); return(Ok()); } catch (EmailException ex) { await _log.LogError(WebApiConfig.LogSourceUsersPasswordReset, ex); return(Conflict()); } catch (Exception ex) { await _log.LogError(WebApiConfig.LogSourceUsersPasswordReset, ex); return(InternalServerError()); } }