/// <summary> /// Validate user name and phone number before sending security code /// </summary> /// <param name="userName"></param> /// <param name="phoneNumber"></param> /// <returns></returns> public async Task <ForgotPasswordModel> ValidateUserInfoAsync(string userName, string phoneNumber) { var model = new ForgotPasswordModel { ForgotPasswordStep = ForgotPasswordStep.VerifyUser }; if (string.IsNullOrWhiteSpace(userName) || string.IsNullOrWhiteSpace(phoneNumber)) { throw new PasswordRecoverException(model.ForgotPasswordStep, "User name and phone number are required fields."); } // 1. get records from audit to check if password attapmt within the last 20 minutes is more than 5 times var attempts = await _auditService.GetAuditActivityWithinTimeAsync(userName, "/passwordRecovery", 20); // 3. insert audit log await WriteAuditLog(userName); // 2. there are 5 or more attempts so we won't send verification code if (attempts.Count >= 5) { throw new PasswordRecoverException(model.ForgotPasswordStep, "Too many attempt to recover password. Please wait for 20 minutes."); } // 4. validate phone number input var formatedPhoneNumber = string.Empty; if (_phoneService.IsValidPhoneNumber(phoneNumber, out formatedPhoneNumber)) { // validate user and phone number and send verification code var user = await _userService.GetUserByNameAsync(userName); var userPhoneNumber = user.Phones.FirstOrDefault(c => c.PhoneNumber == formatedPhoneNumber); if (userPhoneNumber != null) { // generate password recovery token var passwordRecoverToken = await _userService.GeneratePasswordResetTokenAsync(user.Id); user.PasswordRecoveryToken = passwordRecoverToken; await _userService.UpdateUserAsync(user.Id, user); // generate security code var securityCode = _phoneService.GenerateSecurityCode(); // save to our database await _phoneService.InsertSecurityCodeAsync(userPhoneNumber.Id, securityCode); // send text to user using amazon SNS await _phoneService.SendSecurityCodeAsync(formatedPhoneNumber, securityCode); // set user id and password recover token in model for session use model.UserId = user.Id; } } // 5. set next step model.ForgotPasswordStep = ForgotPasswordStep.VerifySecurityCode; return(model); }