public async Task <IActionResult> RecCodeTwoFactor(RecoveryCodeTwoFactorViewModel recoveryCodeTwoFactor) { try { var sequenceData = await sequenceLogic.GetSequenceDataAsync <LoginUpSequenceData>(remove : false); if (sequenceData.TwoFactorAppState != TwoFactorAppSequenceStates.RegisteredShowRecoveryCode) { throw new InvalidOperationException($"Invalid {nameof(TwoFactorAppSequenceStates)} is '{sequenceData.TwoFactorAppState}'. Required to be '{TwoFactorAppSequenceStates.RegisteredShowRecoveryCode}'."); } loginPageLogic.CheckUpParty(sequenceData); var loginUpParty = await tenantRepository.GetAsync <LoginUpParty>(sequenceData.UpPartyId); securityHeaderLogic.AddImgSrc(loginUpParty.IconUrl); securityHeaderLogic.AddImgSrcFromCss(loginUpParty.Css); if (sequenceData.TwoFactorAppRecoveryCode.IsNullOrEmpty()) { throw new InvalidOperationException($"The {nameof(RecCodeTwoFactor)} method is called with empty recovery code."); } logger.ScopeTrace(() => "Two factor recovery code post."); var authMethods = sequenceData.AuthMethods.ConcatOnce(new[] { IdentityConstants.AuthenticationMethodReferenceValues.Otp, IdentityConstants.AuthenticationMethodReferenceValues.Mfa }); var user = await accountTwoFactorLogic.SetTwoFactorAppSecretUser(sequenceData.Email, sequenceData.TwoFactorAppNewSecret, sequenceData.TwoFactorAppSecretExternalName, sequenceData.TwoFactorAppRecoveryCode); return(await loginPageLogic.LoginResponseAsync(loginUpParty, sequenceData.DownPartyLink, user, authMethods)); } catch (Exception ex) { throw new EndpointException($"Two factor registration and recovery code failed, Name '{RouteBinding.UpParty.Name}'.", ex) { RouteBinding = RouteBinding }; } }
public async Task <IActionResult> Login(LoginViewModel login) { try { var sequenceData = await sequenceLogic.GetSequenceDataAsync <LoginUpSequenceData>(remove : false); loginPageLogic.CheckUpParty(sequenceData); var loginUpParty = await tenantRepository.GetAsync <LoginUpParty>(sequenceData.UpPartyId); securityHeaderLogic.AddImgSrc(loginUpParty.IconUrl); securityHeaderLogic.AddImgSrcFromCss(loginUpParty.Css); Func <IActionResult> viewError = () => { login.SequenceString = SequenceString; login.Title = loginUpParty.Title; login.IconUrl = loginUpParty.IconUrl; login.Css = loginUpParty.Css; login.EnableCancelLogin = loginUpParty.EnableCancelLogin; login.EnableResetPassword = !loginUpParty.DisableResetPassword; login.EnableCreateUser = loginUpParty.EnableCreateUser; return(View(nameof(Login), login)); }; if (!ModelState.IsValid) { return(viewError()); } logger.ScopeTrace(() => "Login post."); try { var user = await userAccountLogic.ValidateUser(login.Email, login.Password); if (user.ConfirmAccount && !user.EmailVerified) { await accountActionLogic.SendConfirmationEmailAsync(user); } var session = await sessionLogic.GetSessionAsync(loginUpParty); if (session != null && user.UserId != session.UserId) { logger.ScopeTrace(() => "Authenticated user and session user do not match."); // TODO invalid user login throw new NotImplementedException("Authenticated user and session user do not match."); } if (!sequenceData.UserId.IsNullOrEmpty() && user.UserId != sequenceData.UserId) { logger.ScopeTrace(() => "Authenticated user and requested user do not match."); // TODO invalid user login throw new NotImplementedException("Authenticated user and requested user do not match."); } var authMethods = new[] { IdentityConstants.AuthenticationMethodReferenceValues.Pwd }; var requereMfa = loginPageLogic.GetRequereMfa(user, loginUpParty, sequenceData); if (requereMfa) { sequenceData.Email = user.Email; sequenceData.EmailVerified = user.EmailVerified; sequenceData.AuthMethods = authMethods; if (user.TwoFactorAppSecretExternalName.IsNullOrEmpty()) { sequenceData.TwoFactorAppState = TwoFactorAppSequenceStates.DoRegistration; await sequenceLogic.SaveSequenceDataAsync(sequenceData); return(HttpContext.GetUpPartyUrl(loginUpParty.Name, Constants.Routes.MfaController, Constants.Endpoints.RegisterTwoFactor, includeSequence: true).ToRedirectResult()); } else { sequenceData.TwoFactorAppSecretExternalName = user.TwoFactorAppSecretExternalName; sequenceData.TwoFactorAppState = TwoFactorAppSequenceStates.Validate; await sequenceLogic.SaveSequenceDataAsync(sequenceData); return(HttpContext.GetUpPartyUrl(loginUpParty.Name, Constants.Routes.MfaController, Constants.Endpoints.TwoFactor, includeSequence: true).ToRedirectResult()); } } else { return(await loginPageLogic.LoginResponseAsync(loginUpParty, sequenceData.DownPartyLink, user, authMethods, session : session)); } } catch (ChangePasswordException cpex) { logger.ScopeTrace(() => cpex.Message, triggerEvent: true); return(await StartChangePassword(login.Email, sequenceData)); } catch (UserObservationPeriodException uoex) { logger.ScopeTrace(() => uoex.Message, triggerEvent: true); ModelState.AddModelError(string.Empty, localizer["Your account is temporarily locked because of too many login attempts. Please wait for a while and try again."]); } catch (AccountException aex) { if (aex is InvalidPasswordException || aex is UserNotExistsException) { logger.ScopeTrace(() => aex.Message, triggerEvent: true); ModelState.AddModelError(string.Empty, localizer["Wrong email or password"]); } else { throw; } } return(viewError()); } catch (Exception ex) { throw new EndpointException($"Login failed, Name '{RouteBinding.UpParty.Name}'.", ex) { RouteBinding = RouteBinding }; } }